[英]How can I apply a vectorized function to the previous element of a numpy array?
我想应用这样的函数:
s[i] = a*x[i] + (1 - a)*s[i-1]
其中s
和x
都是相同长度的数组。
我不想使用 for 循环,因为这些数组非常大(> 50 百万)。 我试过做这样的事情
def f(a,x):
s = [0]*len(x)
s[i] = a*x[i] + (1 - a)*s[i-1]
return s
但当然i
没有定义所以这不起作用。
有没有办法使用map
或numpy.apply_along_axis
或其他一些矢量化方法来做到这一点?
我还没有遇到过将函数应用于数组的当前和先前元素而不使用 for 循环的方法,而这正是我想在这里了解如何做的。
编辑
明确地说,这里是 for 循环实现,它有效但我想避免
s = [0]*len(x)
a=0.45
for i in range(len(x)):
s[i] = a*x[i] + (1-a)*s[i-1]
s[0] = x[0] # reset value of s[0]
您可以避免循环,尽管矢量化更像是“计算每个值的所有内容”。
import numpy as np
# Loop
def fun(x, a):
s = [0] * len(x)
for i in range(len(x)):
s[i] = a * x[i] + (1 - a) * s[i - 1]
s[0] = x[0]
return s
# Vectorized
def fun_vec(x, a):
x = np.asarray(x, dtype=np.float32)
n = np.arange(len(x))
p = a * (1 - a) ** n
# Trick from here: https://stackoverflow.com/q/49532575/1782792
pz = np.concatenate((np.zeros(len(p) - 1, dtype=p.dtype), p))
pp = np.lib.stride_tricks.as_strided(
pz[len(p) - 1:], (len(p), len(p)),
(p.strides[0], -p.strides[0]), writeable=False)
t = x[np.newaxis] * pp
s = np.sum(t, axis=1)
s[0] = x[0]
return s
x = list(range(1, 11))
a = 0.45
print(np.allclose(fun(x, a), fun_vec(x, a)))
# True
这种策略虽然需要 O(n 2 ) 内存,但计算量更大。 根据情况,由于并行性,它可以更快(我做了类似的事情来消除 TensorFlow 中的tf.while_loop
以取得巨大成功),但在这种情况下,它实际上更慢:
x = list(range(1, 101))
a = 0.45
%timeit fun(x, a)
# 31 µs ± 85.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit fun_vec(x, a)
# 147 µs ± 2.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
所以,可以有一个非循环版本,但它比其他任何东西都更令人好奇。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.