一,介绍
无论是朴素贝叶斯或者是半朴素贝叶斯,都是建立在所有属性独立或者仅仅只有很少的属性有依赖的前提下。但是,现实环境中很多属性之间都是相互关联、相互影响的,因而我们用一个有向无黄网来刻画属性之间的关系,并用条件概率表来描述属性的联合概率分布,这个就称为贝叶斯网络,也叫信念网。
二,从全概率和贝叶斯公式到贝叶斯网络
全概率公式:
设事件是一个完备事件组,则对于任意一个事件C,若有如下公式成立:
那么就称这个公式为全概率公式。
全概率就是表示达到某个目的,有多种方式(或者造成某种结果,有多种原因),问达到目的的概率是多少。
贝叶斯公式:
贝叶斯公式就是当已知结果,问导致这个结果的第i原因的可能性是多少?
根据以上公式,我们举例如下,看如何构建一个贝叶斯网络:
我们有如下数据:
'色泽','根蒂','敲声','纹理','头部','触感','好瓜'
青绿, 蜷缩, 浊响, 清晰, 凹陷, 硬滑, 是
乌黑, 蜷缩, 沉闷, 清晰, 凹陷, 硬滑, 是
乌黑, 蜷缩, 浊响, 清晰, 凹陷, 硬滑, 是
青绿, 蜷缩, 沉闷, 清晰, 凹陷, 硬滑, 是
浅白, 蜷缩, 浊响, 清晰, 凹陷, 硬滑, 是
青绿, 稍蜷, 浊响, 清晰, 稍凹, 软粘, 是
乌黑, 稍蜷, 浊响, 稍糊, 稍凹, 软粘, 是
乌黑, 稍蜷, 浊响, 清晰, 稍凹, 硬滑, 是
乌黑, 稍蜷, 沉闷, 稍糊, 稍凹, 硬滑, 否
青绿, 硬挺, 清脆, 清晰, 平坦, 软粘, 否
浅白, 硬挺, 清脆, 模糊, 平坦, 硬滑, 否
浅白, 蜷缩, 浊响, 模糊, 平坦, 软粘, 否
青绿, 稍蜷, 浊响, 稍糊, 凹陷, 硬滑, 否
浅白, 稍蜷, 沉闷, 稍糊, 凹陷, 硬滑, 否
乌黑, 稍蜷, 浊响, 清晰, 稍凹, 软粘, 否
浅白, 蜷缩, 浊响, 模糊, 平坦, 硬滑, 否
青绿, 蜷缩, 沉闷, 稍糊, 稍凹, 硬滑, 否
我们做出假设:1,纹理依赖于色泽;2,头部依赖于根蒂;3,触感依赖于头部和敲声;4,用所有属性综合来判断是否为好瓜。
根据上面的数据和假设,我们开始构建贝叶斯网络。贝叶斯网络的构造一般分为两步:确定网络拓扑和确定网络参数。
(1)确定网络拓扑。根据我们的假设可以画出下拓扑图:
(2)确定网络参数。根据数据计算可得带网络参数的拓扑图:
我们的测试数据为: 色泽=浅白, 根蒂=稍蜷, 敲声=沉闷, 纹理=清晰, 头部=稍凹, 触感=软粘。我们可以计算:色泽=浅白&好瓜=是的概率为1/8;根蒂=稍蜷&好瓜=是的概率为5/8;敲声=沉闷&好瓜=是的概率为2/8;纹理=清晰&色泽=浅白&好瓜=是的概率为1/1;头部=稍凹& 根蒂=稍蜷&好瓜=是的概率为3/3;触感=软粘&头部=稍凹&好瓜=是的概率为2/3;好瓜=是的概率为8/17,我们把求得的概率相乘得:0.006127。同理求得坏瓜为(纹理=清晰&色泽=浅白&好瓜=否概率为0 ,为了方便用0.01代替):0.0001936,归一化结果为:好瓜概率=0.96936,坏瓜概率= 0.03064,。所以判定测试数据为好瓜。
三,代码实现
from pgmpy.models import BayesianModel from pgmpy.factors.discrete import TabularCPD import pandas as pd import numpy as np if __name__ == '__main__': watermelon_model = BayesianModel([('Good', 'Color'), # 构建贝叶斯网络 ('Good', 'Texture'), ('Good', 'RootPedicle'), ('Good', 'Head'), ('Good', 'Stroke'), ('Good', 'Touch'), ('Color', 'Texture'), ('RootPedicle', 'Head'), ('Head', 'Touch')]) cpd_Good = TabularCPD(variable='Good', variable_card=2, # 设置参数 values=[[0.47059], [0.52941]]) cpd_Color = TabularCPD(variable='Color', variable_card=3, values=[[0.375, 0.33333], [0.5, 0.22222], [0.125, 0.44445]], evidence=['Good'], evidence_card=[2]) cpd_Texture = TabularCPD(variable='Texture', variable_card=3, values=[[1, 0.75, 1, 0.33333, 0.5, 0], [0, 0.25, 0, 0.66667, 0.5, 0.25], [0, 0, 0, 0, 0, 0.75]], evidence=['Good','Color'], evidence_card=[2,3]) cpd_RootPedicle = TabularCPD(variable='RootPedicle', variable_card=3, values=[[0.625, 0.44445], [0.375, 0.33333], [0, 0.22222]], evidence=['Good'], evidence_card=[2]) cpd_Head = TabularCPD(variable='Head', variable_card=3, values=[[1, 0, 0.33333, 0, 0.5, 0], [0, 1, 0.33333, 0.33333, 0.5, 0], [0, 0, 0.33334, 0.66667, 0, 1]], evidence=['Good', 'RootPedicle'], evidence_card=[2, 3]) cpd_Stroke = TabularCPD(variable='Stroke', variable_card=3, values=[[0.75, 0.44445], [0.25, 0.33333], [0, 0.22222]], evidence=['Good'], evidence_card=[2]) cpd_Touch = TabularCPD(variable='Touch', variable_card=2, values=[[1, 0.33333, 0.5, 1, 0.66667, 0.5], [0, 0.66667, 0.5, 0, 0.33333, 0.5]], evidence=['Good', 'Head'], evidence_card=[2, 3]) watermelon_model.add_cpds(cpd_Good,cpd_Color,cpd_Texture,cpd_RootPedicle,cpd_Head,cpd_Stroke,cpd_Touch) # 将参数添加进网络 watermelon_model.check_model() # 检查贝叶斯网络 data = pd.DataFrame([[2,0,1,0,1,1]],columns = ['Color', 'Texture', 'RootPedicle', 'Head', 'Stroke','Touch']) # 添加测试数据(色泽=浅白, 根蒂=稍蜷, 敲声=沉闷, 纹理=清晰, 头部=稍凹, 触感=软粘) reslut = watermelon_model.predict(data) # 预测 print(reslut)
结果为:Good