高速で再現性の高いランダムサンプリングを実現! NumPyの最新乱数生成アルゴリズム『numpy.random.PCG64DXSM()』徹底解説


本記事では、numpy.random.PCG64DXSM() の詳細と、ランダムサンプリングにおけるその役割について分かりやすく解説します。

numpy.random.PCG64DXSM() とは?

numpy.random.PCG64DXSM() は、NumPyで利用可能なPCG64DXSM 乱数生成アルゴリズムをカプセル化した関数です。PCG64DXSMは、Permuted Congruential Generator (PCG) の一種であり、従来のアルゴリズムよりも高速で、より高い再現性を誇ります。

このアルゴリズムは、以下の2つの128ビット符号なし整数で構成される状態を持ちます。

  • シーケンス
    生成される乱数列のシーケンスを決定します。
  • 状態
    線形合同法 (LCG) によって更新される、乱数生成器の状態を表します。

numpy.random.PCG64DXSM() 関数は、以下のメソッドを提供します。

  • shuffle(a)
    配列 a の要素をランダムにシャッフルします。
  • choice(a, size, replace=True, p=None)
    配列 a から要素をランダムに選択します。
  • randint(low, high, size)
    指定された範囲内の整数を生成します。
  • random()
    一様分布に従う乱数を生成します。
  • seed(seed_state)
    乱数生成の状態を初期化します。

ランダムサンプリングにおける役割

ランダムサンプリングとは、母集団から偏りのないランダムなサンプルを抽出する統計手法です。numpy.random.PCG64DXSM() は、このランダムサンプリングを効率的に行うために役立ちます。

例えば、以下のコードは、100個の要素を持つ配列 data から10個のランダムな要素を抽出します。

import numpy as np

rng = np.random.PCG64DXSM()
data = np.arange(100)
sampled_data = rng.choice(data, size=10, replace=False)
print(sampled_data)

このコードは、choice() メソッドを使用して、data から10個の要素をランダムに選択し、sampled_data に格納します。replace=False オプションを指定することで、同じ要素が複数回選択されることを防ぎます。

numpy.random.PCG64DXSM() は、ブートストラップ法やモンテカルロ法などの統計的手法においても広く利用されています。

  • ランダム性
    PCG64DXSMは、統計的に十分なランダム性を備えています。これは、ランダムサンプリングなどの統計的手法において重要な要素です。
  • 再現性
    PCG64DXSMは、同じシード値から常に同じ乱数列を生成します。これは、科学研究やシミュレーションにおいて再現性を確保するために重要です。
  • 高速性
    PCG64DXSMは、他の乱数生成アルゴリズムと比べて非常に高速です。これは、大規模なデータセットを扱う場合に特に重要です。

numpy.random.PCG64DXSM() は、NumPyで利用可能な最新の乱数生成アルゴリズムの一つであり、高速性、再現性、ランダム性の高さから、ランダムサンプリングをはじめとする様々な統計的手法において広く利用されています。



特定の確率で要素をサンプリング

この例では、配列 data から要素をランダムにサンプリングし、その要素が特定の確率で出現するようにします。

import numpy as np

rng = np.random.PCG64DXSM()
data = np.array(['apple', 'banana', 'orange', 'grape', 'strawberry'])
probabilities = [0.2, 0.3, 0.4, 0.05, 0.05]

# サンプルサイズを指定
sample_size = 10

# 'choice' 関数を使用して、確率に基づいてサンプリング
sampled_data = rng.choice(data, size=sample_size, replace=True, p=probabilities)

print(sampled_data)

このコードは以下の処理を実行します。

  1. rng オブジェクトを生成して、PCG64DXSM 乱数ジェネレータを初期化します。
  2. data 配列と probabilities 配列を定義します。
  3. sample_size 変数に、サンプルのサイズを設定します。
  4. choice() 関数を使用して、data 配列から要素をランダムに選択し、sampled_data 配列に格納します。
  5. replace=True オプションを指定することで、同じ要素が複数回選択されることを許可します。
  6. p=probabilities オプションを指定することで、各要素が出現する確率を指定します。

