机器学习sklearn之贝叶斯网络实战(三)

2023-11-01

贝叶斯网络的结构学习

包括:基于评分的结构学习、基于约束的结构学习以及两者结合的结构学习方法(hybrid structure learning)。

评分函数主要分为两大类:贝叶斯评分函数、基于信息论的评分函数。

贝叶斯评分函数主要包括:K2评分、BD评分、BDeu评分

基于信息论的评分函数包括:MDL评分、BIC评分、AIC评分

基于约束(依赖分析或条件独立性测试)的方法:

基于贝叶斯评分函数的网络结构学习

import pandas as pd
import numpy as np
from pgmpy.estimators import BdeuScore, K2Score, BicScore
from pgmpy.models import BayesianModel

# 随机生成数据样本,包括三个变量,其中Z变量依赖于X,Y变量
data = pd.DataFrame(np.random.randint(0, 4, size=(5000, 2)), columns=list('XY'))
data['Z'] = data['X'] + data['Y']

bdeu = BdeuScore(data, equivalent_sample_size=5)
k2 = K2Score(data)
bic = BicScore(data)

model1 = BayesianModel([('X', 'Z'), ('Y', 'Z')])  # X -> Z <- Y
model2 = BayesianModel([('X', 'Z'), ('X', 'Y')])  # Y <- X -> Z

print("-----model1的评分-----")
print(bdeu.score(model1))
print(k2.score(model1))
print(bic.score(model1))
print("-----model2的评分-----")
print(bdeu.score(model2))
print(k2.score(model2))
print(bic.score(model2))
-----model1的评分-----
-13938.59210841577
-14329.38201774425
-14294.632146121177
-----model2的评分-----
-20900.11792216164
-20926.96302682963
-20944.16319103185

从结果中可以看出model1的评分高于model2

重要的是,这些分数可以分解,也就是说,可以在给定潜在父变量的情况下,对每个变量进行局部计算,而不依赖于网络的其他部分:

print(bdeu.local_score('Z', parents=[]))
print(bdeu.local_score('Z', parents=['X']))
print(bdeu.local_score('Z', parents=['X', 'Y']))
-9271.730661171412
-6990.193641137852
-57.119275509385034

而依据评分函数进行搜索的搜索方法常用的有穷举(5个节点以下可用)和 爬山算法(一个贪婪算法)pympy的实现如下:

穷举,5个节点以下

from pgmpy.estimators import ExhaustiveSearch

es = ExhaustiveSearch(data, scoring_method=bic)
best_model = es.estimate()
print(best_model.edges())

print("\nAll DAGs by score:")
for score, dag in reversed(es.all_scores()):
    print(score, dag.edges())
[('X', 'Z'), ('Y', 'Z')]

All DAGs by score:
-14294.632146121177 [('X', 'Z'), ('Y', 'Z')]
-14327.184045586026 [('X', 'Z'), ('X', 'Y'), ('Y', 'Z')]
-14327.184045586027 [('Z', 'X'), ('Z', 'Y'), ('X', 'Y')]
-14327.184045586027 [('Z', 'Y'), ('X', 'Z'), ('X', 'Y')]
-14327.18404558603 [('Z', 'X'), ('Z', 'Y'), ('Y', 'X')]
-14327.18404558603 [('Z', 'X'), ('Y', 'Z'), ('Y', 'X')]
-14327.18404558603 [('X', 'Z'), ('Y', 'Z'), ('Y', 'X')]
-16575.5120019897 [('Z', 'X'), ('Y', 'X')]
-16577.020154881986 [('Z', 'Y'), ('X', 'Y')]
-18663.28333516333 [('Z', 'X'), ('Z', 'Y')]
-18663.28333516333 [('Z', 'X'), ('Y', 'Z')]
-18663.28333516333 [('Z', 'Y'), ('X', 'Z')]
-20911.611291567002 [('Z', 'X')]
-20911.611291567002 [('X', 'Z')]
-20913.11944445929 [('Z', 'Y')]
-20913.11944445929 [('Y', 'Z')]
-20944.16319103185 [('X', 'Z'), ('Y', 'X')]
-20944.16319103185 [('Z', 'X'), ('X', 'Y')]
-20944.16319103185 [('X', 'Z'), ('X', 'Y')]
-20945.67134392414 [('Z', 'Y'), ('Y', 'X')]
-20945.67134392414 [('Y', 'Z'), ('Y', 'X')]
-20945.67134392414 [('X', 'Y'), ('Y', 'Z')]
-23161.447400862962 []
-23193.999300327807 [('X', 'Y')]
-23193.99930032781 [('Y', 'X')]

