与えられた確率boolean
でTrue
とFalse
でランダムに満たされる巨大なp
行列を作成しようとしています。最初はこのコードを使用しました:
N = 30000
p = 0.1
np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])
しかし、悲しいことに、この大きなN
で終了しないようです。だから私はこれを行うことで単一行の生成に分割しようとしました:
N = 30000
p = 0.1
mask = np.empty((N, N))
for i in range (N):
mask[i] = np.random.choice(a=[False, True], size=N, p=[p, 1-p])
if (i % 100 == 0):
print(i)
今、奇妙なことが起こります(少なくとも私のデバイスでは):最初の〜1100行は非常に高速に生成されます-しかし、その後、コードはひどく遅くなります。なんでこんなことが起こっているの?ここで何が恋しいですか? True
エントリの確率がp
およびFalse
エントリの確率が1-p
である大きな行列を作成するより良い方法はありますか?
編集:多くの人がRAMが問題になると仮定しました:コードを実行するデバイスはほぼ500GBのRAMを持っているため、これは問題。
問題はRAMであり、値は作成時にメモリに保存されます。このコマンドを使用してこのマトリックスを作成しました。
np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])
64GBのRAMおよび8コアのAWS i3
インスタンスを使用しました。このマトリックスを作成するために、htop
は20GBのRAMを占有することを示しています。気になる場合のベンチマーク:
time np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])
CPU times: user 18.3 s, sys: 3.4 s, total: 21.7 s
Wall time: 21.7 s
def mask_method(N, p):
for i in range(N):
mask[i] = np.random.choice(a=[False, True], size=N, p=[p, 1-p])
if (i % 100 == 0):
print(i)
time mask_method(N,p)
CPU times: user 20.9 s, sys: 1.55 s, total: 22.5 s
Wall time: 22.5 s
マスクメソッドは、ピーク時にRAMの最大9GBしか使用しないことに注意してください。
編集:最初のメソッドは、関数メソッドがすべてを保持しているプロセスが完了した後、RAMをフラッシュします。
だから私はこれを行うことで単一行の生成に分割しようとしました:
np.random.choice
が機能する方法は、まずデータのすべてのセルに対してfloat64
で[0, 1)
を生成し、それをnp.search_sorted
を使用して配列のインデックスに変換することです。この中間表現は、ブール配列の8倍です!
データはブール値であるため、次のようにして2倍の速度を得ることができます。
np.random.Rand(N, N) > p
当然、ループソリューション内で使用できます
np.random.choice
はここでいくつかのバッファリングを行うことができるようです-numpyに対して問題を報告することができます。
別のオプションは、float32
sの代わりにfloat64
sを生成しようとすることです。 numpyが今すぐできるかどうかはわかりませんが、機能をリクエストできます。
別の可能性は、バッチで生成することです(つまり、多くのサブ配列を計算し、最後に一緒にスタックします)。ただし、OPが行っているように、mask
ループ内の1つの配列(for
)を更新しないことを検討してください。これにより、インデックス更新のたびにアレイ全体がメインメモリに強制的にロードされます。
代わりに、たとえば:30000x30000
、9000を持っています100x100
個別の配列、このそれぞれを更新100x100
に応じてfor
ループに配列し、最終的にこれらの9000配列を巨大配列にスタックします。これは間違いなく4GB以下のRAMであり、非常に高速です。
最小限の例:
In [9]: a
Out[9]:
array([[0, 1],
[2, 3]])
In [10]: np.hstack([np.vstack([a]*5)]*5)
Out[10]:
array([[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3, 2, 3]])
In [11]: np.hstack([np.vstack([a]*5)]*5).shape
Out[11]: (10, 10)