根据位置将函数应用于 numpy 矩阵
Apply function to numpy matrix dependent on position
给定一个形状为 [m,m] 的二维 numpy 数组 X,我希望应用一个函数并获得一个新的二维 numpy 矩阵 P,其形状也为 [m,m],其得到第[i,j]个元素如下:
P[i][j] = exp (-|| X[i] - x[j] ||**2)
其中 ||.||
表示向量的标准 L-2 范数。有没有比简单的嵌套 for 循环更快的方法?
例如,
X = [[1,1,1],[2,3,4],[5,6,7]]
然后,在对角线上,访问的行将相同,并且它们的差异 norm/magnitude 将为 0。因此,
P[0][0] = P[1][1] = P[2][2] = exp (0) = 1.0
此外,
P[0][1] = exp (- || X[0] - X[1] ||**2) = exp (- || [-1,-2,-3] || ** 2) = exp (-14)
等等
使用嵌套 for 循环的最简单的解决方案如下:
import numpy as np
X = np.array([[1,2,3],[4,5,6],[7,8,9]])
P = np.zeros (shape=[len(X),len(X)])
for i in range (len(X)):
for j in range (len(X)):
P[i][j] = np.exp (- np.linalg.norm (X[i]-X[j])**2)
print (P)
这会打印:
P = [[1.00000000e+00 1.87952882e-12 1.24794646e-47]
[1.87952882e-12 1.00000000e+00 1.87952882e-12]
[1.24794646e-47 1.87952882e-12 1.00000000e+00]]
此处m为5e4量级。
如果您提供示例数组,这会更容易。您可以使用
创建大小为 [m, m, m] 的数组 Q,其中 Q[i, j, k] = X[i, k] - X[j, k]
X[None,:,:] - X[:,None,:]
此时,您正在对第三轴执行简单的 numpy 操作。
In [143]: X = np.array([[1,2,3],[4,5,6],[7,8,9]])
...: P = np.zeros (shape=[len(X),len(X)])
...: for i in range (len(X)):
...: for j in range (len(X)):
...: P[i][j] = np.exp (- np.linalg.norm (X[i]-X[j]))
...:
In [144]: P
Out[144]:
array([[1.00000000e+00, 5.53783071e-03, 3.06675690e-05],
[5.53783071e-03, 1.00000000e+00, 5.53783071e-03],
[3.06675690e-05, 5.53783071e-03, 1.00000000e+00]])
无循环版本:
In [145]: np.exp(-np.sqrt(((X[:,None,:]-X[None,:,:])**2).sum(axis=2)))
Out[145]:
array([[1.00000000e+00, 5.53783071e-03, 3.06675690e-05],
[5.53783071e-03, 1.00000000e+00, 5.53783071e-03],
[3.06675690e-05, 5.53783071e-03, 1.00000000e+00]])
我不得不删除你的 **2
以匹配值。
将 norm
应用于 3d 差异数组:
In [148]: np.exp(-np.linalg.norm(X[:,None,:]-X[None,:,:], axis=2))
Out[148]:
array([[1.00000000e+00, 5.53783071e-03, 3.06675690e-05],
[5.53783071e-03, 1.00000000e+00, 5.53783071e-03],
[3.06675690e-05, 5.53783071e-03, 1.00000000e+00]])
在 scikit
包之一(学习?)中有一个 cdist
可以更快地处理这类事情。
正如 hpaulj 提到的,cdist 做得更好。请尝试以下操作。
from scipy.spatial.distance import cdist
import numpy as np
np.exp(-cdist(X,X,'sqeuclidean'))
注意 sqeuclidean
。这意味着 scipy 不取平方根,因此您不必像上面那样使用标准进行平方。
给定一个形状为 [m,m] 的二维 numpy 数组 X,我希望应用一个函数并获得一个新的二维 numpy 矩阵 P,其形状也为 [m,m],其得到第[i,j]个元素如下:
P[i][j] = exp (-|| X[i] - x[j] ||**2)
其中 ||.||
表示向量的标准 L-2 范数。有没有比简单的嵌套 for 循环更快的方法?
例如,
X = [[1,1,1],[2,3,4],[5,6,7]]
然后,在对角线上,访问的行将相同,并且它们的差异 norm/magnitude 将为 0。因此,
P[0][0] = P[1][1] = P[2][2] = exp (0) = 1.0
此外,
P[0][1] = exp (- || X[0] - X[1] ||**2) = exp (- || [-1,-2,-3] || ** 2) = exp (-14)
等等
使用嵌套 for 循环的最简单的解决方案如下:
import numpy as np
X = np.array([[1,2,3],[4,5,6],[7,8,9]])
P = np.zeros (shape=[len(X),len(X)])
for i in range (len(X)):
for j in range (len(X)):
P[i][j] = np.exp (- np.linalg.norm (X[i]-X[j])**2)
print (P)
这会打印:
P = [[1.00000000e+00 1.87952882e-12 1.24794646e-47]
[1.87952882e-12 1.00000000e+00 1.87952882e-12]
[1.24794646e-47 1.87952882e-12 1.00000000e+00]]
此处m为5e4量级。
如果您提供示例数组,这会更容易。您可以使用
创建大小为 [m, m, m] 的数组 Q,其中 Q[i, j, k] = X[i, k] - X[j, k]X[None,:,:] - X[:,None,:]
此时,您正在对第三轴执行简单的 numpy 操作。
In [143]: X = np.array([[1,2,3],[4,5,6],[7,8,9]])
...: P = np.zeros (shape=[len(X),len(X)])
...: for i in range (len(X)):
...: for j in range (len(X)):
...: P[i][j] = np.exp (- np.linalg.norm (X[i]-X[j]))
...:
In [144]: P
Out[144]:
array([[1.00000000e+00, 5.53783071e-03, 3.06675690e-05],
[5.53783071e-03, 1.00000000e+00, 5.53783071e-03],
[3.06675690e-05, 5.53783071e-03, 1.00000000e+00]])
无循环版本:
In [145]: np.exp(-np.sqrt(((X[:,None,:]-X[None,:,:])**2).sum(axis=2)))
Out[145]:
array([[1.00000000e+00, 5.53783071e-03, 3.06675690e-05],
[5.53783071e-03, 1.00000000e+00, 5.53783071e-03],
[3.06675690e-05, 5.53783071e-03, 1.00000000e+00]])
我不得不删除你的 **2
以匹配值。
将 norm
应用于 3d 差异数组:
In [148]: np.exp(-np.linalg.norm(X[:,None,:]-X[None,:,:], axis=2))
Out[148]:
array([[1.00000000e+00, 5.53783071e-03, 3.06675690e-05],
[5.53783071e-03, 1.00000000e+00, 5.53783071e-03],
[3.06675690e-05, 5.53783071e-03, 1.00000000e+00]])
在 scikit
包之一(学习?)中有一个 cdist
可以更快地处理这类事情。
正如 hpaulj 提到的,cdist 做得更好。请尝试以下操作。
from scipy.spatial.distance import cdist
import numpy as np
np.exp(-cdist(X,X,'sqeuclidean'))
注意 sqeuclidean
。这意味着 scipy 不取平方根,因此您不必像上面那样使用标准进行平方。