使用 numpy 广播计算序列的部分和

Using numpy broadcasting to compute the partial sum of a series

我必须计算以下总和,S 定义为:

我试过以下功能:

import numpy as np
a = np.array([0.4,2.6,3, 1.2, 3.4])
b = np.array([-5,7,2,1.1,1.8])
c = np.array([3.3,30,15,0.4,28])
t = np.linspace(0, np.pi, 600)
def S(t):
  return np.sum([a[i]*np.cos(b[i]*t + c[i]) for i in range(5)], axis=0)

这很好用。但我想知道是否有纯 numpy 版本使用广播而不依赖 Python 的列表理解?

我试过:

def S(t):
  return np.sum(a*np.cos(b*t + c), axis=0)

当我计算 S(t) 时,出现以下错误:

...
ValueError: operands could not be broadcast together with shapes (5,) (600,)

我怎样才能让它正常工作?

我想我通过向 abc 数组添加新轴找到了答案,如下所示:

def S(t):
   return np.sum(a[:,None]*cos(b[:,None]*t + c[:,None]), axis=0)

def S(t):
   return np.sum(a[:,np.newaxis]*cos(b[:,np.newaxis]*t + c[:,np.newaxis]), axis=0)

编辑:

正如 Michael 在评论中所建议的,更好的解决方案是向 t 添加一个新轴(请注意,在这种情况下,求和是在 axis=1 上进行的):

def S(t):
   return np.sum(a*cos(b*t[:,None] + c), axis=1)

怎么做?

对于广播,您需要在您希望具有“复制”值的维度中。所以它是这样工作的:

import numpy as np

a = np.array([0.4,2.6,3, 1.2, 3.4])
b = np.array([-5,7,2,1.1,1.8])
c = np.array([3.3,30,15,0.4,28])
t = np.linspace(0, np.pi, 600).reshape(-1,1)

np.sum(a*np.cos(b*t+c), axis=1)

如何检查你是否做对了?

你可以做的一个巧妙的技巧是将 sympy.symbols 放入你的数组中并做同样的事情。然后你得到它为你计算的公式:

import sympy

a = np.array(sympy.symbols([f"a{i}" for i in range(5)]))
b = np.array(sympy.symbols([f"b{i}" for i in range(5)]))
c = np.array(sympy.symbols([f"c{i}" for i in range(5)]))
t = np.array(sympy.symbols([f"t{i}" for i in range(10)])).reshape(-1,1)

cos = np.vectorize(sympy.cos)
np.sum(a*cos(b*t+c), axis=1)

这给了你

array([a0*cos(b0*t0 + c0) + a1*cos(b1*t0 + c1) + a2*cos(b2*t0 + c2) + a3*cos(b3*t0 + c3) + a4*cos(b4*t0 + c4),
       a0*cos(b0*t1 + c0) + a1*cos(b1*t1 + c1) + a2*cos(b2*t1 + c2) + a3*cos(b3*t1 + c3) + a4*cos(b4*t1 + c4),
       a0*cos(b0*t2 + c0) + a1*cos(b1*t2 + c1) + a2*cos(b2*t2 + c2) + a3*cos(b3*t2 + c3) + a4*cos(b4*t2 + c4),
       a0*cos(b0*t3 + c0) + a1*cos(b1*t3 + c1) + a2*cos(b2*t3 + c2) + a3*cos(b3*t3 + c3) + a4*cos(b4*t3 + c4),
       a0*cos(b0*t4 + c0) + a1*cos(b1*t4 + c1) + a2*cos(b2*t4 + c2) + a3*cos(b3*t4 + c3) + a4*cos(b4*t4 + c4),
       a0*cos(b0*t5 + c0) + a1*cos(b1*t5 + c1) + a2*cos(b2*t5 + c2) + a3*cos(b3*t5 + c3) + a4*cos(b4*t5 + c4),
       a0*cos(b0*t6 + c0) + a1*cos(b1*t6 + c1) + a2*cos(b2*t6 + c2) + a3*cos(b3*t6 + c3) + a4*cos(b4*t6 + c4),
       a0*cos(b0*t7 + c0) + a1*cos(b1*t7 + c1) + a2*cos(b2*t7 + c2) + a3*cos(b3*t7 + c3) + a4*cos(b4*t7 + c4),
       a0*cos(b0*t8 + c0) + a1*cos(b1*t8 + c1) + a2*cos(b2*t8 + c2) + a3*cos(b3*t8 + c3) + a4*cos(b4*t8 + c4),
       a0*cos(b0*t9 + c0) + a1*cos(b1*t9 + c1) + a2*cos(b2*t9 + c2) + a3*cos(b3*t9 + c3) + a4*cos(b4*t9 + c4)],
      dtype=object)

请注意,这不适用于 numpy 的余弦,因为它仅适用于浮点数。但是

cos = np.vectorize(sympy.cos)

为您提供一个适用于数组元素的 sympys 余弦版本。