Образец из байесовской сети в гранате
Я построил байесовскую сеть, используя from_samples()
в гранате. Я могу получить максимально вероятные прогнозы из модели, используя model.predict()
, Я хотел знать, есть ли способ выборки из этой байесовской сети условно (или безоговорочно)? т.е. есть ли случайные выборки из сети, а не максимально вероятные прогнозы?
я смотрел на model.sample()
, но это поднимало NotImplementedError
,
Также, если это невозможно сделать с помощью pomegranate
Какие другие библиотеки отлично подходят для байесовских сетей в Python?
3 ответа
Просто чтобы прояснить приведенные выше ответы на конкретном примере, чтобы это было кому-то полезно, давайте начнем со следующего простого набора данных (с 4 переменными и 5 точками данных):
import pandas as pd
df = pd.DataFrame({'A':[0,0,0,1,0], 'B':[0,0,1,0,0], 'C':[1,1,0,0,1], 'D':[0,1,0,1,1]})
df.head()
# A B C D
#0 0 0 1 0
#1 0 0 1 1
#2 0 1 0 0
#3 1 0 0 1
#4 0 0 1 1
Теперь давайте изучим структуру байесовской сети из приведенных выше данных, используя
'exact'
алгоритм с
pomegranate
(использует DP/A* для изучения оптимальной структуры BN), используя следующий фрагмент кода
import numpy as np
from pomegranate import *
model = BayesianNetwork.from_samples(df.to_numpy(), state_names=df.columns.values, algorithm='exact')
# model.plot()
Обучаемая структура BN показана на следующем рисунке вместе с соответствующими CPT.
Как видно из приведенного выше рисунка, он точно объясняет данные. Мы можем вычислить логарифмическую вероятность данных с помощью модели следующим образом:
np.sum(model.log_probability(df.to_numpy()))
# -7.253364813857112
Как только структура BN изучена, мы можем сделать выборку из BN следующим образом:
model.sample()
# array([[0, 1, 0, 0]], dtype=int64)
В качестве примечания, если мы используем
algorithm='chow-liu'
вместо этого (который находит древовидную структуру с быстрым приближением) мы получим следующий BN:
Логарифмическая вероятность данных на этот раз равна
np.sum(model.log_probability(df.to_numpy()))
# -8.386987635761297
что указывает на алгоритм
exact
находит лучшую оценку.
model.sample()
должен был быть реализован, если я правильно вижу историю коммитов.
Вы можете взглянуть на PyMC, который также поддерживает дистрибутивные смеси. Тем не менее, я не знаю ни одного другого набора инструментов с подобным фабричным методом, как from_samples()
в гранате.
Один из способов выборки из "запеченной" байесовской сети - использование метода pred_proba. pred_proba возвращает список распределений, соответствующих каждому узлу, для которого информация не была предоставлена, при условии, что информация была предоставлена.
например:
bn = BayesianNetwork.from_samples(X)
proba = bn.predict_proba({"1":1,"2":0}) # proba will be an array of dists
samples = np.empty_like(proba)
for i in np.arange(proba.shape[0]):
for j in np.arange(proba.shape[1]):
if hasattr(proba[i][j],'sample'):
samples[i,j] = proba[i][j].sample(10000).mean() #sample and aggregate however you want
else:
samples[i,j] = proba[i][j]
pd.Series(samples,index=X.columns) #convert samples to a pandas.Series with column labels as index