Python 在Numpy下对两个矩阵中的所有成对行应用函数
我有两个矩阵:Python 在Numpy下对两个矩阵中的所有成对行应用函数,python,arrays,numpy,matrix,Python,Arrays,Numpy,Matrix,我有两个矩阵: import numpy as np def create(n): M = array([[ 0.33840224, 0.25420152, 0.40739624], [ 0.35087337, 0.40939274, 0.23973389], [ 0.40168642, 0.29848413, 0.29982946], [ 0.17442095, 0.5098227
import numpy as np
def create(n):
M = array([[ 0.33840224, 0.25420152, 0.40739624],
[ 0.35087337, 0.40939274, 0.23973389],
[ 0.40168642, 0.29848413, 0.29982946],
[ 0.17442095, 0.50982272, 0.31575633]])
return np.concatenate([M] * n)
A = create(1)
nof_type = A.shape[1]
I = np.eye(nof_type)
矩阵A
维度是4x3
,I是3x3
。
我想做的是
I
中的每一行计算a
中每一行的距离分数A
中的每一行,报告I
的行id和最大分数def jsd(x,y): #Jensen-shannon divergence
import warnings
warnings.filterwarnings("ignore", category = RuntimeWarning)
x = np.array(x)
y = np.array(y)
d1 = x*np.log2(2*x/(x+y))
d2 = y*np.log2(2*y/(x+y))
d1[np.isnan(d1)] = 0
d2[np.isnan(d2)] = 0
d = 0.5*np.sum(d1+d2)
return d
在实际情况下,A
的行数约为40K。所以我们真的很喜欢它的速度
使用循环方式:
def scoreit (A, I):
aoa = []
for i, x in enumerate(A):
maxscore = -10000
id = -1
for j, y in enumerate(I):
distance = jsd(x, y)
#print "\t", i, j, distance
if dist > maxscore:
maxscore = distance
id = j
#print "MAX", maxscore, id
aoa.append([maxscore,id])
return aoa
它将打印此结果:
In [56]: scoreit(A,I)
Out[56]:
[[0.54393736529629078, 1],
[0.56083720679952753, 2],
[0.49502813447483673, 1],
[0.64408263453965031, 0]]
当前时间:
In [57]: %timeit scoreit(create(1000),I)
1 loops, best of 3: 3.31 s per loop
您可以在不同的位置将
I
的尺寸扩展到3D
阵列版本,以发挥作用。我们保留了A
,因为它是一个巨大的数组,我们不希望在移动其元素时导致性能损失。此外,您还可以避免检查nan
并使用对非nan
进行求和的单个操作进行求和的昂贵工作。因此,矢量化的解决方案看起来像这样-
def jsd_vectorized(A,I):
# Perform "(x+y)" in a vectorized manner
AI = A+I[:,None]
# Calculate d1 and d2 using AI again in vectorized manner
d1 = A*np.log2(2*A/AI)
d2 = I[:,None,:]*np.log2((2*I[:,None,:])/AI)
# Use np.nansum to ignore NaNs & sum along rows to get all distances
dists = np.nansum(d1,2) + np.nansum(d2,2)
# Pack the argmax IDs and the corresponding scores as final output
ID = dists.argmax(0)
return np.vstack((0.5*dists[ID,np.arange(dists.shape[1])],ID)).T
样本运行 循环函数以运行原始函数代码-
def jsd_loopy(A,I):
dists = np.empty((A.shape[0],I.shape[0]))
for i, x in enumerate(A):
for j, y in enumerate(I):
dists[i,j] = jsd(x, y)
ID = dists.argmax(1)
return np.vstack((dists[np.arange(dists.shape[0]),ID],ID)).T
运行并验证-
In [511]: A = np.array([[ 0.33840224, 0.25420152, 0.40739624],
...: [ 0.35087337, 0.40939274, 0.23973389],
...: [ 0.40168642, 0.29848413, 0.29982946],
...: [ 0.17442095, 0.50982272, 0.31575633]])
...: nof_type = A.shape[1]
...: I = np.eye(nof_type)
...:
In [512]: jsd_loopy(A,I)
Out[512]:
array([[ 0.54393737, 1. ],
[ 0.56083721, 2. ],
[ 0.49502813, 1. ],
[ 0.64408263, 0. ]])
In [513]: jsd_vectorized(A,I)
Out[513]:
array([[ 0.54393737, 1. ],
[ 0.56083721, 2. ],
[ 0.49502813, 1. ],
[ 0.64408263, 0. ]])
运行时测试
In [514]: A = np.random.rand(1000,3)
In [515]: nof_type = A.shape[1]
...: I = np.eye(nof_type)
...:
In [516]: %timeit jsd_loopy(A,I)
1 loops, best of 3: 782 ms per loop
In [517]: %timeit jsd_vectorized(A,I)
1000 loops, best of 3: 1.17 ms per loop
In [518]: np.allclose(jsd_loopy(A,I),jsd_vectorized(A,I))
Out[518]: True
所以,
I
总是一个标识数组吗?@Divakar:没错!如果您已尝试和/或给定示例的预期输出,是否可以添加任何循环代码?我只是不确定输出的形状如何(4,2)
。另外,你能为你的实际情况列出A
和I
的形状吗?@Divakar:我用loopy way更新了。谢谢。当out=jsd\u矢量化(A,I)
时,是否有方法将索引ids=out[:,1::][/code>设置为整数?我想用它来屏蔽一个列表,比如说foo=[“a”,“b”,“c”]
@永远不要做像out[:,2]这样的事情。astype(int)
,其中out=jsd\u向量化(a,I)
?顺便问一句,为什么要这样做jsdout=jsd\u向量化(a,I)
给我这个警告//anaconda/bin/ipython:4:RuntimeWarning:ipython import start_ipython//anaconda/bin/ipython:4:RuntimeWarning:ipython import start_python的乘法中遇到无效值
@neversaint您可以使用问题中的忽略警告代码这里也有这种方法,对吗?输出不会改变,因此基本上可以忽略警告。