我正在尝试使用BNT和MATLAB实现一个朴素贝叶斯分类器。到目前为止,我一直使用简单的tabular_CPD
变量,并对变量的概率进行“猜测”。我的原型网络目前包括以下内容:
DAG = false(5);DAG(1, 2:5) = true;bnet = mk_bnet(DAG, [2 3 4 3 3]);bnet.CPD{1} = tabular_CPD(bnet, 1, [.5 .5]);bnet.CPD{2} = tabular_CPD(bnet, 2, [.1 .345 .45 .355 .45 .3]);bnet.CPD{3} = tabular_CPD(bnet, 3, [.2 .02 .59 .2 .2 .39 .01 .39]);bnet.CPD{4} = tabular_CPD(bnet, 4, [.4 .33333 .5 .33333 .1 .33333]);bnet.CPD{5} = tabular_CPD(bnet, 5, [.5 .33333 .4 .33333 .1 .33333]);engine = jtree_inf_engine(bnet);
这里变量1是我期望的输出变量,初始设置为对任一输出类别分配0.5的概率。
变量2-5定义了我测量的特征的条件概率分布:
- 2是集群大小,范围从1到十几个或更多
- 3是一个比率,将是一个大于或等于1的实数值
- 4和5是标准偏差(实数)值(X和Y的散布)
为了对候选集群进行分类,我将所有特征测量值分成3-4个范围区间,如下所示:
... evidence = cell(1, 5); evidence{2} = sum(M > [0 2 6]); evidence{3} = sum(O > [0 1.57 2 3]); evidence{4} = sum(S(1) > [-Inf 1 2]); evidence{5} = sum(S(2) > [-Inf 0.4 0.8]); eng = enter_evidence(engine, evidence); marginals = marginal_nodes(eng, 1); e = marginals.T(1);...
考虑到我只是在猜测范围区间和概率值,这实际上效果还不错。但我认为我应该使用的是gaussian_CPD
。我认为gaussian_CPD
可以学习最佳的区间和概率(作为均值和协方差矩阵以及权重)。
我的问题是,我找不到任何关于BNTgaussian_CPD
类的简单示例。例如,我如何初始化一个gaussian_CPD
以大致与上面的tabular_CPD
变量具有相同的行为?
回答:
我最终通过在MATLAB命令提示符下实验BNT解决了这个问题。以下是我使用gaussian_CPD
节点定义我的分类器网络的方式:
DAG = false(5); DAG(1, 2:5) = truebnet = mk_bnet(DAG, [2 1 1 2 1], 'discrete', 1);bnet.CPD{1} = tabular_CPD(bnet, 1, 'prior_type', 'dirichlet');for node = 2:5 bnet.CPD{node} = gaussian_CPD(bnet, node);endbnetDAG = 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0bnet = equiv_class: [1 2 3 4 5] dnodes: 1 observed: [] names: {} hidden: [1 2 3 4 5] hidden_bitv: [1 1 1 1 1] dag: [5x5 logical] node_sizes: [2 1 1 2 1] cnodes: [2 3 4 5] parents: {[1x0 double] [1] [1] [1] [1]} members_of_equiv_class: {[1] [2] [3] [4] [5]} CPD: {[1x1 tabular_CPD] [1x1 gaussian_CPD] [1x1 gaussian_CPD] [1x1 gaussian_CPD] [1x1 gaussian_CPD]} rep_of_eclass: [1 2 3 4 5] order: [1 5 4 3 2]
为了训练它,我使用我的原始分类器帮助我标记了一组300个样本,然后简单地将其中的2/3通过训练算法运行。
bnet = learn_params(bnet, lsamples);CPD = struct(bnet.CPD{1}); % 查看CPD{1}内部dispcpt(CPD.CPT);1 : 0.6045 2 : 0.3955
dispcpt
的输出大致显示了训练集中标记样本的类别分配情况。
为了测试新的分类器,我将结果的最后1/3通过原始和新的贝叶斯网络运行。以下是我用于新网络的代码:
engine = jtree_inf_engine(bnet);evidence = cell(1, 5);tresults = cell(3, length(tsamples));tresults(3, :) = tsamples(1, :);for i = 1:length(tsamples) evidence(2:5) = tsamples(2:5, i); marginal = marginal_nodes(enter_evidence(engine, evidence), 1); tresults{1, i} = find(marginal.T == max(marginal.T)); % 通用决策点 tresults{2, i} = marginal.T(1);endtresults(:, 1:8)ans = [ 2] [ 1] [ 2] [ 2] [ 2] [ 1] [ 1] [ 1] [1.8437e-10] [0.9982] [3.3710e-05] [3.8349e-04] [2.2995e-11] [0.9997] [0.9987] [0.5116] [ 2] [ 1] [ 2] [ 2] [ 2] [ 1] [ 1] [ 2]
然后为了确定是否有任何改进,我绘制了叠加的ROC图。结果证明,我的原始网络表现得足够好,以至于很难确定使用高斯CPD的训练网络是否表现得更好。打印ROC曲线下的面积清楚地表明,新网络确实表现得略好一些。(base area
是原始网络,area
是新网络。)
conf = cell2mat(tresults(2,:));hit = cell2mat(tresults(3,:)) == 1;[~, ~, basearea] = plotROC(baseconf, basehit, 'r')hold all;[~, ~, area] = plotROC(conf, hit, 'b')hold off;basearea = 0.9371area = 0.9555
我在这里发布这个,以便下次我需要这样做时,我能够找到答案…希望其他人也可能觉得有用。