1. 程式人生 > >貝葉斯網路-使用matlab工具集

貝葉斯網路-使用matlab工具集

提綱: 最近工作:     B-COURSE工具學習     BNT研究與學習     BNT相關實驗及結果 手動建立貝葉斯網及簡單推理        引數學習         結構學習 下一步工作安排 最近工作: 1.   B-COURSE 工具學習 B-COURSE是一個供教育者和研究者免費使用的web貝葉斯網路工具。主要分為依賴關係建模和分類器模型設計。輸入自己的研究資料,就可以利用該工具線上建立模型,並依據建立好的模型進行簡單推理。 B-COURSE要求資料格式是ASCII txt格式的離散資料,其中第一行是各種資料屬性變數,其餘各行則是採集的樣本,屬性變數值可以是字串也可以是資料,屬性變數之間用製表符分割,缺失屬性變數值用空格代替。讀入資料後,在進行結構學習前,可以手動的選擇需要考慮的資料屬性!生成過程中,可以手動確定模型,確定好模型後,可以選擇JAVA playgroud,看到一個java applet程式,可以手動輸入相應證據,從而進行簡單推理。 B-COURSE工具隱藏了資料處理,演算法實現等技術難點,所以對初學者來說,容易上手。但是卻不能夠針對不同的應用進行自主程式設計,缺乏靈活性。 2.   貝葉斯網工具箱BNT的研究與學習
基於matlab的貝葉斯網路工具箱BNT是kevin p.murphy基於matlab語言開發的關於貝葉斯網路學習的開源軟體包,提供了許多貝葉斯網路學習的底層基礎函式庫,支援多種型別的節點(概率分佈)、精確推理和近似推理、引數學習及結構學習、靜態模型和動態模型。    貝葉斯網路表示:BNT中使用矩陣方式表示貝葉斯網路,即若節點i到j有一條弧,則對應矩陣中(i,j)值為1,否則為0。    結構學習演算法函式:BNT中提供了較為豐富的結構學習函式,都有: 1.     學習樹擴充套件貝葉斯網路結構的TANC演算法learn_struct_tan(). 2.     資料完整條件下學習一般貝葉斯網路結構的K2演算法learn_struct_k2()、貪婪搜尋GS(greedy search)演算法learn_struct_gs()和爬山HC(hill climbing)演算法learn_struct_hc()等。 3.     缺失資料條件下學習一般貝葉斯網路結構的最大期望EM(expectation maximization)演算法learn_struct_EM()和馬爾科夫鏈蒙特卡羅MCMC(Markov Chain Monte Carlo)learn_struct_mcmc()演算法等。 引數學習演算法函式:
BNT中也提供了豐富的引數學習函式,都有: 1.  完整資料時,學習引數的方法主要有兩種:最大似然估計learn_params()和貝葉斯方法bayes_update_params(); 2.  資料缺失時,如果已知網路拓撲結構,用EM演算法來計算引數,倘若未知網路拓撲結構,使用結構最大期望SEM(structure EM)演算法learn_struct_SEM()。 推理機制及推理引擎:為了提高運算速度,使各種推理演算法能夠有效應用,BNT工具箱採用了引擎機制,不同的引擎根據不同的演算法來完成模型轉換、細化和求解。這個推理過程如下: BNT中提供了多種推理引擎,都有: 1.  聯合樹推理引擎jtree_inf_engine(); 2.  全域性聯合樹推理引擎global_joint_inf_engine(); 3.  信念傳播推理引擎 belprop_inf_engine(); 4.  變數消元推理引擎 var_elim_inf_engine(). 3.   使用BNT做的相關實驗及結果
u       手動建立貝葉斯網模型及簡單推理實驗: 1.     “草地潮溼原因模型”建立及推理:(全是離散變數) %建立貝葉斯網路結構並制定條件概率表 N = 4;  %四個節點 分別是cloudy,sprinkler,rain,wetgrass dag = zeros(N,N); C = 1; S = 2; R = 3; W = 4; dag(C,[R S]) = 1; %節點之間的連線關係 dag(R,W) = 1; dag(S,W) = 1; discrete_nodes = 1:N; %離散節點 node_sizes = 2*ones(1,N);%節點狀態數 bnet =mk_bnet(dag,node_sizes,'names',{'cloudy','sprinkler','rain','wetgrass'},'discrete',discrete_nodes);     bnet.CPD{C} = tabular_CPD(bnet,C,[0.5 0.5]); bnet.CPD{R} = tabular_CPD(bnet,R,[0.8 0.2 0.2 0.8]); bnet.CPD{S} = tabular_CPD(bnet,S,[0.5 0.9 0.5 0.1]); bnet.CPD{W} = tabular_CPD(bnet,W,[1 0.1 0.1 0.01 0 0.9 0.9 0.99]); %畫出建立好的貝葉斯網路 figure draw_graph(dag) %選擇jtree_inf_engine推理引擎。 engine = jtree_inf_engine(bnet); %輸入證據 evidence = cell(1,N); evidence{R} = 2; [engine, loglike] = enter_evidence(engine, evidence); %計算單個節點後驗概率,即進行推理 marg1 = marginal_nodes(engine,S); marg1.T %計算對節點聯合後驗概率 marg2 = marginal_nodes(engine,[S R W]); marg2.T %給出“軟證據”,即節點的可能分佈概率情況下的推理 evidence{R} = []; soft_evidence{R}=[0.6 0.4]; [engine, loglike] = enter_evidence(engine,evidence,'soft',soft_evidence); marg3 = marginal_nodes(engine,S); marg3.T 實驗結果: 1.貝葉斯網路                             2.單個節點後驗概率                                  3.多個節點後驗概率                        4.soft_evidence情況下的後驗概率 2.     焚化爐廠廢物排放模型建立及推理:(包含離散變數和連續變數) 這個實驗與第一個實驗不同的地方就是它所建立的貝葉斯網中的節點變數包含連續變數,在建立條件概率概率表時會有所不同,離散變數使用CPD構造器tabular_CPD,連續變數使用gaussian_CPD。這裡指給出這一部分的程式碼: bnet.CPD{B} = tabular_CPD(bnet,B,'CPT',[0.85 0.15]); bnet.CPD{F} = tabular_CPD(bnet,F,'CPT',[0.95 0.05]); bnet.CPD{W} = tabular_CPD(bnet,W,'CPT',[2/7 5/7]); bnet.CPD{E} = gaussian_CPD(bnet,E,'mean',[-3.9 -0.4 -3.2 -0.5],'cov',[0.00002 0.0001 0.00002 0.0001]); bnet.CPD{D} = gaussian_CPD(bnet,D,'mean',[6.5 6.0 7.5 7.0],'cov',[0.03 0.04 0.1 0.1],'weights',[1 1 1 1]); bnet.CPD{C} = gaussian_CPD(bnet,C,'mean',[-2 -1],'cov',[0.1 0.3]); bnet.CPD{L} = gaussian_CPD(bnet,L,'mean',3,'cov',0.25,'weights',-0.5); bnet.CPD{Min} = gaussian_CPD(bnet, Min,'mean',[0.5 -0.5],'cov',[0.01 0.005]); bnet.CPD{Mou}=gaussian_CPD(bnet,Mout,'mean',0,'cov',0.002,'weights',[1 1]); 貝葉斯網建立好後,推理部分和實驗一相似,這裡就不再討論。 實驗結果建立的貝葉斯網如下: u       引數學習實驗: 這裡使用的例子依然是“草地潮溼原因模型”。首先我先如上面實驗那樣建立好貝葉斯網bnet,並手動構造條件概率表CPT。然後使用BNT裡的函式sample_bnet(bnet)來產生nsamples個數據樣本,nsamples分別取值20,200,2000。然後,再重新建立一個不知道條件概率表的貝葉斯網bnet2(結構和bnet相同),並把得到的樣本作為訓練集代入learn_params()函式進行學習,把學習到的條件概率表CPT2與手動構造的CPT進行了比較。引數學習部分程式碼: nsamples = 20; samples = cell(N, nsamples); for i = 1:nsamples     samples(:,i) = sample_bnet(bnet); end data = cell2num(samples); bnet2 = mk_bnet(dag,node_sizes,'discrete',discrete_nodes); seed = 0; rand('state',seed); bnet2.CPD{C} = tabular_CPD(bnet2,C); bnet2.CPD{S} = tabular_CPD(bnet2,S); bnet2.CPD{R} = tabular_CPD(bnet2,R); bnet2.CPD{W} = tabular_CPD(bnet2,W); bnet3 = learn_params(bnet2,data); 實驗結果: 手動給出的CPT          nsamples=20         nsamples=200       nsamples=2000 可以看出,隨著訓練樣本數的增加,學習到的條件概率表越來越逼近於手動給出的條件概率表。 u       結構學習實驗: 這裡我主要作了兩個實驗,一個是基於上面“草地潮溼原因模型”例子,首先手動建立好貝葉斯網bnet,然後使用函式sample_bnet(bnet)產生訓練樣本,制定節點順序和最大父親節點數,代入K2演算法,進行結構學習,並比較了不同訓練樣本數(nsamples)的情況下,學習到的結構和實際結構的差異。實驗結果如下: 可以看出當樣本數達到一定的值以後,K2演算法可以很好的建立出需要的貝葉斯網路結構。 1.手動給出的結構                    2.nsamples=10 3.nsamples=20                         4.nsamples=30 另一個是根據葉進,林士敏的《基於貝葉斯網路的推理在移動客戶中流失分析中的應用》提到的使用K2演算法進行結構學習方法,通過手動構造相應資料,最後實現了該演算法,成功實現了模型的建立,而且與論文中給出的模型比較接近。實驗部分程式碼如下: n = 6; ns = [3,3,2,2,2,2]; names = {'A','B','C','D','E','class'}; A = 1; B = 2; C = 3; D = 4;E = 5; class = 6; order = [4 5 6 3 2 1]; max_fan_in = 2; result_matrix = zeros(ns(class),ns(class)); fn = 'e:/data.txt'; load(fn); data_train1 = data'; [num_attrib num_cases] = size(data_train1); data_train = zeros(num_attrib, num_cases); dag = zeros(n,n); dag = learn_struct_k2(data_train,ns,order,'max_fan_in',max_fan_in);%結構學習 bnet = mk_bnet(dag,ns); priors = 1; seed = 0; rand('state', seed); for i = 1:n     bnet.CPD{i} = tabular_CPD(bnet,i,'CPT','unif','prior_type','dirichlet','dirichlet_type','BDeu','dirichlet_weight',priors); end bnet2 = bayes_update_params(bnet,data_train);%更新條件概率表 實驗結果如下,雖然比較接近作者給出的結構,但多了幾條邊,而且因為訓練樣本是自己手動給出的,不是實際資料,所以學習到的條件概率表偏離較大。 下一步工作安排: 1.     怎樣對資料進行分類,離散化 2.     搞清楚BNT中各種推理引擎的區別,研究不完整資料下的學習演算法learn_params_em()等, 3.     深入演算法內部,分析和優化演算法 4.     結合課題作一些實驗