机器学习:贝叶斯网浅析(附代码实现)

贝叶斯网的目的是为了从已知属性推测其他未知属性的取值。

贝叶斯网是描述属性间依赖关系的有向无环图,并使用概率分布表描述属性的联合概率分布。如下图(A指向B表示B依赖于A):
贝叶斯网由结构G和参数 Θ组成,即B=<G, Θ >。 Θ定量描述了属性间的依赖关系,即 Θ包含了每个属性条件概率表。
我们要做的就是构建一个尽量能准确反应属性间依赖关系的贝叶斯图。常使用“ 评分搜索”。
定义评分函数(稍后解释):
其中,|B|表示贝叶斯网参数的个数(所有条件概率表涉及的概率个数总和) ,f( θ )表示描述每个参数 θ 所需的字节数,对f(θ)的不同取值,可以得到AIC和BIC评分函数:
另外:
其中(样本x有d个属性):
以最开始的西瓜问题的贝叶斯网为例:
回头看评分函数:
第一项描述了编码贝叶斯网所需的字节数(越少越好),第二项LL(B|D)是贝叶斯网的对数释然,即计算贝叶斯网B对应的概率分布对数据集D描述的有多好(越大越好),于是,要构建一个好的贝叶斯网,就转变为一个优化任务:寻找一个贝叶斯网使评分函数s(B|D)最小。

然而,从所有可能的网络中寻找最优的贝叶斯网是一个NP难问题,难以快速解决,只能通过某些方法求解近似解。如K2算法(g()是评分函数):

matlab代码(仿K2算法,基于BIC准则的评分函数):
%attrs:样本属性表,行为属性(有序属性,根据经验对属性排序,最有可能被依赖的属性排在最前),列为样本
%parents_limit:每个属性最多依赖的属性个数
%attrs_valid_num:每个属性可能的取值数列表
function [parent_attrs] = createbnFunc(attrs,parents_limit,attrs_valid_num)
%属性个数
attr_num = size(attrs,1);
%为每个属性初始化空的依赖属性(父节点)
parent_attrs = {};
for i=1:attr_num,
  parent_attrs{i} = [];
endfor;
%没有任何依赖关系的评分
[min_score] = scoreFunc(parent_attrs,attrs,attrs_valid_num);
%为每个属性搜索依赖属性
for i=1:attr_num,
  %在当前属性之前的属性中寻找依赖属性,防止形成有环图
  for j=1:i-1,
    len = length(parent_attrs{i});
    if len<parents_limit,
      %设置当前属性依赖的属性
      parent_attrs{i}(len+1) = j;
      %计算评分
      [score] = scoreFunc(parent_attrs,attrs,attrs_valid_num);
      if score<min_score,
        min_score = score;
      else
        %评分变高,删掉这个依赖属性,并且结束进一步搜索当前属性的依赖属性
        parent_attrs{i}(len+1) = [];
        break;
      endif;
    else
      break;
    endif;
  endfor;
endfor;
评分函数(BIC准则):
function [score] = scoreFunc(parent_attrs,attrs,attrs_valid_num)

[rows cols] = size(attrs);
f = log(cols)/2;
b = 0;
%计算参数个数
for i=1:length(parent_attrs),
  if length(parent_attrs{i}) == 0,
    b = b + attrs_valid_num(i);
  else
    condition_num = 1;
    for j=1:length(parent_attrs{i}),
      condition_num = condition_num * attrs_valid_num(parent_attrs{i}(j));
    endfor;
    b = b + condition_num * attrs_valid_num(i);
  endif;
endfor;

%计算LL(B|D)
p = 0;
%样本循环
for i=1:cols,
  x_p = 1;
  %当前样本属性循环
  for j=1:rows,
    %没有依赖属性
    if length(parent_attrs{j}) == 0,
      count = 0;
      for k=1:cols,
        if isequal(attrs{j,k},attrs{j,i}),
          count ++;
        endif;
      endfor;
      x_p = x_p * count / cols;
    else%有依赖属性
      c_count = 0;
      count = 0;
      for k=1:cols,
        %满足条件的样本标记
        flag = true;
        for m=1:length(parent_attrs{j}),
          if ~isequal(attrs{parent_attrs{j}(m),i},attrs{parent_attrs{j}(m),k}),
            flag = false;
            break;
          endif;
        endfor;
        if flag,
          c_count ++;
        endif;
        if flag&&isequal(attrs{j,i},attrs{j,k}),
          count ++;
        endif;
      endfor;
      if c_count == 0,
        x_p = 0;
        break;
      else
        x_p = x_p * count / c_count;
      endif;
    endif;
  endfor;
  if x_p~=0,
    p = p + log(x_p);
  endif;
endfor;
%BIC准则评分
score = f * b - p;
多多指教~

参考资料:周志华《机器学习》
参考博文:


猜你喜欢

转载自blog.csdn.net/weixin_35732969/article/details/80989537