<p>值得一提的是,以下是你如何使用“花式”跨步技巧。我昨天本来要发这个的,但是被实际工作搞得心烦意乱!:)</p>
<p>@Paul&;@eat都有很好的实现,使用各种其他方法来实现。为了继续前面问题的内容,我想我应该发布N维等价物。</p>
<p>但是,对于>;1D数组,您将无法显著优于<code>scipy.ndimage</code>函数。(<code>scipy.ndimage.uniform_filter</code>应该优于<code>scipy.ndimage.convolve</code>)</p>
<p>此外,如果您试图获得多维移动窗口,则在无意中复制数组时,可能会导致内存使用量爆炸。虽然最初的“滚动”数组只是原始数组内存中的一个视图,但是复制该数组的任何中间步骤都将生成一个比原始数组大<em>个数量级</em>的副本(例如,假设您使用的是100x100原始数组。。。它的视图(对于(3,3)大小的过滤器)将是98x98x3x3,但使用与原始内存相同的内存。但是,任何副本都将使用<em>完全</em>98x98x3x3数组所需的内存量!!)</p>
<p>基本上,当你想在ndarray的<em>单轴</em>上对移动窗口操作进行矢量化时,使用疯狂的跨步技巧是很好的。它使得计算移动标准差等事情变得非常容易,而且开销很小。当你想沿着多个轴开始这样做的时候,这是可能的,但是你通常最好使用更专门的函数。(如<code>scipy.ndimage</code>等)</p>
<p>无论如何,以下是你的做法:</p>
<pre><code>import numpy as np
def rolling_window_lastaxis(a, window):
"""Directly taken from Erik Rigtorp's post to numpy-discussion.
<http://www.mail-archive.com/numpy-discussion@scipy.org/msg29450.html>"""
if window < 1:
raise ValueError, "`window` must be at least 1."
if window > a.shape[-1]:
raise ValueError, "`window` is too long."
shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
strides = a.strides + (a.strides[-1],)
return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
def rolling_window(a, window):
if not hasattr(window, '__iter__'):
return rolling_window_lastaxis(a, window)
for i, win in enumerate(window):
if win > 1:
a = a.swapaxes(i, -1)
a = rolling_window_lastaxis(a, win)
a = a.swapaxes(-2, i)
return a
filtsize = (3, 3)
a = np.zeros((10,10), dtype=np.float)
a[5:7,5] = 1
b = rolling_window(a, filtsize)
blurred = b.mean(axis=-1).mean(axis=-1)
</code></pre>
<p>所以当我们做<code>b = rolling_window(a, filtsize)</code>的时候,我们得到的是一个8x8x3x3数组,它实际上是一个进入原始10x10数组相同内存的视图。我们可以很容易地沿着不同的轴使用不同的滤波器大小,或者只沿着N维数组的选定轴操作(即,在四维数组上的<code>filtsize = (0,3,0,3)</code>将为我们提供一个6维视图)。</p>
<p>然后,我们可以对最后一个轴重复应用任意函数,以有效地计算移动窗口中的内容。</p>
<p>但是,因为我们在<code>mean</code>(或<code>std</code>或其他任何步骤)的每一步都存储比原始数组大得多的临时数组,所以这根本不节省内存!也不会太快。</p>
<p>与<code>ndimage</code>等价的是:</p>
<pre><code>blurred = scipy.ndimage.uniform_filter(a, filtsize, output=a)
</code></pre>
<p>这将处理各种边界条件,在不需要阵列临时副本的情况下进行“模糊”处理,并且可以非常快地<em>very</em>fast。跨步技巧是将函数应用于沿<em>一个</em>轴移动的窗口的好方法,但它们不是沿多个轴移动的好方法,通常。。。。</p>
<p>不管怎样,只要我的0.02美元。。。</p>