Generator.hypergeometricは、超幾何分布から乱数配列を生成するnumpy.randomモジュールのジェネレータメソッドです。
超幾何分布の例として、黒石と白石が入っている壺を考えてみましょう。黒石は当たりで、白石は外れとします。ここからn個の石を取り出します。超幾何分布は、取り出したn個の中に、当たりである黒石がどれぐらい含まれているのかを示す確率分布です。
この確率分布は、二項分布と似ています。違いは、超幾何分布は一度取り出した石は戻さないという点にあります。二項分布では、1回石を取り出す度に、取り出した石を壺に戻します。標本の数が大きくなればなるほど、超幾何分布は二項分布に近づきます。
このページでは、この超幾何分布から乱数を生成するGenerator.hypergeometricを解説します。
1. 書式
書き方:
Generator.hypergeometric(ngood, nbad, nsample, size=None)
パラメーター:
ngood: int or array_like of ints 当たりの数(<10**9) |
nbad: int or array_like of ints 外れの数(<10**9) |
nsample: int or array_like of ints 抽出数(< ngood+nbad) |
size: int or tuple of ints, optional 出力する配列のshapeを指定する。デフォルト値のNoneの場合で、かつ、ngood, nbad, nsampleがスカラーの場合、1つの乱数の値を返す。それ以外の場合は、np.broadcast(ngood, nbad, nsample).sizeの乱数を生成する。 |
戻り値:
out: ndarray or scalar パラメータを設定した超幾何分布からの乱数を出力する。 |
Notes
Generator.hypergeometricでは、ngoodとnbadは10**9以下である必要があります。ここまで極端に大きな引数の場合、標本の処理の処理に使われるアルゴリズムがうまく機能せず、浮動小数点数の計算に支障が出てしまうからです。ここまで大きな値を扱う場合で、さらにnsampleがそこまで大きくない場合は、分布は二項分布に近くなります。そのため、binomial(n=nsample, p=ngood/(ngood + nbad))で対応することができます。
2. サンプルコード
それでは、サンプルコードを見ていきましょう。
まずは、random.default_rng コンストラクタでジェネレータオブジェクトを作成します。『numpy.random.default_rng – 乱数生成のためのジェネレータオブジェクトの作成』に目を通しておいてください。
import numpy as np
rng = np.random.default_rng()
rng
こうして作成したジェネレータオブジェクト rng に対して、Generator.hypergeometricを呼び出すことによって、超幾何分布から乱数配列を取得することができます。
以下のコードでは、当たりの数98個、外れの数2個の合計100個から10個取り出す試行を5回行っています。
ngood, nbad, nsamp = 98, 2, 10
rng.hypergeometric(ngood, nbad, nsamp, 5)
# 当たりの数98個、外れの数2個から10個取り出す試行を
# 行った場合に取り出した当たりの数 × 5セット
1回目から4回目の試行では、取り出したものは全て当たりでした。5回目の試行では1個だけ外れを引きました。
以下のヒストグラムは、10000回の試行を行った際の確率分布です。当たりを8個しか引けない(=数少ない外れをどちらも引く)確率は非常に小さいことがわかります。
s = rng.hypergeometric(ngood, nbad, nsamp, 10000)
from matplotlib.pyplot import hist
hist(s)
plt.show()
それでは、2個しかない外れをすべて引いてしまう確率はどれぐらいあるのでしょうか。以下の式で計算することができます。
s = rng.hypergeometric(ngood, nbad, nsamp, 100000)
sum(s<=8)/100000.
0.93%なので非常に小さな確率です。
3. まとめ
以上のように、Generator.hypergeometricは、超幾何分布から乱数配列を生成するジェネレータメソッドです。
以前は、numpy.random.hypergeometric関数が使われていましたが、ジェネレータメソッドを使うようにしましょう。こちらの方が、処理が高速で、大量のデータを扱う科学技術計算に適しているからです。
コメント