多个节点可使用爬山算法

from pgmpy.estimators import HillClimbSearch

# create some data with dependencies
data = pd.DataFrame(np.random.randint(0, 3, size=(2500, 8)), columns=list('ABCDEFGH'))
data['A'] += data['B'] + data['C']
data['H'] = data['G'] - data['A']

hc = HillClimbSearch(data, scoring_method=BicScore(data))
best_model = hc.estimate()
print(best_model.edges())
[('A', 'C'), ('A', 'B'), ('G', 'A'), ('G', 'H'), ('H', 'A'), ('C', 'B')]

搜索策略:

DAGS的搜索空间在变量数量上是超指数的,上面的评分函数允许局部极大值。第一个属性使穷尽搜索对于除非常小的网络之外的所有网络都是难以解决的,第二个属性禁止有效的局部优化算法总是找到最优结构。因此,识别理想的结构通常是不可处理的。尽管有这些坏消息,启发式搜索策略通常会产生好的结果。

如果只涉及几个节点(读取:小于5),则可以使用ExhaustVesearch计算每个DAG的分数,并返回最佳分数。

一旦涉及到更多的节点,就需要切换到启发式搜索。爬山搜索实现贪婪的局部搜索,从DAG开始(默认:断开DAG),并通过迭代执行最大程度提高分数的单边缘操作继续进行。一旦找到本地最大值,搜索将终止。

一个参数学习和结构学习相结合的例子,没有对连续值进行处理,想要进行学习的朋友可以对数据进行一下处理,这里只是给了个流程,其他因素均为考虑,后面会考虑用一个贝叶斯网络做一个实际的例子,敬请期待…
from pgmpy.models import BayesianModel
from pgmpy.estimators import BayesianEstimator, HillClimbSearch
import pandas as pd
import networkx as nx
from matplotlib import pyplot as plt
%matplotlib inline

import warnings
warnings.filterwarnings("ignore")

data = pd.DataFrame(np.random.randint(0, 3, size=(2500, 8)), columns=list('ABCDEFGH'))
data['A'] += data['B'] + data['C']
data['H'] = data['G'] - data['A']

# 从数据中学习DAG结构
hc = HillClimbSearch(data, scoring_method=BicScore(data))
best_model = hc.estimate()
edges = best_model.edges()
print(edges)

model = BayesianModel(edges)

# 先已知DAG结构,根据这个结构学习CPD参数
model.fit(data, estimator=BayesianEstimator)
[('A', 'C'), ('A', 'B'), ('G', 'A'), ('H', 'A'), ('H', 'G'), ('C', 'B')]
nx.draw(model,
        with_labels=True,
        node_size=1000,
        font_weight='bold',
        node_color='y',
        pos={"A": [5, 6], "C": [4, 5], "H": [6, 5], "B": [4.5, 4], "G": [5.5, 4],})

plt.text(1, 6, model.get_cpds("A"), fontsize=10, color='b')
plt.text(4.5, 4, model.get_cpds("B"), fontsize=10, color='b')
plt.text(4, 5, model.get_cpds("C"), fontsize=10, color='b')
plt.text(5.5, 4, model.get_cpds("G"), fontsize=10, color='b')
plt.text(6, 5, model.get_cpds("H"), fontsize=10, color='b')


plt.show()

print(model.cpds)

在这里插入图片描述

[<TabularCPD representing P(A:7 | G:3, H:9) at 0x1b9be308710>, <TabularCPD representing P(C:3 | A:7) at 0x1b9be3087f0>, <TabularCPD representing P(G:3 | H:9) at 0x1b9be308630>, <TabularCPD representing P(H:9) at 0x1b9be308588>, <TabularCPD representing P(B:3 | A:7, C:3) at 0x1b9be308f28>]

基于约束的结构学习

从数据构建DAG的一种不同但非常简单的方法是:

  • 使用假设检验确定数据集中的独立性
  • 根据确定的独立性构造DAG(模式)
