4

这是我必须为我的 Numpy 矩阵的每个元素计算的公式:

Mi_j = Sum_v(Av * Xi_v) + Sum_v(Bv * Wj_v) + Sum_v(Gv * Zij_v)

我真的不知道如何以 numpy 的方式对其进行编码(在 python 中它太长了):vectorized / slicing / C Api。

你有什么建议,你能给我一个简单的例子吗?我是 numpy 的新手。

@Edited 索引

  • A, B, G 是一维数组 [x,x,x]
  • Xi 和 Wj 相同(X 是矩阵,W 是矩阵)
  • Zij 是一维数组
4

2 回答 2

2

我个人认为确定代数过程更具可读性,然后使用 numpy 矩阵将它们作为标准。matrix如果您的工作完全是数学的,那么如果您使用 numpy类,将数学转换为代码会容易得多,反之亦然。

这也将帮助您避免必须仔细广播。

从...开始:

Mi_j = Sum_v(Av * Xi_v) + Sum_v(Bv * Wj_v) + Sum_v(Gv * Zij_v)

在 numpy 中变成:

M = X*A + (W*B).T + Z*G

如果将每个矩阵初始化为np.matrix,则会自动完成正确的代数。

import numpy as np
N = 5

A = np.asmatrix(np.arange(N)).T
B = np.asmatrix(np.arange(N)).T
G = np.asmatrix(np.arange(N)).T

X = np.asmatrix(np.arange(N*N).reshape(N,N))
W = np.asmatrix(np.arange(N*N).reshape(N,N))

Z = np.asmatrix(np.arange(N**3).reshape(N,N,N))

请注意,我已经transposed 了 1d 矩阵,因为默认情况下 1d 矩阵是行向量。真向量是列向量。之后,您不再需要担心广播。

M = X*A + (W*B).T + Z*G
print M
[[  90  190  290  390  490]
 [ 390  490  590  690  790]
 [ 690  790  890  990 1090]
 [ 990 1090 1190 1290 1390]
 [1290 1390 1490 1590 1690]]
于 2013-03-11T16:26:30.417 回答
1

让我们通过一个简单的例子来工作:

如果我们定义:

import numpy as np
N = 5
A = np.arange(N)
X = np.arange(N*N).reshape(N,N)

B = np.arange(N)
W = np.arange(N*N).reshape(N,N)

G = np.arange(N)
Zij = np.arange(N)

然后第一个总和Sum_v(Av * Xi_v)可以用 计算np.dot

In [54]: X
Out[54]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

In [55]: A
Out[55]: array([0, 1, 2, 3, 4])

In [56]: np.dot(X, A)
Out[56]: array([ 30,  80, 130, 180, 230])

类似地,第二个总和Sum_v(Bv * Wj_v)可以计算为:

In [58]: np.dot(W,B)
Out[58]: array([ 30,  80, 130, 180, 230])

但是,我们希望第一个和产生一个沿i-index 变化的向量,而我们希望第二个和产生一个沿j-index 变化的向量。要在 numpy 中进行安排,请使用广播:

In [59]: np.dot(X,A) + np.dot(W,B)[:,None]
Out[59]: 
array([[ 60, 110, 160, 210, 260],
       [110, 160, 210, 260, 310],
       [160, 210, 260, 310, 360],
       [210, 260, 310, 360, 410],
       [260, 310, 360, 410, 460]])

第三个和是两个一维数组之间的简单点积:

In [60]: np.dot(Zij, G)
Out[60]: 30

所以把这一切放在一起,

In [61]: M = np.dot(X,A) + np.dot(W,B)[:,None] + np.dot(Zij, G)

In [62]: M
Out[62]: 
array([[ 90, 140, 190, 240, 290],
       [140, 190, 240, 290, 340],
       [190, 240, 290, 340, 390],
       [240, 290, 340, 390, 440],
       [290, 340, 390, 440, 490]])

注意我可能误解了Zij. 尽管您说它是一维数组,但也许您的意思是对于每个 i,j它都是一维数组。然后Z将是3维的。

为了具体起见,假设 的前两个轴Z表示ij- 索引,最后一个轴Z是您希望总结的轴。

在这种情况下,您希望最后一项是np.dot(Z, G)

In [13]: Z = np.arange(N**3).reshape(N,N,-1)

In [14]: np.dot(X,A) + np.dot(W,B)[:,None] + np.dot(Z, G)
Out[14]: 
array([[  90,  190,  290,  390,  490],
       [ 390,  490,  590,  690,  790],
       [ 690,  790,  890,  990, 1090],
       [ 990, 1090, 1190, 1290, 1390],
       [1290, 1390, 1490, 1590, 1690]])
于 2013-03-11T13:24:31.780 回答