Алгоритм байесовской сети для чайников?
Есть ли простое и легкое объяснение алгоритма для байесовских сетей без всех напыщенных терминов? Мне не разрешено использовать библиотеки, поэтому, пожалуйста, не давайте мне библиотеку просто и скажите, как легко ее использовать.
Итак, я понимаю, что у нас есть таблицы условной вероятности (CPT), и мы должны умножить их вместе и выполнить исключение переменных, но как мне реализовать это в коде? Поэтому я попытался представить каждый CPT в виде списка словарей:
{
{
"Cavity": "True",
"own_value": "True",
"probability": 0.9
},
{
"Cavity": "True",
"own_value": "False",
"probability": 0.1
},
{
"Cavity": "False",
"own_value": "True",
"probability": 0.4
},
{
"Cavity": "False",
"own_value": "False",
"probability": 0.6
}
}
А потом вставить эти CPT в другой дикт.
Однако я не могу сказать, как умножить эти CPT и где их хранить? Например, P(A|B, C, D) * P(D|E, F) = P(A, D|B, C, E, F)
Произведение 2 CPT может привести к множителю, имеющему несколько головок, поэтому dict больше не работает...
По сути, следующий фрагмент кода - это алгоритм, который я могу придумать до сих пор, где я храню очередь узлов и передаю их в эту функцию, пока не будут найдены все известные вероятности всех узлов. И, конечно же, очередь уже выстроена в топологическом порядке, так что для родителей всегда гарантирована известная вероятность.
Но, как вы сейчас поняли, этот алгоритм может ответить только P(A = true) или P(C = false) и т. Д.
cpt = self.conditional_probabilities[nodeName] #get my cpt
for parent in self.dependencies[nodeName]:
parentProb = self.knownProbabilities[parent]
#matching of the parent and multiplying the probability
for probability in parentProb:
varName = probability
varProb = parentProb[probability]
for item in cpt:
if parent in item and (item[parent] == varName):
item["probability"] = item["probability"] * varProb
#eliminate the parent node
#some code here
#insert known probability into my known probabilities table
#e.g. insert P(A) into a dict() of P(B), P(C), ... where A, B, C are keys
nodeProbability = dict()
for item in cpt:
state = item["own_value"]
nodeProbability[state] = item["probability"]
self.knownProbabilities[nodeName] = nodeProbability
И это не может выполнять байесовские сетевые запросы, такие как P(A = true, B = false| C = false, D = "donkey", E = "cat").
Где D, E имеют домен ["осел", "кот", "собака", "мышь"], а остальные являются логическими.
TL;DR Может ли кто-нибудь объяснить мне, используя простые структуры данных (список, pq, dict и т.д.), как реализовать байесовскую сеть?
1 ответ
Это немного поздно, но для тех, кто ищет, как смоделировать байесовскую сеть и сделать вывод, вот несколько советов: На Coursera
есть очень хороший курс по вероятностным графическим моделям Дафны Коллер .
В курсе используется структура данных, называемая фактором , для хранения значений дискретного распределения вероятностей (предельное распределение или CPT).
Фактор содержит вектор для хранения значений дискретного распределения вероятностей. Кроме того, он содержит некоторые метаданные, вектор индексов переменных, содержащихся в факторе, и мощности этих переменных.
Учебное пособие, объясняющее использование факторов для моделирования байесовских сетей, можно найти здесь .
РеализацияАлгоритм исключения переменных с использованием коэффициентов можно найти здесь .
Этого нет в Python, но если вы хоть немного разбираетесь в C++, то, вероятно, сможете придумать, как реализовать это на Python. А пример использования факторов и алгоритма Variable Elimination можно посмотреть здесь:
readme, код