(有条件)独立性测试

数据中的独立性可以使用chi2条件独立性测试来识别。为此,pgmpy中基于约束的估计量有一个test_conditional_independence(X, Y, Zs)-方法,对数据样本进行假设测试。它允许在给定一组变量zs的情况下检查x是否独立于y:

from pgmpy.estimators import ConstraintBasedEstimator

data = pd.DataFrame(np.random.randint(0, 3, size=(2500, 8)), columns=list('ABCDEFGH'))
data['A'] += data['B'] + data['C']
data['H'] = data['G'] - data['A']
data['E'] *= data['F']

est = ConstraintBasedEstimator(data)

print(est.test_conditional_independence('B', 'H'))          # dependent
print(est.test_conditional_independence('B', 'E'))          # independent
print(est.test_conditional_independence('B', 'H', ['A']))   # independent
print(est.test_conditional_independence('A', 'G'))          # independent
print(est.test_conditional_independence('A', 'G',  ['H']))  # dependent
(666.7771836117021, 6.639207610049184e-124, True)
(7.060271006520653, 0.7941818308528195, True)
(10.223630812021746, 0.9999999733553018, True)
(8.600668236644461, 0.9870879541949906, True)
(4612.0, 0.0, True)

test_conditional_independence()返回一个元组(chi2, p_value, sufficient_data),由计算的chi2测试统计、测试的p_value和一个启发式标志组成,该标志指示样本大小是否足够。p_value是观察计算的chi2统计(或更高的chi2值)的概率,假设x和y独立于zs。
这可用于在给定的重要程度上作出独立判断:

def is_independent(X, Y, Zs=[], significance_level=0.05):
    return est.test_conditional_independence(X, Y, Zs)[1] >= significance_level

print(is_independent('B', 'H'))
print(is_independent('B', 'E'))
print(is_independent('B', 'H', ['A']))
print(is_independent('A', 'G'))
print(is_independent('A', 'G', ['H']))
False
True
True
True
False

DAG 结构:

使用现有的独立性测试方法,我们可以通过三个步骤从数据集构造DAG:

  • 构造一个无向结构 - estimate_skeleton()

  • 定向强迫边缘以获得部分有向无环图(PDAG;DAGS的等价类)- skeleton_to_pdag()

  • 通过以某种方式保守地确定其余边的方向,将DAG图案扩展到DAG - pdag_to_dag()

skel, seperating_sets = est.estimate_skeleton(significance_level=0.01)
print("Undirected edges: ", skel.edges())

pdag = est.skeleton_to_pdag(skel, seperating_sets)
print("PDAG edges:       ", pdag.edges())

model = est.pdag_to_dag(pdag)
print("DAG edges:        ", model.edges())
Undirected edges:  [('A', 'H'), ('A', 'C'), ('A', 'B'), ('G', 'H'), ('E', 'F')]
PDAG edges:        [('A', 'H'), ('G', 'H'), ('E', 'F'), ('C', 'A'), ('F', 'E'), ('B', 'A')]
DAG edges:         [('A', 'H'), ('G', 'H'), ('C', 'A'), ('F', 'E'), ('B', 'A')]

estimate()方法提供了上述三个步骤的简写,并直接返回BayesianModel:

est.estimate(significance_level=0.01).edges()
[('A', 'H'), ('G', 'H'), ('C', 'A'), ('F', 'E'), ('B', 'A')]

可以使用estimate_from_independencies()方法从提供的一组独立项构造Baysianmodel。

from pgmpy.independencies import Independencies

ind = Independencies(['B', 'C'],
                     ['A', ['B', 'C'], 'D'])
ind = ind.closure()  # required (!) for faithfulness

model = ConstraintBasedEstimator.estimate_from_independencies("ABCD", ind)

print(model.edges())
[('A', 'D'), ('C', 'D'), ('B', 'D')]

PDAG的构建只保证在确定的一组独立性是可信的前提下工作,即存在一个与之完全对应的DAG。数据集中的虚假依赖关系可能会导致报告的独立关系违反忠实性。可能发生的情况是,估计的PDAG没有任何可靠的完成(即边缘方向,不引入新的V结构)。在这种情况下,会发出警告。

混合结构学习

