這不是一個完整的答案,但這裏是從wikipedia article的示例網絡的可能編碼。每個節點都有一個名稱,繼承人(兒童)的列表和概率表:
(defn node [name children fn]
{:name name :children children :table fn})
而且,這裏是構建真/假的概率小助手功能:
;; builds a true/false probability map
(defn tf [true-prob] #(if % true-prob (- 1.0 true-prob)))
以上函數返回當給定true
值(其值爲false
值)時,返回事件X=true
(對於我們編碼的X
概率變量)的概率。因爲網絡是一個DAG,所以我們可以直接引用節點(就像你提到的指針一樣),而不必關心循環引用。我們只是建立在拓撲順序圖:
(let [gw (node "grass wet" [] (fn [& {:keys [sprinkler rain]}]
(tf (cond (and sprinkler rain) 0.99
sprinkler 0.9
rain 0.8
:else 0.0))))
sk (node "sprinkler" [gw]
(fn [& {:keys [rain]}] (tf (if rain 0.01 0.4))))
rn (node "rain" [sk gw]
(constantly (tf 0.2)))]
(def dag {:nodes {:grass-wet gw :sprinkler sk :rain rn}
:joint (fn [g s r]
(*
(((:table gw) :sprinkler s :rain r) g)
(((:table sk) :rain r) s)
(((:table rn)) r)))}))
每個節點的概率表中給出的父節點的狀態的函數,並返回true
和false
值的概率。例如,
((:table (:grass-wet dag)) :sprinkler true :rain false)
...返回{:true 0.9, :false 0.09999999999999998}
。
所得關節功能結合根據此公式的概率:
P(G,S,R) = P(G|S,R).P(S|R).P(R)
而且((:joint dag) true true true)
返回0.0019800000000000004。 事實上,((:table <x>) <args>)
返回的每個值都是一個關於if
的閉包,它返回了知道概率變量狀態的概率。我們將每個封閉值分別稱爲true
/false
以提取適當的概率,並將它們相乘。
在這裏,我有點欺騙,因爲我認爲應該通過遍歷圖來計算聯合函數(在一般情況下宏可以提供幫助)。這也感覺有點混亂,特別是關於節點的狀態,這些狀態不一定只是真的和假的:在一般情況下,你最可能使用地圖。
這[SO問題] [1]可以幫助你。 [1]:http:// stackoverflow。com/questions/3127890/clojure-or-scheme-bayesian-classification-libraries/3128224#3128224 – Ankur 2012-07-14 12:39:04
Chas Emerick有一個[關於貝葉斯網絡的討論](http://blip.tv/clojure/chas-emerick-modeling-the -world-probabilistically-using-bayesian-networks-in-clojure-5961126)他給了ClojureConj。它有一些有用的信息可以回答你的一些問題。 – jszakmeister 2012-07-27 08:38:23
...現在https://www.youtube.com/watch?v=xoSFcSqo1jQ – Thumbnail 2014-02-24 11:01:14