🍠Python精神病算法和自我认知异类数学模型

🏈指点迷津 | Brief

🎯要点

🎯空间不确定性和动态相互作用自我认知异类模型 | 🎯精神病神经元算法推理 | 🎯集体信念催化个人行动力数学模型 | 🎯物种基因进化关系网络算法 | 🎯电路噪声低功耗容错解码算法

📜和-积消息传递算法用例

📜MATLAB激光通信和-积消息传递算法(Python图形模型算法)模拟调制

📜图概率模型

📜Python问题决策影响图结构化概率模型

🍪语言内容分比

🍇Python贝叶斯网络消息传递算法

首先,假设我们有一个多叉树,它是没有循环的图。例如,我们有 4 个变量“下雨”、“洒水器”、“福尔摩斯”和“华生”,有向边分别为“下雨”到“福尔摩斯”、“下雨”到“华生”和“洒水器”到“福尔摩斯”。贝叶斯网络模拟了福尔摩斯和华生是邻居的故事。一天早上,福尔摩斯走出家门,发现草地湿了。要么是下雨了,要么是他忘了关洒水器。于是他去找邻居华生,看看他的草地是否也湿了。当他看到草地确实湿了时,他很确定他没有忘了洒水器,而是下雨了。因此,信息从华生流向洒水器。这种信息流由贝叶斯网络中的消息传递算法建模。

可能性包含有关观察的信息,例如,福尔摩斯草地在未观察的情况下的可能性为 1(湿)和 1(不湿)。如果观察到湿草,可能性变为 1(湿)和 0(不湿)。这些单位向量未归一化。

L(X)=Kλ(KX)L(X)=\prod_K \lambda_{(K \rightarrow X)}

似然函数基本上是变量子级发送的所有传入消息的乘积。它返回一个似然向量,其中包含变量每个可能值的似然值。对于“下雨”,它的基数为 2,代表“是”和“否”两种状态。

如果某个变量没有子节点(因为它是图中的叶节点且未被观察到),则其似然向量将是一个单位向量,其所有可能值均为 1,例如,由于我们一开始没有观察到福尔摩斯的草,因此我们将其似然向量分别设置为 [1, 1],代表“不湿”和“湿”。

Python伪码表示:

 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)

先验是某些事件在开始时就已经知道的概率,例如,下雨的概率为 20%。如果先验未知,则使用以下公式进行计算。先验会给出相应变量的无条件概率。因此,我们还需要包括条件概率。

π(X)=WP(XW)Kϕ(KX) \pi(X)=\sum_W P(X \mid W) \prod_K \phi_{(K \rightarrow X)}

我们的例子中还给出了条件概率。公式中的“P(X|W)”对应于此。此外,我们需要使用来自所有父方的传入消息,即公式中的“ϕ”。索引显示消息方向 - 从父“K”到当前变量“X”。使用这两个部分(条件概率和来自父的消息)是因为它们都提供有关变量概率的信息。一方面,我们看到给定某些父值的概率,另一方面我们看到这些父的消息。如果没有观察,这些信息对应于父的先验。因此,这里计算“X”的边际并摆脱条件变量。

Python伪码表示:

 def priors(self):
      parents_messages = [
          p.message_to_child(self) for p in self.parents
      ]
      return reduce(np.dot, [self.m.transpose()]+parents_messages)

信念是我们观察到某些事件后的后验概率。它基本上是可能性和先验的标准化产物。

β(X)=αL(X)π(X)\beta(X)=\alpha L(X) \pi(X)

Python伪码表示:

 def belief(self):
      unnormalized = self.likelihood() * self.priors()
      normalized = unnormalized/unnormalized.sum()
      return normalized

为了计算变量的可能性,我们需要考虑来自变量子项的所有传入消息,这些消息由似然函数中的 lambda 表示。

λ(XK)=xXL(x)kK;kuP(xu)ikϕ(YX)i\lambda_{(X \rightarrow K)}=\sum_{x \in X} L(x) \sum_{k \in K ; k \in u} P(x \mid u) \prod_{i \neq k} \phi_{(Y \rightarrow X) i}

这个公式相当混乱,但看一些 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)

计算父方发送给子方的消息有两种方法。要么将从其他子方收到的所有消息与当前节点的先验相乘,要么将当前节点的信念除以相应子方发送给父方的消息。

κ(XK)=αC\Kλ(CX)π(X)=αβ(X)λ(KX)\kappa_{(X \rightarrow K)}=\alpha \prod_{C \backslash K} \lambda_{(C \rightarrow X)} \pi(X)=\alpha \frac{\beta(X)}{\lambda_{(K \rightarrow X)}}

我们认为这个公式称为 Kappa,其索引告诉我们消息的方向(从 X 到 K)。

如果我们看一下信念公式,就会发现这个公式是似然值和先验值的乘积。然而,似然值是所有传入消息的乘积。因此,信念除以来自 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()

Last updated