使用pgmpy构建贝叶斯信念网络时循环停滞问题求助
贝叶斯信念网络验证循环停滞问题
我用pgmpy库在Python中构建了贝叶斯信念网络(Bayesian Belief Network),数据集包含5列(Healthy、Growth、Refined、Reasoned、Accepted)共5万行,已划分为1万行训练集和剩余的验证集。网络边定义为:('Healthy', 'Refined')、('Healthy', 'Reasoned')、('Refined', 'Accepted')、('Reasoned', 'Accepted')、('Growth', 'Accepted')。
为评估网络质量,我编写循环从验证集提取Healthy、Growth、Refined、Reasoned节点的证据,预测Accepted节点值并与实际值对比,但循环总是在584次迭代后停滞,无报错且内核仍显示忙碌。以下是采用最大似然估计(Maximum likelihood)方法的简化代码,其他参数计算方法也存在相同问题:
import pandas as pd from pgmpy.base import DAG from pgmpy.models import BayesianNetwork from pgmpy.sampling import BayesianModelSampling from pgmpy.factors.discrete import State #import dataset df = pd.read_csv("C:\\Users\\puddu\\Desktop\\Tools\\Dummy.BBN\\Dummy_data_set.csv") #preliminary operation on dataset df.rename(columns = {'Q1.Healthy':'Healthy', 'Q2.Growth':'Growth', 'Q3.Refined':'Refined', 'Q9.Accepted':'Accepted', 'Q8.Reasoned':'Reasoned'}, inplace = True) nodes = ('Healthy', 'Growth', 'Refined', 'Reasoned', 'Accepted') replies = ['E','D', 'C', 'B', 'A'] edges = [('Healthy', 'Refined'), ('Healthy', 'Reasoned'), ('Refined', 'Accepted'), ('Reasoned', 'Accepted'), ('Growth', 'Accepted')] for nod in nodes: df[nod]=df[nod].astype('category') df[nod] = df[nod].cat.set_categories(replies, ordered=True) #training set definition df_train = df.head(10000).copy().reset_index(drop= True) #directed acyclic graph building dag = DAG() dag.add_edges_from(ebunch= edges) #BBN building + estimating MLE parameters model_mle = BayesianNetwork(dag) model_mle.fit(df_train) df_validation = df.iloc[(10000):(11000),].copy().reset_index(drop= True) inference_mle = BayesianModelSampling(model_mle) mle_guesses = 0 for i in range(1000): evidence = [State(var= 'Growth', state= df_validation['Growth'][i]), State(var= 'Healthy', state= df_validation['Healthy'][i]), State(var= 'Reasoned', state= df_validation['Reasoned'][i]), State(var= 'Refined', state = df_validation['Refined'][i])] mle_prediction = inference_mle.rejection_sample(size= 1, evidence = evidence, show_progress= False)['Accepted'][0] result = df_validation['Accepted'][i] if mle_prediction == result: mle_guesses+= 1 print(f"Step {i}")
问题根源与解决方法
核心问题:拒绝采样的低效性
停滞的原因是使用了rejection_sample方法。拒绝采样的逻辑是生成大量随机样本,再过滤掉不符合证据的样本——当某组证据的联合概率极低(甚至在训练集中从未出现)时,采样过程会陷入无限等待,因为很难抽到符合条件的样本。你遇到的584次迭代后停滞,大概率是第585条验证数据的证据组合在训练集中出现频率极低,导致采样无法快速找到匹配样本。
替换方案:使用精确推理
改用pgmpy的VariableElimination精确推理类,它直接计算后验概率,无需采样,速度更快且不会卡住:
from pgmpy.inference import VariableElimination # 替换采样推理为精确推理 inference_mle = VariableElimination(model_mle) mle_guesses = 0 for i in range(1000): # 用字典构造证据,比State列表更简洁 evidence = { 'Growth': df_validation['Growth'][i], 'Healthy': df_validation['Healthy'][i], 'Reasoned': df_validation['Reasoned'][i], 'Refined': df_validation['Refined'][i] } # 计算Accepted的后验概率分布 posterior = inference_mle.query(variables=['Accepted'], evidence=evidence) # 取概率最高的状态作为预测值 mle_prediction = posterior.state_names['Accepted'][posterior.values.argmax()] result = df_validation['Accepted'][i] if mle_prediction == result: mle_guesses += 1 print(f"Step {i}")
额外优化建议
- 批量处理:若验证集规模大,可按证据组合分组批量计算后验概率,避免逐行循环的开销。
- 过滤罕见组合:提前统计验证集中各证据组合的出现频率,对训练集中未出现的组合,可直接标记为未知或使用默认值,避免推理卡壳。
内容的提问来源于stack exchange,提问作者Edoardo Puddu
相关产品推荐
相关产品推荐

