我正在尝试基于矩阵编写快速、优化的代码,最近我发现einsum是一种实现显著加速的工具。
是否可以使用此方法有效地设置多维数组的对角线,或者只能返回数据?
在我的问题中,我试图通过将每个正方形( N )矩阵中的列相加来设置方阵的对角(shape: M)。
我目前(慢的,基于循环的)解决方案是:
# Build dummy array
dimx = 2 # Dimension x (likely to be < 100)
dimy = 3 # Dimension y (likely to be between 2 and 10)
M = np.random.randint(low=1, high=9, size=[dimx, dimy, dimy])
# Blank the diagonals so we can see the intended effect
np.fill_diagonal(M[0], 0)
np.fill_diagonal(M[1], 0)
# Compute diagonals based on summing columns
diags = np.einsum('ijk->ik', M)
# Set the diagonal for each matrix
# THIS IS LOW. CAN IT BE IMPROVED?
for i in range(len(M)):
np.fill_diagonal(M[i], diags[i])
# Print result
M
请把这个改进一下好吗?np.fill_diagonal似乎不接受非平方矩阵(因此迫使我的循环解决方案)。也许einsum也能帮上忙?
发布于 2017-05-15 23:07:50
一种方法是重塑为2D
,在ncols+1
的步骤中设置带有对角线值的列。重塑创建了一个视图,因此允许我们直接访问这些对角线位置。因此,实施将是-
s0,s1,s2 = M.shape
M.reshape(s0,-1)[:,::s2+1] = diags
发布于 2017-05-16 00:24:22
如果您执行np.source(np.fill_diagonal)
,您将看到在2d的情况下,它使用了一种“跨步”方法
if a.ndim == 2:
step = a.shape[1] + 1
end = a.shape[1] * a.shape[1]
a.flat[:end:step] = val
@Divakar's
解决方案将此应用到你的3d案例中,在二维上“平放”。
可以将列与M.sum(axis=1)
相加。虽然我隐约记得一些发现einsum
实际上要快一点的时间。sum
有点传统。
有人已经要求有能力在einsum
中扩展维度,但我不认为这种情况会发生。
https://stackoverflow.com/questions/43990071
复制相似问题