deflikelihood(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伪码表示:
defmessage_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 inrange(parent.cardinality) ])return np.dot(stack, likelihood)
如果我们看一下信念公式,就会发现这个公式是似然值和先验值的乘积。然而,似然值是所有传入消息的乘积。因此,信念除以来自 K 的传入消息,结果是所有传入消息(除了我们除以的消息)与先验值的乘积。这样,我们就可以解释两种计算 Kappa 的方法之间的相等性。给子方发送消息背后的直觉与给父方发送消息类似。您要考虑所有传入消息,然后将聚合发送到下一个节点。
Python伪码表示:
defmessage_to_child(self,child): children_messages = []for c in self.children:if c != child: children_messages.append(c.message_to_parent(self))iflen(children_messages)>0: unnormalized = (children_messages * self.get_priors()) unnormalized = unnormalized.prod(axis=0) message = unnormalized/unnormalized.sum()return messagereturn self.get_priors()