前言
在前面的时间里已经学习过了NB朴素贝叶斯算法, 又刚刚初步的学习了贝叶斯网络的一些基本概念和常用的计算方法。于是就有了上篇初识贝叶斯网络的文章,由于本人最近一直在研究学习<<贝叶斯网引论>>,也接触到了许多与贝叶斯网络相关的知识,可以说朴素贝叶斯算法这些只是我们所了解贝叶斯知识的很小的一部分。今天我要总结的学习成果就是基于NB算法的,叫做Tree Augmented Naive Bays,中文意思就是树型朴素贝叶斯算法,简单理解就是树增强型NB算法,那么问题来了,他是如何增强的呢,请继续往下正文的描述。
朴素贝叶斯算法
又得要从朴素贝叶斯算法开始讲起了,因为在前言中已经说了,TAN算法是对NB算法的增强,了解过NB算法的,一定知道NB算法在使用的时候是假设属性事件是相互独立的,而决策属性的分类结果是依赖于各个条件属性的情况的,最后选择分类属性中拥有最大后验概率的值为决策属性。比如下面这个模型可以描述一个简单的模型,
上面账号是否真实的依赖属性条件有3个,好友密度,是否使用真实头像,日志密度,假设这3个属性是相互独立的,但是事实上,在这里的头像是否真实和好友密度其实是有关联的,所以更加真实的情况是下面这张情况;
OK,TAN的出现就解决了条件间的部分属性依赖的问题。在上面的例子中我们是根据自己的主观意识判断出头像和好友密度的关系,但是在真实算法中,我们当然希望机器能够自己根据所给数据集帮我们得出这样的关系,令人高兴的事,TAN帮我们做到了这点。
TAN算法
互信息值
互信息值,在百度百科中的解释如下:
互信息值是信息论中一个有用的信息度量。它可以看出是一个信息量里包含另一个随机变量的信息量。
用图线来表示就是下面这样。
中间的I(x;y)就是互信息值,X,Y代表的2种属性。于是下面这个属性就很好理解了,互信息值越大,就代表2个属性关联性越大。互信息值的标准公式如下:
但是在TAN中会有少许的不一样,会有类变量属性的加入,因为属性之间的关联性的前提是要在某一分类属性确定下进行重新计算,不同的类属性值会有不同的属性关联性。下面是TAN中的I(x;Y)计算公式:
现在看不懂不要紧,后面在给出的程序代码中可自行调试。
算法实现过程
TAN的算法过程其实并不简单,在计算完各个属性对的互信息值之后,要进行贝叶斯网络的构建,这个是TAN中最难的部分,这个部分有下面几个阶段。
1、根据各个属性对的互信息值降序排序,依次取出其中的节点对,遵循不产生环路的原则,构造最大权重跨度树,直到选择完n-1条边为止(因为总共n个属性节点,n-1条边即可确定)。按照互信息值从高到低选择的原因就是要保留关联性更高的关联依赖性的边。
2、上述过程构成的是一个无向图,接下来为整个无向图确定边的方向。选择任意一个属性节点作为根节点,由根节点向外的方向为属性节点之间的方向。
3、为每一个属性节点添加父节点,父节点就是分类属性节点,至此贝叶斯网络结构构造完毕。
为了方便大家理解,我在网上截了几张图,下面这张是在5个属性节点中优先选择了互信息值最大的4条作为无向图:
上述带了箭头是因为,我选择的A作为树的根节点,然后方向就全部确定了,因为A直接连着4个属性节点,然后再此基础上添加父节点,就是下面这个样子了。
OK,这样应该就比较好理解了吧,如果还不理解,请仔细分析我写的程序,从代码中去理解这个过程也可以。
分类结果概率的计算
分类结果概率的计算其实非常简单,只要把查询的条件属性传入分类模型中,然后计算不同类属性下的概率值,拥有最大概率值的分类属性值为最终的分类结果。下面是计算公式,就是联合概率分布公式:
代码实现
测试数据集input.txt:
[java] view plain copy
- OutLook Temperature Humidity Wind PlayTennis
- Sunny Hot High Weak No
- Sunny Hot High Strong No
- Overcast Hot High Weak Yes
- Rainy Mild High Weak Yes
- Rainy Cool Normal Weak Yes
- Rainy Cool Normal Strong No
- Overcast Cool Normal Strong Yes
- Sunny Mild High Weak No
- Sunny Cool Normal Weak Yes
- Rainy Mild Normal Weak Yes
- Sunny Mild Normal Strong Yes
- Overcast Mild High Strong Yes
- Overcast Hot Normal Weak Yes
- Rainy Mild High Strong No
节点类Node.java:
[java] view plain copy
- package DataMining_TAN;
- import java.util.ArrayList;
- /**
- * 贝叶斯网络节点类
- *
- * @author lyq
- *
- */
- public class Node {
- //节点唯一id,方便后面节点连接方向的确定
- int id;
- // 节点的属性名称
- String name;
- // 该节点所连续的节点
- ArrayList<Node> connectedNodes;
- public Node(int id, String name) {
- this.id = id;
- this.name = name;
- // 初始化变量
- this.connectedNodes = new ArrayList<>();
- }
- /**
- * 将自身节点连接到目标给定的节点
- *
- * @param node
- * 下游节点
- */
- public void connectNode(Node node) {
- //避免连接自身
- if(this.id == node.id){
- return;
- }
- // 将节点加入自身节点的节点列表中
- this.connectedNodes.add(node);
- // 将自身节点加入到目标节点的列表中
- node.connectedNodes.add(this);
- }
- /**
- * 判断与目标节点是否相同,主要比较名称是否相同即可
- *
- *