4

numpy を使用して実装したいアルゴリズムを次に示します。

特定の 1D 配列について、スライディング ウィンドウの最大値と最小値を計算します。最初の値が指定された配列の最初の値と等しい新しい配列を作成します。後続の値ごとに、スライディング ウィンドウの最小値と最大値の間で新しい配列に挿入された前の値をクリップします。

例として、配列a=[3, 4, 5, 4, 3, 2, 3, 3]とサイズ 3 のスライディング ウィンドウを見てみましょう。最小値と最大値は次のようになります。

min = [3, 4, 3, 2, 2, 2]
max = [5, 5, 5, 4, 3, 3]

これで、出力配列は の最初の要素から始まるaので、 になり3ます。次の値として、3 (最後に挿入された値) を 4 と 5 (インデックス 1 で見つかった最小値と最大値) の間で切り取ります。結果は 4 です。次の値では、4 を 3 と 5 の間で切り取ります。それでも 4 です。したがって、最終的には次のようになります。

output = [3, 4, 4, 4, 3, 3]

コードで python for ループを使用しないようにする方法が見つかりません。これが私が今のところ持っているものです:

def second_window(array, samples):
    sample_idx = samples - 1
    output = np.zeros_like(array[0:-sample_idx])
    start, stop = 0, len(array)
    last_value = array[0]
    # Sliding window is a deque of length 'samples'.
    sliding_window = deque(array[start : start+sample_idx], samples)
    for i in xrange( stop - start - sample_idx):
        # Get the next value in sliding window. After the first loop,
        # the left value gets discarded automatically.
        sliding_window.append(array[start + i + sample_idx])
        min_value, max_value = min(sliding_window), max(sliding_window)
        # Clip the last value between sliding window min and max
        last_value = min( max(last_value, min_value), max_value)
        output[start + i] = last_value
    return output

numpyだけでこの結果を達成することは可能でしょうか?

4

2 に答える 2

2

私はあなたができるとは思わない。バッファリングされていない ufunc を使用して、この種の反復計算を実行できる場合もありますが、そうではありません。しかし、詳しく説明させてください...

OK、最初に最小/最大計算のウィンドウ処理をはるかに高速に実行できます。

>>> a = np.array([3, 4, 5, 4, 3, 2, 3, 3])
>>> len_a = len(a)
>>> win = 3
>>> win_a = as_strided(a, shape=(len_a-win+1, win), strides=a.strides*2)
>>> win_a
array([[3, 4, 5],
       [4, 5, 4],
       [5, 4, 3],
       [4, 3, 2],
       [3, 2, 3],
       [2, 3, 3]])
>>> min_ = np.min(win_a, axis=-1)
>>> max_ = np.max(win_a, axis=-1)

それでは、出力配列を作成して埋めましょう。

>>> out = np.empty((len_a-win+1,), dtype=a.dtype)
>>> out[0] = a[0]

where が ufunc の場合np.clip、次のことを試みることができます。

>>> np.clip(out[:-1], min_[1:], max_[1:], out=out[1:])
array([4, 3, 3, 3, 3])
>>> out
array([3, 4, 3, 3, 3, 3])

しかし、これはnp.clipufunc ではなく、バッファリングが関係しているように見えるため、機能しません。

また、個別に適用するnp.minimumnp.maximum、常に機能するとは限りません。

>>> np.minimum(out[:-1], max_[1:], out=out[1:])
array([3, 3, 3, 3, 3])
>>> np.maximum(out[1:], min_[1:], out=out[1:])
array([4, 3, 3, 3, 3])
>>> out
array([3, 4, 3, 3, 3, 3])

あなたの特定のケースでは、他のものを逆にしてもうまくいきます:

>>> np.maximum(out[:-1], min_[1:], out=out[1:])
array([4, 4, 4, 4, 4])
>>> np.minimum(out[1:], max_[1:], out=out[1:])
array([4, 4, 4, 3, 3])
>>> out
array([3, 4, 4, 4, 3, 3])
于 2013-11-09T15:30:19.837 に答える
0

ベクトル化された方法でクリッピング操作を実行するために使用できますがnumpy.clip、移動ウィンドウで最小値と最大値を計算するには、いくつかの Python ループと、既に実装したような両端キューまたはスタック構造が必要になります。

アプローチのその他の例については、次の質問を参照してください。

于 2013-11-09T14:19:29.517 に答える