def likelihood(self):
incoming_children_messages = np.array([
c.message_to_parent(self) for c in self.children
])
return incoming_children_messages.prod(axis=0)
这个公式相当混乱,但看一些 Python 代码会更容易理解。一般来说,我们从 P(X|U) 中边缘化 K,而 X 是发送者(子节点),K 是接收者(父节点),U 是 X 的所有父节点,包括 K。如果我们想象一个 X 的条件概率表,对于每个条目,我们取父节点的相应激活,并将相应的传入消息 ϕ 乘以不包含 K 本身的数值。然后,我们将该值乘以 X 的似然值。最后,我们将所有 K 值相同的值相加,剩下向量是从 X 到 K 的消息。
Python伪码表示:
def message_to_parent(self, parent):
likelihood = self.likelihood()
parents_priors = np.array([
p.message_to_child(self)
for p in self.parents if p != parent
])
parent_i = self.parents.index(parent)
stack = np.vstack([
np.dot(
self.m.take(r, axis=parent_i).transpose(),
parents_priors.prod(axis=0)
)
for r in range(parent.cardinality)
])
return np.dot(stack, likelihood)
如果我们看一下信念公式,就会发现这个公式是似然值和先验值的乘积。然而,似然值是所有传入消息的乘积。因此,信念除以来自 K 的传入消息,结果是所有传入消息(除了我们除以的消息)与先验值的乘积。这样,我们就可以解释两种计算 Kappa 的方法之间的相等性。给子方发送消息背后的直觉与给父方发送消息类似。您要考虑所有传入消息,然后将聚合发送到下一个节点。
Python伪码表示:
def message_to_child(self, child):
children_messages = []
for c in self.children:
if c != child:
children_messages.append(c.message_to_parent(self))
if len(children_messages) > 0:
unnormalized = (children_messages * self.get_priors())
unnormalized = unnormalized.prod(axis=0)
message = unnormalized/unnormalized.sum()
return message
return self.get_priors()