首页 > 解决方案 > 将 1d numpy 数组与一个较小的数组“相乘”并将结果相加

问题描述

对于 X 中的每 N 个元素,我想"multiply"(由于缺乏更好的描述)一个大小为 M 的 numpy 数组 X 和一个大小为 N 的较小的 numpy 数组 Y。然后,我想要sum得到的数组(几乎像 a dotproduct)。

我希望这个例子更清楚:

Example
X = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Y = [1,2,3]

Z = mymul(X, Y)
  = [0*1, 1*2, 2*3, 3*1, 4*2, 5*3, 6*1, 7*2, 8*3, 9*1]
  = [  0,   2,   6,   3,   8,  15,   6,  14,  24,   9]

result = sum(Z) = 87

X 和 Y 可以有不同的长度,并且 Y 总是小于 X,但不一定可整除(例如 M % N != 0)

我有一些解决方案,但它们很慢。我希望有一种更快的方法来做到这一点。

import numpy as np
X = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int)
Y = np.array([1,2,3], dtype=int)

# these work but are slow for large X, Y

# simple for-loop
t = 0
for i in range(len(X)):
  t += X[i] * Y[i % len(Y)]
print(t) #87

# extend Y M/N times so np.dot can be applied
Ytiled = np.tile(Y, int(np.ceil(len(X) / len(Y))))[:len(X)] 
t = np.dot(X, Ytiled)
print(t) #87

标签: pythonarraysnumpy

解决方案


调整Y到与相同的长度X,然后使用矩阵乘法 -

In [52]: np.dot(X, np.resize(Y,len(X)))
Out[52]: 87

使用的替代方法np.resize是平铺。因此,np.tile(Y,(m+n-1)//n)[:m]对于m,n = len(X), len(Y),可以替换np.resize(Y,len(X))为更快的。

另一个无需调整大小Y即可实现内存效率 -

In [79]: m,n = len(X), len(Y)

In [80]: s = n*(m//n)

In [81]: X2D = X[:s].reshape(-1,n)

In [82]: X2D.dot(Y).sum() + np.dot(X[s:],Y[:m-s])
Out[82]: 87

或者,我们可以使用np.einsum('ij,j->',X2D,Y)来替换X2D.dot(Y).sum().


推荐阅读