0

我有一个关于 numpy 的问题。

假设我有一个功能

def calcSomething(A,t):

    return t*A

我想将 A 传递给一个常量 numpy 数组,例如A=np.array([1.0,2.0])和 t 作为等距点,例如t = np.linspace(0.0,1.0,10). 现在,当我执行

x = calcSomething(A,t)

我想得到x[0] = [0,0], x[1] = [.1,.2],..., x[9] = [1.0,2.0]。有没有一种简单的方法可以实现这一点,还是我必须使用 for 循环和附加来实现它?

编辑:'calcSomething(): 只是一个更复杂函数的占位符。

例如y=np.sin(t)产量y[i]=np.sin(t[i])。这就是我想要实现的通用功能。

提前致谢!

4

3 回答 3

1

在可能的情况下,使用对整个数组进行操作的 numpy 函数和运算符,并broadcasting为您执行必要的操作:

In [24]: A = np.array([1.0,2.0]); t = np.linspace(0.0, 1.0, 10)
In [25]: x = t[:,None] * A[None,:]
In [26]: x.shape
Out[26]: (10, 2)
In [27]: x[:3,:]
Out[27]: 
array([[0.        , 0.        ],
       [0.11111111, 0.22222222],
       [0.22222222, 0.44444444]])
In [28]: np.sin(t)
Out[28]: 
   array([0.        , 0.11088263, 0.22039774, 0.3271947 , 0.42995636,
          0.52741539, 0.6183698 , 0.70169788, 0.77637192, 0.84147098])

如果您有一个仅适用于标量输入的函数,则可以使用np.vectorize这些值向它提供这些值 - 来自广播数组:

In [30]: def foo(A,t):
    ...:     return t*A
    ...: 
In [31]: f = np.vectorize(foo, otypes=[float])
In [32]: f(A[None,:], t[:,None])
Out[32]: 
array([[0.        , 0.        ],
       [0.11111111, 0.22222222],
       [0.22222222, 0.44444444],
       ....
       [1.        , 2.        ]])

vectorize是一个便利函数;它不承诺速度。比较它的时间In[25]

In [33]: timeit f(A[None,:], t[:,None])
41.3 µs ± 48.5 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [34]: timeit x = t[:,None] * A[None,:]
5.41 µs ± 8.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

慢 8 倍。

或使用标量math.sin函数:

In [35]: import math
In [36]: g = np.vectorize(math.sin)
...
In [39]: timeit g(t)
39 µs ± 72.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [40]: timeit np.sin(t)
1.4 µs ± 2.72 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

迭代调用math.sin比 快np.sin,但np.sin在给定整个数组时要快得多。

基本区别在于vectorize,像显式循环一样,它在解释的 Python 中进行迭代,并为每个输出元素调用一次函数。 np.sin并且数组*正在迭代,但是在编译的代码中。

在 Python 和 numpy 中有多种迭代方式,但很少有超过 2 倍的加速。

有一些工具可以将计算转移到已编译的代码中,例如cythonnumba。搜索这些标签以获取有关如何使用它们的想法。

于 2018-04-11T23:50:32.690 回答
0

您可以使用矩阵乘法:

>>> A = np.array([1.0,2.0])
>>> t = np.linspace(0.0,1.0,10)
>>> np.matmul(t.reshape(10, 1), A.reshape(1, 2))
array([[0.        , 0.        ],
       [0.11111111, 0.22222222],
       [0.22222222, 0.44444444],
       [0.33333333, 0.66666667],
       [0.44444444, 0.88888889],
       [0.55555556, 1.11111111],
       [0.66666667, 1.33333333],
       [0.77777778, 1.55555556],
       [0.88888889, 1.77777778],
       [1.        , 2.        ]])
于 2018-04-11T15:13:17.623 回答
0

只需使用None指定一个新轴:

A[None, :] * t[:, None] 
于 2018-04-11T15:15:18.743 回答