一个窍门是将最后的L-1
行附加到数组外并将这些行追加到数组的开头。那么,这将是一个简单的例子,使用非常高效的NumPy strides
。对于那些想知道这个技巧的成本的人来说,正如我们稍后将通过时序测试所看到的那样,它没有任何好处。
诀窍领先的高达将支持在代码向前和向后跨步会是这个样子的最终目标 -
向后跨步:
def strided_axis0_backward(inArr, L = 2):
# INPUTS :
# a : Input array
# L : Length along rows to be cut to create per subarray
# Append the last row to the start. It just helps in keeping a view output.
a = np.vstack((inArr[-L+1:], inArr))
# Store shape and strides info
m,n = a.shape
s0,s1 = a.strides
# Length of 3D output array along its axis=0
nd0 = m - L + 1
strided = np.lib.stride_tricks.as_strided
return strided(a[L-1:], shape=(nd0,L,n), strides=(s0,-s0,s1))
向前跨步:
def strided_axis0_forward(inArr, L = 2):
# INPUTS :
# a : Input array
# L : Length along rows to be cut to create per subarray
# Append the last row to the start. It just helps in keeping a view output.
a = np.vstack((inArr , inArr[:L-1]))
# Store shape and strides info
m,n = a.shape
s0,s1 = a.strides
# Length of 3D output array along its axis=0
nd0 = m - L + 1
strided = np.lib.stride_tricks.as_strided
return strided(a[:L-1], shape=(nd0,L,n), strides=(s0,s0,s1))
样品运行 -
In [42]: inArr
Out[42]:
array([[1, 2],
[3, 4],
[5, 6]])
In [43]: strided_axis0_backward(inArr, 2)
Out[43]:
array([[[1, 2],
[5, 6]],
[[3, 4],
[1, 2]],
[[5, 6],
[3, 4]]])
In [44]: strided_axis0_forward(inArr, 2)
Out[44]:
array([[[1, 2],
[3, 4]],
[[3, 4],
[5, 6]],
[[5, 6],
[1, 2]]])
运行试验 -
In [53]: inArr = np.random.randint(0,9,(1000,10))
In [54]: %timeit make_timesteps(inArr, 2)
...: %timeit strided_axis0_forward(inArr, 2)
...: %timeit strided_axis0_backward(inArr, 2)
...:
10 loops, best of 3: 33.9 ms per loop
100000 loops, best of 3: 12.1 µs per loop
100000 loops, best of 3: 12.2 µs per loop
In [55]: %timeit make_timesteps(inArr, 10)
...: %timeit strided_axis0_forward(inArr, 10)
...: %timeit strided_axis0_backward(inArr, 10)
...:
1 loops, best of 3: 152 ms per loop
100000 loops, best of 3: 12 µs per loop
100000 loops, best of 3: 12.1 µs per loop
In [56]: 152000/12.1 # Speedup figure
Out[56]: 12561.98347107438
的strided_axis0
的定时保持不变,甚至当我们增加子阵列的长度在输出中。这只是为了向我们展示strides
带来的巨大收益,当然还有疯狂的加速也超过了原来的loopy版本。
截至一开始答应了,这里的一对堆叠成本时序与np.vstack
-
In [417]: inArr = np.random.randint(0,9,(1000,10))
In [418]: L = 10
In [419]: %timeit np.vstack((inArr[-L+1:], inArr))
100000 loops, best of 3: 5.41 µs per loop
时序支持堆叠是一个很有效的一个的想法。
非常感谢 - 这确实有所帮助,我曾看过as_strided,但直到您的示例和链接都无法理解它!为了获得相同的顺序,我用第一行加上最后一行,然后在第一行上加上np.flip。我编辑了这个问题来显示我的最终代码。 – nickyzee
@nickyzee我不认为我明白你为什么需要'翻转“。你的'make_timesteps'是正确的,因为我编码试图产生与'make_timesteps'相同的结果。用你的翻页建议,我的代码产生的结果与'make_timesteps'不同。澄清这一点? – Divakar
有趣 - 翻转是需要做出相同的输出,因为我从原来的。目视检查输出也证实了这一点。不知道为什么 - numpy @ latest和py3.5 - 我原来的返回数组([[[1,2], [3,4]], [[3,4], [5,6]] , [[5,6], [7,8], [[7,8], [1,2]]])' – nickyzee