この例では、層別化サンプリングを使用して、各層から比例的に要素をサンプリングします。

import numpy as np

rng = np.random.PCG64DXSM()
data = np.array([
    ['apple', 'banana', 'orange'],
    ['grape', 'strawberry', 'blueberry'],
    ['mango', 'peach', 'kiwi']
])
strata = np.array(['fruit1', 'fruit2', 'fruit3'])
strata_sizes = [2, 3, 2]

# サンプルサイズを指定
sample_size = 7

# 層別化サンプリングを実行
sampled_data = []
for stratum, size in zip(strata, strata_sizes):
    stratum_data = data[strata == stratum]
    sampled_indices = rng.choice(len(stratum_data), size=int(size * sample_size / sum(strata_sizes)), replace=False)
    sampled_data.extend(stratum_data[sampled_indices])

print(sampled_data)
  1. rng オブジェクトを生成して、PCG64DXSM 乱数ジェネレータを初期化します。
  2. data 配列と strata 配列を定義します。data 配列は各層の要素を格納し、strata 配列は各要素の層をラベル付けします。
  3. strata_sizes 配列を定義します。この配列は、各層の要素数を格納します。
  4. sample_size 変数に、サンプルのサイズを設定します。
  5. 各層から要素をサンプリングします。
    • stratastrata_sizes 配列をループします。
    • 各層のデータ (stratum_data) を選択します。
    • choice() 関数を使用して、層内の要素をランダムに選択します。
    • 選択された要素を sampled_data リストに追加します。
  6. sampled_data リストを出力します。

これらの例は、numpy.random.PCG64DXSM() 関数の柔軟性と、ランダムサンプリングにおける様々な応用可能性を示しています。

  • numpy.random.PCG64DXSM() は比較的新しい機能であり、古いバージョンのNumPyでは利用できない場合があります。
  • NumPyには、他にも様々なランダムサンプリング機能が用意されています。詳細は、NumPyドキュメントを参照してください。
  • 上記のコード例はあくまでも例であり、具体的な状況に合わせて調整する必要があります。


しかし、状況によっては、以下の代替方法を検討することもできます。

他の BitGenerator クラス

NumPyには、PCG64DXSM 以外にも様々な BitGenerator クラスが用意されています。それぞれ異なる特性を持つため、用途に合わせて選択することができます。

  • MT19937
    古典的な乱数生成アルゴリズムです。高速で使いやすいですが、PCG64 や PCG64DXSM ほど強力ではありません。
  • SFC64
    PCG64 や PCG64DXSM よりも高速で、より高い再現性を備えた乱数生成アルゴリズムです。
  • Philox
    PCG64 や PCG64DXSM よりも高速な乱数生成アルゴリズムです。ただし、再現性は低くなります。
  • PCG64
    PCG64DXSM と同様に高速で再現性の高い乱数生成アルゴリズムです。ただし、PCG64DXSM ほど強力ではありません。

カスタム乱数生成関数

独自の乱数生成ロジックが必要な場合は、カスタム乱数生成関数を作成することができます。ただし、この方法は、複雑で時間のかかる場合があることに注意が必要です。

他のライブラリ

NumPy以外にも、乱数生成に特化したライブラリがいくつか存在します。例えば、SciPyRandom ライブラリなどが挙げられます。これらのライブラリは、NumPyよりも高度な機能を提供している場合があります。

  • 機能
    特殊な機能が必要かどうか
  • 使いやすさ
    使いやすく、理解しやすい乱数生成アルゴリズムが必要かどうか
  • ランダム性
    統計的に十分なランダム性を備えた乱数が必要かどうか
  • 再現性
    同じシード値から常に同じ乱数列を生成する必要があるかどうか
  • 速度
    高速な乱数生成が必要かどうか