假设我有一个2x3矩阵A
:
1 2 3
4 5 6
和长度为4的向量y
:
0 1 2 1
以及另一个4x2矩阵B
:
0 0
1 1
2 2
3 3
我希望通过添加A
行来多次更新B
列。
要更新的A
列的索引由y
给出。
使用for
循环,可以这样做:
for i in np.arange(4):
A[:,y[i]] += B[i,:]
我使用ufunc.at
实现了这个:
np.add.at(A.T,y,B)
但是,ufunc.at
的效果几乎与使用for
循环一样糟糕。
如何获得不同的矢量化实现?
使用A[:,y]+=B.T
进行更新似乎只会更新每列一次。
答案 0 :(得分:1)
方法#1
以下是使用np.add.reduceat
-
def reduceat_app(A, y, B):
idx = y.argsort()
y0 = y[idx]
sep_idx = np.concatenate(([0], np.flatnonzero(y0[1:] != y0[:-1])+1))
A += np.add.reduceat(B[idx],sep_idx).T
方法#2
A
中的行数相对较少,我们也可以使用np.bincount
以迭代的方式为每一行执行基于bin的求和,如下所示 -
def bincount_loopy_app(A, y, B):
n = A.shape[1]
for i,a in enumerate(A):
a += np.bincount(y,B[:,i],minlength=n).astype(A.dtype)
方法#3
我们可以通过为所有元素创建2D
y
个bincount
索引/二进制网格来矢量化以前的方法,这样对于每一行,我们都会有偏移的二进制数。通过该偏移,def bincount_vectorized_app(A, y, B):
m,n = A.shape
IDs = y[:,None] + n*np.arange(B.shape[1])
vals = np.bincount(IDs.ravel(), B.ravel(), minlength=m*n)
A += vals.astype(A.dtype).reshape((m,n))
可用于以矢量化方式跨所有行执行基于bin的求和。
因此,实施将是 -
ItemTemplate