🎯要点
🎯图模型和消息传递推理算法 | 🎯消息传递推理和循环消息传递推理算法 | 🎯空间人工智能算法多维姿势估计 | 🎯超图结构解码算法量子计算 | 🎯GPU处理变分推理消息传递贝叶斯网络算法 | 🎯高斯消息传递数学形式和算法代码 | 🎯蜂窝通信Wi-Fi大量数据传输和存储信道编码解码算法 | 🎯图消息传递推理算法暴力哈希加密协议
📜消息传递推理算法用例
📜Python精神病算法和自我认知异类数学模型
🍪语言内容分比
🍇Python图消息数学
和积消息传递是一种有效应用概率的和规则和乘积规则来计算不同分布的算法。例如,如果离散概率分布
p
(
h
1
,
v
1
,
h
2
,
v
2
)
p\left(h_1, v_1, h_2, v_2\right)
p(h1,v1,h2,v2) 可以分解为
p
(
h
1
,
h
2
,
v
1
,
v
2
)
=
p
(
h
1
)
p
(
h
2
∣
h
1
)
p
(
v
1
∣
h
1
)
p
(
v
2
∣
h
2
)
p\left(h_1, h_2, v_1, v_2\right)=p\left(h_1\right) p\left(h_2 \mid h_1\right) p\left(v_1 \mid h_1\right) p\left(v_2 \mid h_2\right)
p(h1,h2,v1,v2)=p(h1)p(h2∣h1)p(v1∣h1)p(v2∣h2)
我可以通过将各项相乘并对其他变量求和来计算边际,例如
p
(
v
1
)
p\left(v_1\right)
p(v1)。
p
(
v
1
)
=
∑
h
1
,
h
2
,
v
2
p
(
h
1
)
p
(
h
2
∣
h
1
)
p
(
v
1
∣
h
1
)
p
(
v
2
∣
h
2
)
p\left(v_1\right)=\sum_{h_1, h_2, v_2} p\left(h_1\right) p\left(h_2 \mid h_1\right) p\left(v_1 \mid h_1\right) p\left(v_2 \mid h_2\right)
p(v1)=h1,h2,v2∑p(h1)p(h2∣h1)p(v1∣h1)p(v2∣h2)
有了边际,我们就可以计算
p
(
v
1
)
p\left(v_1\right)
p(v1) 和
p
(
v
1
,
v
2
)
p\left(v_1, v_2\right)
p(v1,v2) 等分布,这意味着我们还可以计算像
p
(
v
2
∣
v
1
)
p\left(v_2 \mid v_1\right)
p(v2∣v1)的项。置信传播提供了一种计算这些边际的有效方法。
在此,我将使用有向图形模型对其进行编码。
import numpy as np
from collections import namedtuple
离散条件分布 p ( v 1 ∣ h 1 ) p\left(v_1 \mid h_1\right) p(v1∣h1) 可以表示为具有两个轴的数组,例如
h
1
=
a
h
1
=
b
h
1
=
c
v
1
=
0
0.4
0.8
0.9
v
1
=
1
0.6
0.2
0.1
h_1= a h_1= b h_1= c\\ \begin{array}{llll} v_1=0 & 0.4 & 0.8 & 0.9 \\ v_1=1 & 0.6 & 0.2 & 0.1 \end{array}
h1=ah1=bh1=cv1=0v1=10.40.60.80.20.90.1
对每个变量使用一个轴可以推广到更多变量。例如,5 变量
p
(
h
5
∣
h
4
,
h
3
,
h
2
,
h
1
)
p\left(h_5 \mid h_4, h_3, h_2, h_1\right)
p(h5∣h4,h3,h2,h1) 可以用具有五个轴的数组表示。
LabeledArray = namedtuple('LabeledArray', [
'array',
'axes_labels',
])
def name_to_axis_mapping(labeled_array):
return {
name: axis
for axis, name in enumerate(labeled_array.axes_labels)
}
def other_axes_from_labeled_axes(labeled_array, axis_label):
return tuple(
axis
for axis, name in enumerate(labeled_array.axes_labels)
if name != axis_label
)
要检查多维数组是否为联合分布,整个数组的总和应该为一。要检查二维数组是否为条件分布,当所有右侧变量都已分配后,例如 p ( v 1 ∣ h 1 = a ) p\left(v_1 \mid h_1=a\right) p(v1∣h1=a),所得向量表示分布。该向量的长度应为 v 1 v_1 v1 的状态数,并且总和应为 1。在 numpy 中计算此值涉及沿与 v 1 v_1 v1 变量对应的轴求和。
再次将条件分布数组推广到多维示例,当所有右侧变量都已分配时,例如
p ( h 5 ∣ h 4 = a , h 3 = b , h 2 = a , h 1 = a ) p\left(h_5 \mid h_4=a, h_3=b, h_2=a, h_1= a\right) p(h5∣h4=a,h3=b,h2=a,h1=a),所得向量表示分布。该向量的长度应为 h 1 h_1 h1 的状态数,且总和应为 1。
def is_conditional_prob(labeled_array, var_name):
return np.all(np.isclose(np.sum(
labeled_array.array,
axis=name_to_axis_mapping(labeled_array)[var_name]
), 1.0))
def is_joint_prob(labeled_array):
return np.all(np.isclose(np.sum(labeled_array.array), 1.0))
p_v1_given_h1 = LabeledArray(np.array([[0.4, 0.8, 0.9], [0.6, 0.2, 0.1]]), ['v1', 'h1'])
p_h1 = LabeledArray(np.array([0.6, 0.3, 0.1]), ['h1'])
p_v1_given_many = LabeledArray(np.array(
[[[0.9, 0.2], [0.3, 0.2]],
[[0.1, 0.8], [0.7, 0.8]]]
), ['v1', 'h1', 'h2'])
assert is_conditional_prob(p_v1_given_h1, 'v1')
assert not is_joint_prob(p_v1_given_h1)
assert is_conditional_prob(p_h1, 'h1')
assert is_joint_prob(p_h1)
assert is_conditional_prob(p_v1_given_many, 'v1')
assert not is_joint_prob(p_v1_given_many)
在信念传播中,我还需要计算分布的乘积,例如 p ( h 2 ∣ h 1 ) p ( h 1 ) p\left(h_2\mid h_1\right) p\left(h_1\right) p(h2∣h1)p(h1)。
在此,我只需要将多维数组乘以一维数组,偶尔乘以标量。我最终实现这一点的方法是将一维数组的轴与其他分布的相应轴对齐。然后我将一维数组平铺为 p ( h 2 ∣ h 1 ) p\left(h_2 \mid h_1\right) p(h2∣h1) 的大小。这给出了联合分布 p ( h 1 , h 2 ) p\left(h_1, h_2\right) p(h1,h2)。
def tile_to_shape_along_axis(arr, target_shape, target_axis):
raw_axes = list(range(len(target_shape)))
tile_dimensions = [target_shape[a] for a in raw_axes if a != target_axis]
if len(arr.shape) == 0:
tile_dimensions += [target_shape[target_axis]]
elif len(arr.shape) == 1:
assert arr.shape[0] == target_shape[target_axis]
tile_dimensions += [1]
else:
raise NotImplementedError()
tiled = np.tile(arr, tile_dimensions)
shifted_axes = raw_axes[:target_axis] + [raw_axes[-1]] + raw_axes[target_axis:-1]
transposed = np.transpose(tiled, shifted_axes)
assert transposed.shape == target_shape
return transposed
def tile_to_other_dist_along_axis_name(tiling_labeled_array, target_array):
assert len(tiling_labeled_array.axes_labels) == 1
target_axis_label = tiling_labeled_array.axes_labels[0]
return LabeledArray(
tile_to_shape_along_axis(
tiling_labeled_array.array,
target_array.array.shape,
name_to_axis_mapping(target_array)[target_axis_label]
),
axes_labels=target_array.axes_labels
)
tiled_p_h1 = tile_to_other_dist_along_axis_name(p_h1, p_v1_given_h1)
assert np.isclose(np.sum(p_v1_given_h1.array * tiled_p_h1.array), 1.0)
图结构
该算法将计算从因子 f f f 到变量 x x x 的消息,表示为 μ f → x ( x ) \mu_{f \rightarrow x}(x) μf→x(x)。它还将计算从变量 x x x 到因子 f , μ x → f ( x ) f, \mu_{x \rightarrow f}(x) f,μx→f(x) 的值。正如图算法中常见的那样,它们是递归定义的。
变量到因子的消息由以下公式给出:
μ
x
→
f
(
x
)
=
∏
g
∈
{
n
e
(
x
)
\
f
}
μ
g
→
x
(
x
)
\mu_{x \rightarrow f}(x)=\prod_{g \in\{n e(x) \backslash f\}} \mu_{g \rightarrow x}(x)
μx→f(x)=g∈{ne(x)\f}∏μg→x(x)
其中
n
e
(
x
)
n e(x)
ne(x) 是
x
x
x 的邻居。
def _variable_to_factor_messages(variable, factor):
incoming_messages = [
_factor_to_variable_message(neighbor_factor, variable)
for neighbor_factor in variable.neighbors
if neighbor_factor.name != factor.name
]
return np.prod(incoming_messages, axis=0)