文章目录
pgmpy
Parameter learning: Given a set of data samples and a DAG that captures the dependencies between the variables, estimate the (conditional) probability distributions of the individual variables.
Structure learning: Given a set of data samples, estimate a DAG that captures the dependencies between the variables.
pgmpy.org
github.com/pgmpy/pgmpy_notebook/blob/master/blob/master/notebooks
代码记录
包
"""
学习链接 :
http://pgmpy.org/
https://github.com/pgmpy/pgmpy_notebook/blob/master/notebooks/9.%20Learning%20Bayesian%20Networks%20from%20Data.ipynb
"""
# ====================BN模型=========================
# 贝叶斯模型
from pgmpy.models import BayesianModel
# ====================参数学习=========================
# 参数估计
from pgmpy.estimators import ParameterEstimator
# MLE参数估计
from pgmpy.estimators import MaximumLikelihoodEstimator
# Bayesian参数估计
from pgmpy.estimators import BayesianEstimator
# ====================结构学习=========================
# ========评分搜索=========================
# 评分
from pgmpy.estimators import BdeuScore, K2Score, BicScore
# 穷举搜索
from pgmpy.estimators import ExhaustiveSearch
# 爬山搜索
from pgmpy.estimators import HillClimbSearch
# ======== 约束 =========================
from pgmpy.estimators import ConstraintBasedEstimator
# 独立性
from pgmpy.independencies import Independencies
# ======== 混合 =========================
from pgmpy.estimators import MmhcEstimator
# ==================== 通用库 =========================
import pandas as pd
import numpy as np
parameter Learning
def parameterLearning():
data = pd.DataFrame(data={'fruit': ["banana", "apple", "banana", "apple", "banana","apple", "banana",
"apple", "apple", "apple", "banana", "banana", "apple", "banana",],
'tasty': ["yes", "no", "yes", "yes", "yes", "yes", "yes",
"yes", "yes", "yes", "yes", "no", "no", "no"],
'size': ["large", "large", "large", "small", "large", "large", "large",
"small", "large", "large", "large", "large", "small", "small"]})
model = BayesianModel([('fruit', 'tasty'), ('size', 'tasty')]) # fruit -> tasty <- size
print("========================================================")
pe = ParameterEstimator(model, data)
print("\n", pe.state_counts('fruit')) # unconditional
print("\n", pe.state_counts('size')) # unconditional
print("\n", pe.state_counts('tasty')) # conditional on fruit and size
print("========================================================")
mle = MaximumLikelihoodEstimator(model, data)
print(mle.estimate_cpd('fruit')) # unconditional
print(mle.estimate_cpd('tasty')) # conditional
print("========================================================")
est = BayesianEstimator(model, data)
print(est.estimate_cpd('tasty', prior_type='BDeu', equivalent_sample_size=10))
# Setting equivalent_sample_size to 10 means
# that for each parent configuration, we add the equivalent of 10 uniform samples
# (here: +5 small bananas that are tasty and +5 that aren't).
print("========================================================")
# Calibrate all CPDs of `model` using MLE:
model.fit(data, estimator=MaximumLikelihoodEstimator)
print("========================================================")
# generate data
data = pd.DataFrame(np.random.randint(low=0, high=2, size=(5000, 4)), columns=['A', 'B', 'C', 'D'])
model = BayesianModel([('A', 'B'), ('A', 'C'), ('D', 'C'), ('B', 'D')])
model.fit(data, estimator=BayesianEstimator, prior_type="BDeu") # default equivalent_sample_size=5
for cpd in model.get_cpds():
print(cpd)
structural Learning with Score
def structuralLearning_Score():
"""
score-based structure learning
constraint-based structure learning
The combination of both techniques allows further improvement:
hybrid structure learning
"""
print("===================基于评分=================================")
# create random data sample with 3 variables, where Z is dependent on 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))
print("==========基于评分===局部评分==============")
print(bdeu.local_score('Z', parents=[]))
print(bdeu.local_score('Z', parents=['X']))
print(bdeu.local_score('Z', parents=['X', 'Y']))
print("==========基于评分===穷举搜索算法==============")
# 穷举搜索(计算困难),启发式搜索
es = ExhaustiveSearch(data, scoring_method=bic)
# 获取分数最高的分数
best_model = es.estimate()
print(best_model.edges())
print("\n 遍历所有的分数:")
for score, dag in reversed(es.all_scores()):
print(score, dag.edges())
print("==========基于评分===爬山搜索算法==============")
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())
structural Learning with Constraint
def structuralLearning_Constraint():
print("===================基于约束=================================")
# Identify independencies in the data set using hypothesis tests
# Construct DAG (pattern) according to identified independencies
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']
# Independencies in the data can be identified
# using chi2 conditional independence tests
est = ConstraintBasedEstimator(data)
print("==========基于约束===条件独立测试===============")
# test_conditional_independence(X, Y, Zs)
# 判断X,Y在Zs的条件下是否条件独立
# check if X is independent from Y given a set of variables Zs:
print(est.test_conditional_independence('B', 'H')) # dependent False
print(est.test_conditional_independence('B', 'E')) # independent True
print(est.test_conditional_independence('B', 'H', ['A'])) # independent True
print(est.test_conditional_independence('A', 'G')) # independent True
print(est.test_conditional_independence('A', 'G', ['H'])) # dependent False
print("==========基于约束===DAG构建=================")
"""
1. 构造一个无向骨架——estimate_skeleton()
2. 利用强迫边进行定向,得到部分有向无环图(PDAG;- skeleton_to_pdag()
3. 通过以某种方式保守地定向剩余的边,将DAG模式扩展到DAG—pdag_to_dag()
Step 1.&2. form the so-called PC algorithm.
PDAGs are DirectedGraphs, that may contain both-way edges,
to indicate that the orientation for the edge is not determined.
"""
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())
print("==========基于约束===DAG构建===estimate方法=================")
# he estimate()-method provides a shorthand for the three steps above
# and directly returns a BayesianModel
# 三步并作一步,直接返回一个网络结构
print(est.estimate(significance_level=0.01).edges())
print("==========基于约束===DAG构建===从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())
structural Learning with Hybrid
def structuralLearning_Hybrid():
"""
MMHC算法[3]结合了基于约束和基于分数的方法。它有两部分:
1. 使用基于约束的构造过程MMPC学习无向图骨架
2. 基于分数的优化(BDeu分数+修改爬山)
"""
print("===================混合方法=================================")
# 实验数据生成
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_length=10, white_list=skeleton.to_directed().edges())
print("Part 2) Model: ", model.edges())
print("===================两步划为一步=================================")
# MmhcEstimator.estimate(self, scoring_method=None, tabu_length=10,
# significance_level=0.01)
# mmhc.estimate(scoring_method=BdeuScore(data),tabu_length=10)
mian
if __name__ == "__main__":
parameterLearning()
structuralLearning_Score()
structuralLearning_Constraint()
structuralLearning_Hybrid()
运行展示
参数学习
1 ============参数估计=================================================
1 ========state_counts 统计信息=======
fruit
apple 7
banana 7
size
large 10
small 4
fruit apple banana
size large small large small
tasty
no 1.0 1.0 1.0 1.0
yes 3.0 2.0 5.0 0.0
1 ========MLE估计CPD==按变量===========
+---------------+-----+
| fruit(apple) | 0.5 |
+---------------+-----+
| fruit(banana) | 0.5 |
+---------------+-----+
+------------+--------------+--------------------+---------------------+---------------+
| fruit | fruit(apple) | fruit(apple) | fruit(banana) | fruit(banana) |
+------------+--------------+--------------------+---------------------+---------------+
| size | size(large) | size(small) | size(large) | size(small) |
+------------+--------------+--------------------+---------------------+---------------+
| tasty(no) | 0.25 | 0.3333333333333333 | 0.16666666666666666 | 1.0 |
+------------+--------------+--------------------+---------------------+---------------+
| tasty(yes) | 0.75 | 0.6666666666666666 | 0.8333333333333334 | 0.0 |
+------------+--------------+--------------------+---------------------+---------------+
1 ========贝叶斯估计CPD==按变量========
+------------+---------------------+--------------------+--------------------+---------------------+
| fruit | fruit(apple) | fruit(apple) | fruit(banana) | fruit(banana) |
+------------+---------------------+--------------------+--------------------+---------------------+
| size | size(large) | size(small) | size(large) | size(small) |
+------------+---------------------+--------------------+--------------------+---------------------+
| tasty(no) | 0.34615384615384615 | 0.4090909090909091 | 0.2647058823529412 | 0.6428571428571429 |
+------------+---------------------+--------------------+--------------------+---------------------+
| tasty(yes) | 0.6538461538461539 | 0.5909090909090909 | 0.7352941176470589 | 0.35714285714285715 |
+------------+---------------------+--------------------+--------------------+---------------------+
1 ========fit函数估计===所有变量=======
1 ===================================
+------+----------+
| A(0) | 0.506593 |
+------+----------+
| A(1) | 0.493407 |
+------+----------+
+------+--------------------+---------------------+
| A | A(0) | A(1) |
+------+--------------------+---------------------+
| B(0) | 0.5183395779925064 | 0.48076533711277586 |
+------+--------------------+---------------------+
| B(1) | 0.4816604220074936 | 0.5192346628872241 |
+------+--------------------+---------------------+
+------+--------------------+--------------------+---------------------+--------------------+
| A | A(0) | A(0) | A(1) | A(1) |
+------+--------------------+--------------------+---------------------+--------------------+
| D | D(0) | D(1) | D(0) | D(1) |
+------+--------------------+--------------------+---------------------+--------------------+
| C(0) | 0.5160626836434867 | 0.5142942227516378 | 0.49917576756645377 | 0.4964179104477612 |
+------+--------------------+--------------------+---------------------+--------------------+
| C(1) | 0.4839373163565132 | 0.4857057772483621 | 0.5008242324335462 | 0.5035820895522388 |
+------+--------------------+--------------------+---------------------+--------------------+
+------+--------------------+--------------------+
| B | B(0) | B(1) |
+------+--------------------+--------------------+
| D(0) | 0.5029982010793523 | 0.4918114639504693 |
+------+--------------------+--------------------+
| D(1) | 0.4970017989206476 | 0.5081885360495306 |
+------+--------------------+--------------------+
评分搜索
2 ===================基于评分=================================
2 ==========基于评分===model1===============
-13939.038934816337
-14329.822136429982
-14295.079563299281
2 ==========基于评分===model2===============
-20900.389985754824
-20927.22925737244
-20944.436530518695
2 ==========基于评分===局部评分==============
-9232.535088735991
-6990.879293129073
-57.11895038935745
2 ==========基于评分===穷举搜索算法==============
[('X', 'Z'), ('Y', 'Z')]
遍历所有的分数:
-14295.079563299281 [('X', 'Z'), ('Y', 'Z')]
-14326.77068416731 [('X', 'Y'), ('Z', 'X'), ('Z', 'Y')]
-14326.770684167312 [('Y', 'X'), ('Z', 'X'), ('Z', 'Y')]
-14326.770684167312 [('Y', 'Z'), ('Y', 'X'), ('Z', 'X')]
-14326.770684167312 [('X', 'Z'), ('Y', 'Z'), ('Y', 'X')]
-14326.770684167312 [('X', 'Y'), ('X', 'Z'), ('Z', 'Y')]
-14326.770684167312 [('X', 'Y'), ('X', 'Z'), ('Y', 'Z')]
-16536.707465219723 [('X', 'Y'), ('Z', 'Y')]
-16537.846854154086 [('Y', 'X'), ('Z', 'X')]
-18701.669239663883 [('Z', 'X'), ('Z', 'Y')]
-18701.669239663883 [('Y', 'Z'), ('Z', 'X')]
-18701.669239663886 [('X', 'Z'), ('Z', 'Y')]
-20911.606020716295 [('Z', 'Y')]
-20911.606020716295 [('Y', 'Z')]
-20912.745409650663 [('Z', 'X')]
-20912.745409650663 [('X', 'Z')]
-20943.297141584328 [('Y', 'X'), ('Z', 'Y')]
-20943.297141584328 [('Y', 'Z'), ('Y', 'X')]
-20943.297141584328 [('X', 'Y'), ('Y', 'Z')]
-20944.436530518695 [('X', 'Z'), ('Y', 'X')]
-20944.436530518695 [('X', 'Y'), ('Z', 'X')]
-20944.436530518695 [('X', 'Y'), ('X', 'Z')]
-23122.682190703075 []
-23154.373311571104 [('Y', 'X')]
-23154.373311571104 [('X', 'Y')]
2 ==========基于评分===爬山搜索算法==============
[('A', 'H'), ('A', 'C'), ('A', 'B'), ('C', 'B'), ('G', 'H')]
约束
3 ===================基于约束=================================
3 ==========基于约束===条件独立测试===============
False
True
True
True
False
3 ==========基于约束===DAG构建=================
Undirected edges: [('A', 'B'), ('A', 'C'), ('A', 'H'), ('E', 'F'), ('G', 'H')]
PDAG edges: [('A', 'H'), ('B', 'A'), ('C', 'A'), ('E', 'F'), ('F', 'E'), ('G', 'H')]
DAG edges: [('A', 'H'), ('B', 'A'), ('C', 'A'), ('F', 'E'), ('G', 'H')]
3 ==========基于约束===DAG构建===estimate方法=================
[('A', 'H'), ('B', 'A'), ('C', 'A'), ('F', 'E'), ('G', 'H')]
3 ==========基于约束===DAG构建===从independencies中学习======
[('A', 'D'), ('B', 'D'), ('C', 'D')]
混合
4 ===================混合方法=================================
Part 1) Skeleton: [('A', 'H'), ('A', 'C'), ('E', 'F'), ('G', 'H')]
Part 2) Model: [('A', 'C'), ('E', 'F'), ('H', 'A'), ('H', 'G')]
4 ===================两步划为一步=================================
。。。