1

私は非常に(非常に、非常に)大きな2次元配列を持っています.1,000列のオーダーですが、数百万行です(32GBマシンのメモリに収まらないほどです)。千列のそれぞれの分散を計算したいと思います。役立つ重要な事実の 1 つ: 私のデータは 8 ビットの符号なし整数です。

これが私がこれにどのようにアプローチすることを計画しているかです。まず、 countsという形状 (1000, 256)の新しい 2 次元配列を作成しcounts[i,:] == np.bincount(bigarray[:,i])ます。この配列を取得したら、分散を計算するのは簡単です。

問題は、効率的に計算する方法がわからないことです (この計算はリアルタイムで実行する必要があり、SSD がデータを返す速度によって帯域幅を制限したいと考えています)。これは機能しますが、非常に遅いです:

counts = np.array((1000,256))
for row in iterator_over_bigaray_rows():
    for i,val in enumerate(row):
        counts[i,val] += 1

より速く実行するためにこれを書く方法はありますか? このようなもの:

counts = np.array((1000,256))
for row in iterator_over_bigaray_rows():
    counts[i,:] = // magic np one-liner to do what I want
4

1 に答える 1

1

これがあなたが望むものだと思います:

counts[np.arange(1000), row] += 1

しかし、配列に何百万もの行がある場合でも、何百万もの行を反復処理する必要があります。次のトリックにより、システムが 5 倍近く高速化されます。

chunk = np.random.randint(256, size=(1000, 1000))

def count_chunk(chunk):
    rows, cols = chunk.shape
    col_idx = np.arange(cols) * 256
    counts = np.bincount((col_idx[None, :] + chunk).ravel(),
                         minlength=256*cols)
    return counts.reshape(-1, 256)

def count_chunk_by_rows(chunk):
    counts = np.zeros(chunk.shape[1:]+(256,), dtype=np.int)
    indices = np.arange(chunk.shape[-1])
    for row in chunk:
        counts[indices, row] += 1
    return counts

そしていま:

In [2]: c = count_chunk_by_rows(chunk)

In [3]: d = count_chunk(chunk)

In [4]: np.all(c == d)
Out[4]: True

In [5]: %timeit count_chunk_by_rows(chunk)
10 loops, best of 3: 80.5 ms per loop

In [6]: %timeit count_chunk(chunk)
100 loops, best of 3: 13.8 ms per loop
于 2013-03-27T20:54:23.433 に答える