MMHC算法结合了基于约束和基于分数的方法。它有两部分:

  • 使用基于约束的构造过程MMPC学习无向图框架
  • 使用基于分数的优化确定边缘方向(BDeu score + 修正的hill-climbing)

我们可以分别执行以下两个步骤:

from pgmpy.estimators import MmhcEstimator

data = pd.DataFrame(np.random.randint(0, 3, size=(2500, 8)), columns=list('ABCDEFGH'))
data['A'] += data['B'] + data['C']
data['H'] = data['G'] - data['A']
data['E'] *= data['F']

mmhc = MmhcEstimator(data)
skeleton = mmhc.mmpc()
print("Part 1) Skeleton: ", skeleton.edges())

# use hill climb search to orient the edges:
hc = HillClimbSearch(data, scoring_method=BDeuScore(data))

model = hc.estimate(tabu=10, white_list=skeleton.to_directed().edges())
print("Part 2) Model:    ", model.edges())
---------------------------------------------------------------------------

ImportError                               Traceback (most recent call last)

<ipython-input-12-a28c7de0d45e> in <module>()
----> 1 from pgmpy.estimators import MmhcEstimator
      2 
      3 data = pd.DataFrame(np.random.randint(0, 3, size=(2500, 8)), columns=list('ABCDEFGH'))
      4 data['A'] += data['B'] + data['C']
      5 data['H'] = data['G'] - data['A']


ImportError: cannot import name 'MmhcEstimator'

导包出现了问题,还在排查…

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习sklearn之贝叶斯网络实战(三) 的相关文章

  • javaScript-----数组使用字符串作为下标

    原文地址 http blog csdn net chenssy article details 7366160 首先Array是从Object那里继承下 它具备Object所有的功能和特性 下面是Object的情况 html view pl
  • TypeScript void 无返回值

    void 表示没有任何类型 当一个函数没有返回值时 通常会返回 void 有值则会返回指定值类型 void 类型 没有返回值 function showMsg void console log 显示消息 不能返回数据 会报错 return
  • Android开发从入门到精通 章节一 : 环境+IDE

    Android开发从入门到精通 章节一 环境 IDE 接下来带领大家踏入Android编程的世界 跟着我的文章一起迈入移动端开发的世界 Android官网 https developer android google cn index ht

