Pythonでのnumpy.randomとrandom.randomの違い


100

Pythonに大きなスクリプトがあります。私は他の人のコードにインスピレーションを与えたのでnumpy.random、いくつかの目的でモジュールを使用することになり(たとえば、二項分布から取得した乱数の配列を作成するため)、他の場所ではモジュールを使用しましたrandom.random

誰かが2つの主な違いを教えていただけますか?2つそれぞれのドキュメントのWebページを見ると、numpy.randomメソッドの数が多いように見えますが、乱数の生成がどのように異なるのかはわかりません。

私が尋ねる理由は、デバッグのためにメインプログラムをシードする必要があるためです。しかし、インポートしているすべてのモジュールで同じ乱数ジェネレータを使用しないと機能しませんが、これは正しいですか?

また、私はここを別の投稿でを使用numpy.random.seed()しないことについての議論で読みましたが、これがなぜそんなに悪い考えであるのか本当に理解していませんでした。これが事実である理由を誰かが私に説明してくれると本当にありがたいです。

回答:


120

あなたはすでに多くの正しい観察をしました!

両方のランダムジェネレーターをシードする場合を除き、どちらか一方のジェネレーターを選択する方が長期的にはおそらく簡単です。ただし、両方を使用する必要がある場合は、両方ともシードする必要があります。これらは互いに独立して乱数を生成するためです。

以下のためnumpy.random.seed()であること、それはあなたが持っている場合は、使用するのは安全ではありません- 、主な問題は、スレッドセーフではありませんということで、実行の多くの異なるスレッドを 2つの異なるスレッドが同時に関数を実行している場合、それが動作する保証はないので、。スレッドを使用しておらず、将来この方法でプログラムを書き直す必要がないと合理的に期待できる場合は、問題ありませんnumpy.random.seed()。将来的にスレッドが必要になると思われる理由がある場合は、長期的には、提案されているようにしてnumpy.random.Randomクラスのローカルインスタンス作成する方がはるかに安全です。私の知る限り、random.random.seed()スレッドセーフです(または少なくとも、反対の証拠は見つかりませんでした)。

numpy.randomライブラリーは、一般的に科学的研究だけでなく、ランダムなデータの配列を生成するための便利な機能のカップルで使用されるいくつかの余分な確率分布が含まれています。random.randomライブラリには、もう少し軽量であり、そしてあなたは、科学研究や統計での作業の他の種類をやっていない場合は問題ないはずです。

それ以外の場合は、どちらもメルセンヌツイスターシーケンスを使用して乱数を生成します。どちらも完全に決定論的です。つまり、情報の重要なビットをいくつか知っている場合は、次に来る数字を確実に予測できます。このため、numpy.randomもrandom.randomも、深刻な暗号化の用途には適していません。ただし、シーケンスが非常に長いため、データをリバースエンジニアリングしようとする人が心配されていない場合は、どちらも乱数を生成するのに適しています。これは、ランダムな値をシードする必要がある理由でもあります。毎回同じ場所から開始すると、常に同じ乱数列が得られます。

あなたがあれば注意点として、ない暗号レベルのランダム性を必要とする、あなたが使うべき秘密のモジュール、またはのようなものCrypto.Randomを以前のPython 3.6よりもPythonのバージョンを使用している場合。


14
Mersenneツイスターは暗号化(および通常とは異なる科学的)目的に十分なエントロピーのランダムシーケンスを生成しないため、遠く離れた関連の注意として、どちらも使用しないことが必要な場合があります。これらのまれなケースでは、多くの場合、Crypto.Randomが必要です。Crypto.Randomは、OS固有のエントロピーソースを使用して、random.random単独で利用できるよりもはるかに高品質の非決定論的なランダムシーケンスを生成できます。ただし、通常は必要ありません。
SingleNegationElimination 2011

ハネレありがとうございます。あなたの洞察は本当に非常に役に立ちました!私のプログラムの一部がランダムを使用する別のプログラムを呼び出しているため、単一の乱数ジェネレーター(ランダムでは二項分布が生成されないため、派手である必要があります)だけを使用しても問題が解決しないことがわかりました。2つのジェネレータをシードする必要があります。
ローラ

2
「現在の数字がわかっている場合は、次に来る数字を確実に予測することができます。」この発言にはいくつかの説明が必要かもしれません。つまり、ジェネレーターの内部状態がわかっていれば、シーケンスを再現できます。これは、ジェネレーターをシードするときに行うことです。ジェネレータから出力される単一の数値を指定すると、次の数値を予測することはできません。期間が非常に大きいため、疑似ランダムシーケンスのどこにいるのかを計算して次のシーケンスを予測する前に、長い数値のシーケンスが必要になる可能性があります。
Kaushik Ghose 2014

12

データ分析のためのPython、モジュールはnumpy.randomパイソンを補足random効率的確率分布の多くの種類からのサンプル値の全配列を生成するための機能を。

対照的に、Pythonの組み込みrandomモジュールは一度に1つの値しかサンプリングしませんが、numpy.random非常に大きなサンプルをより速く生成できます。IPythonマジック関数を使用すると、%timeitどのモジュールがより高速に実行されるかを確認できます。

In [1]: from random import normalvariate
In [2]: N = 1000000

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop

In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop

1
他の方法には当てはまりません。と比較np.random.randint(2)してrandom.randrange(2)、NumPyは遅いものでした。NumPy:1.25 us、ランダム:891 ns。そしてまたのための同じ関係np.random.rand()random.random()
Shayan Amani

3

シードのソースと使用される配布プロファイルは出力に影響を及ぼします-暗号のランダム性を探している場合、os.urandom()からシードすると、デバイスのチャター(つまりイーサネットまたはディスク)からほぼ実際のランダムバイトが取得されます(つまり/ BSDでのdev / random)

これにより、シードを指定して確定的な乱数を生成することが回避されます。ただし、ランダムコールを使用すると、数値を分布に適合させることができます(私は科学的ランダムネスと呼んでいます-最終的に必要なのは、乱数のベルカーブ分布だけです。numpyは、これをうまく処理するのに最適です。

だからはい、1つのジェネレーターに固執しますが、どのランダムを使用するかを決定します-ランダムですが、分布曲線から、または量子デバイスなしで取得できる限りランダムです。


ポールありがとう、あなたの答えは本当に役に立ちました!私は暗号のランダム性を探しているのではなく、数学的なモデリングを行っており、疑似乱数で十分です。私は二項分布にnumpyが必要であり、私のプログラムはランダムを使用する別のプログラムを呼び出すので、思い通りに1つのジェネレーターに固執できないことがわかりました:(
Laura
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.