Я пробую Байесовско-логический язык, используя следующий пример.
Я создал следующий код:
random Boolean Has_Cancer ~ BooleanDistrib(0.01);
random Boolean Detect_Cancer ~
if Has_Cancer then BooleanDistrib(0.8)
else BooleanDistrib(0.096);
obs Detect_Cancer = true;
query Has_Cancer;
Когда я запускаю его, я получаю следующие результаты:
======== Query Results =========
Number of samples: 10000
Distribution of values for Has_Cancer
false 0.9245347606896278
true 0.07546523931038764
======== Done ========
Согласно блогу true должно быть 0.0776.
Когда я запускаю 100 образцов, я получаю следующее:
======== Query Results =========
Number of samples: 100
Distribution of values for Has_Cancer
false 0.9223602484472041
true 0.077639751552795
======== Done ========
Я просто пытаюсь понять, почему.




Значения, генерируемые BLOG, являются точечными оценками после создания случайных выборок из условной вероятностной графической модели с использованием алгоритма взвешивания правдоподобия (LWA). Отличия от аналитических значений в примере поста, вероятно, связаны с шумом от процесса случайной выборки.
Что может сбивать с толку, так это то, что BLOG по умолчанию инициализирует генератор случайных чисел одним и тем же фиксированным начальным числом, и поэтому результаты вводят в заблуждение, как будто они детерминированы. Если вы добавите флаг --randomize к вызову запуска, вы увидите результаты использования других случайных семян.
Я не знаю теоретических свойств LWA (например, насколько сильно он ограничивает апостериорные средние значения), но, по крайней мере, для наивной схемы генеративной выборки средние значения, которые вы генерируете, находятся в пределах 95% ДИ. Вот пример Python, имитирующий 1000 прогонов 10 000 сэмплов.
import numpy as np
from scipy.stats import binom
np.random.seed(2019)
N, K = 10000, 1000
tp = np.empty(K)
for i in range(K):
t = binom(n=N, p=0.01).rvs()
f = N - t
detect_t = binom(n=t, p=0.800).rvs()
detect_f = binom(n=f, p=0.096).rvs()
tp[i] = detect_t / (detect_f + detect_t)
np.quantile(tp, [0.025, 0.5, 0.975])
# array([0.06177242, 0.07714902, 0.09462359])
Ага! Да, это имеет больше смысла. Спасибо.