随机推荐

  • qt 嵌入web页面_Qt与Web混合开发(一)--简单使用

    目录 放个目录方便预览 目录是从博客复制过来的 点击会跳转到博客 前言 Qt与Web混合开发 系列文章 主要讨论Qt与Web混合开发相关技术 这类技术存在适用场景 例如 Qt项目使用Web大量现成的组件 方案做功能扩展 Qt项目中性能无关
  • 创建型设计模式

    为什么说支持懒加载的双重检测不比饿汉式更优 单例模式 一个类只允许创建一个对象 或实例 即单例模式 为什么使用单例 处理资源访问冲突 表示全局唯一类 从业务概念上 有些数据在系统种只应该保存一份 就比较适合设计为单例类 实现一个单例 构造函
  • python多线程读图片

    用 threading 模块多线程读图片加速 flickr25k 和 nuswide 两个数据集的图片准备见 1 4 图像预处理程序来自 5 为了测试 写了一个叫 LazyImage 的类 和其多线程版本 LazyImage MT 代码 i
  • 常用的正则表达式汇总(最全)

    0 常用的正则表达式汇总 1 匹配中文 u4e00 u9fa5 2 英文字母 a zA Z 3 数字 0 9 4 匹配中文 英文字母和数字及下划线 u4e00 u9fa5 a zA Z0 9 同时判断输入长度 u4e00 u9fa5 a z
  • /bin/sh -e

    e含义 每条指令之后 都可以用 去判断它的返回值 零就是正确执行 非零就是执行有误 加了 e之后 就不用自己写代码去判断返回值 返回非零 脚本就会自动退出
  • JUST技术:高效时空索引揭秘及使用指南

    一 问题背景 城市中超过80 的数据都与时空有关 如加油站点 出租车轨迹 交通路况等 这些数据多为半结构化和非结构化数据 并且需要管理的数据量巨大 传统的时空数据库管理海量数据时会出现性能严重下降的情况 如带有PostGIS插件的Postg
  • 编程题中的问题 2020-9-13

    1 多行的输入输出 Scanner sc new Scanner System in int t sc nextInt 以空格和回车区别的数 String s sc nextLine 或得一行的内容 因为好久没有接触基本的输入输出了 导致今
  • STM32进阶:使用STM32驱动ST7735S(内附核心源码)

    使用STM32驱动ST7735S 内附核心源码 感觉很久很久没有来博客更新了 历经千难万阻 终于做出来了TFT显示屏的SPI驱动 这里分享以下核心源码 接下来一段时间开始准备考科一了 后面有时间了再来更新 有三种模式下的驱动 一 软件SPI
  • Linux入门篇-RHEL8的网络管理

    简介 没有比 Linux 网络管理更重要的知识 只适用于 centos rhel 系列 不低于 rhel7 版本 RHEL8网络管理服务 在早期的Linux发行版本里几乎所有的网络服务都是network服务 从RHEL7开始红帽官方建议采用
  • 如何声明静态方法 和 实现?

    如何声明静态方法 和 实现 在 C 中 声明和实现静态方法 静态成员函数 与普通成员函数有一些区别 静态方法属于类本身 而不是类的对象 因此在声明和实现时需要特殊的语法 声明静态方法 在类的声明中 通过在函数原型前面添加关键字 static
  • Spring Boot整合Elasticsearch

    Elasticsearch是一个全文搜索引擎 专门用于处理大型数据集 根据描述 自然而然使用它来存储和搜索应用程序日志 与Logstash和Kibana一起 它是强大的解决方案Elastic Stack的一部分 我之前的一些文章中已经对此进
  • 专辑一:爱之初体验(初级)

    1 Everyone Has a Story in Life 每个人都有自己的故事 A 24 year old boy seeing out from the train s windows shouted Dad look the tre
  • C++子类不能使用初始化列表来初始化父类的属性

    不能使用初始化列表来初始化父类的属性 变量赋值 函数调用要在函数内 不能使用初始化列表来初始化父类的属性 报错 xx 不是类 xxx 的非静态数据成员或基类 主要原因 子类不能使用初始化列表来初始化父类的参数或属性 报错代码 class O
  • TCP/IP详解笔记(9)

    TFTP简单文本传输协议和BOOTP引导程序协议 TFTP协议 TFTP主要使用UDP协议 当需要将程序或文件同时向许多机器下载时就需要TFTP 或者当无盘系统工作时先广播一TFTP请求 网络上的TFTP服务器就会发送响应 其中包含可执行的
  • 秩亏自由网平差的附加条件法

    目录 一 原理概述 二 案例分析 三 代码实现 四 结果展示 一 原理概述 N B T P B N B TPB N
  • 为什么学习java

    我们为什么要学习java 前几天在上课的时候 老师问了一句这样的话 为什么要学习java 好家伙 当然是热 穷 爱 的 了 当然 如此肤浅也是万万不能的 于是我陷入沉思 是啊 现在主流编程语言这么多 python c c 为什么我要学习ja
  • 使用Tensorflow实现CNN进行手写数字识别

    传统的机器学习需要使用不同的特征提取算法获取特征 深度卷积神经网络为图像分类提供了统一的解决方案 一 卷积神经网络 卷积神经网络CNN是多层神经网络的一个变种 传统的多层神经网络 当隐层数变多时 节点数目过多时就会造成参数个数过多 训练难度
  • 【STM32】基本定时器

    基于stm32f103 基于 零死角玩转STM32 F103指南者 进行学习 定时器 分类 基本定时器 通用定时器 高级定时器 功能框图 简单来说就是来自APB或者AHB的时钟 经过PSC 1到65535分频 形成时基 每经过一个时基 TI
  • Matlab R2021b下载安装教程

    1 本人使用百度网盘下载 2 准备工具 内存较大的电脑 会占用20 G 请注意 百度网盘 还需要耐心 这点我待会细说 3 Matlab R2021b下载地址私信我即可 4 开始下载 然后就是漫长的等待过程 因为我在学校宿舍 网速慢 但是总体
  • 机器学习sklearn之贝叶斯网络实战(三)

    贝叶斯网络的结构学习 包括 基于评分的结构学习 基于约束的结构学习以及两者结合的结构学习方法 hybrid structure learning 评分函数主要分为两大类 贝叶斯评分函数 基于信息论的评分函数 贝叶斯评分函数主要包括 K2评分