【问题标题】:"Multiply" 1d numpy array with a smaller one and sum the result将 1d numpy 数组与一个较小的数组“相乘”并将结果相加
【发布时间】:2019-12-17 05:25:32
【问题描述】:

我想"multiply"(因为缺乏更好的描述)一个大小为 M 的 numpy 数组 X 和一个大小为 N 的更小的 numpy 数组 Y,对于 X 中的每 N 个元素。然后,我想sum 结果数组(几乎像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

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    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()

    【讨论】:

      【解决方案2】:

      你可以使用convolvedocumentation):

      np.convolve(X, Y[::-1], 'same')[::len(Y)].sum()

      记得反转第二个数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-13
        • 1970-01-01
        • 2020-04-16
        • 2020-04-04
        • 1970-01-01
        • 2013-01-08
        相关资源
        最近更新 更多