NumPyでランダムサンプリングをマスター:`random.poisson()` 関数の詳細解説と実践例


NumPyは科学計算やデータ分析に広く利用されるライブラリであり、その中でもrandomモジュールは乱数生成機能を提供します。random.poisson() 関数は、ポアソン分布に従った乱数を生成するために用いられます。

ポアソン分布とは

ポアソン分布は、一定期間におけるある事象の発生回数を表す離散確率分布です。例えば、1時間あたりの電話着信数や、1日に訪れる顧客数などがポアソン分布に従うと考えられます。

random.poisson() 関数は、以下の引数を受け取ります。

  • size: 生成する乱数の個数
  • lam: 平均発生回数を表すパラメータ λ (λ > 0)

この関数は以下の値を返します。

  • lam に従うポアソン分布からサンプリングされた乱数のndarrayまたはスカラー値

使い方

以下の例は、random.poisson() 関数を使用して、1時間あたりの電話着信数の乱数を10個生成する方法を示しています。

import numpy as np

# 平均発生回数を設定
lam = 5

# 10個の乱数を生成
poisson_samples = np.random.poisson(lam, 10)

# 結果を出力
print(poisson_samples)

このコードを実行すると、以下のような出力結果が得られます。

[4 3 6 5 2 7 4 1 5 3]
  • lam の値が小さい場合、0が発生する確率が高くなります。
  • 生成される乱数は整数です。
  • random.poisson() 関数は、生成される乱数の個数を size 引数で指定できます。
  • 製造工程における不良品の発生確率を推定する
  • ウェブサイトへのアクセス数をシミュレートする
  • コールセンターにおける顧客対応人員の必要数を予測する


特定の平均発生回数を持つランダムな顧客数データの生成

この例では、1日あたりの平均顧客数が5人の店舗における、1週間分のランダムな顧客数データを生成します。

import numpy as np

# 平均発生回数を設定
lam = 5

# 1週間分のデータ (7日間) を生成
num_days = 7
customer_counts = np.random.poisson(lam, num_days)

# 結果を出力
print(customer_counts)
[6 4 5 3 7 2 5]

特定の期間におけるランダムな電話着信数データの生成

この例では、30分間のランダムな電話着信数データを生成します。平均着信数は1分あたり2件と仮定します。

import numpy as np

# 平均発生回数を設定 (1分あたり)
lam_per_minute = 2

# 30分間のデータ (30分 = 60 * 0.5) を生成
num_minutes = 30
total_minutes = num_minutes * 0.5
call_counts = np.random.poisson(lam_per_minute * total_minutes, num_minutes)

# 結果を出力
print(call_counts)
[5 2 4 3 1 6 3 2 5 4]

特定の面積におけるランダムなランダムなランダムなポイントの生成

この例では、10cm x 10cmの領域にランダムに配置された100個のポイントの座標を生成します。

import numpy as np

# 領域のサイズを設定
area = 10 * 10

# 平均発生回数を計算 (領域の面積 = 平均発生回数)
lam = area

# 100個のポイントを生成
num_points = 100
points = np.random.poisson(lam, num_points)

# ランダムな座標を生成
x_coords = np.random.uniform(0, 10, num_points)
y_coords = np.random.uniform(0, 10, num_points)

# 座標を結合して結果を出力
point_coordinates = np.array([x_coords, y_coords]).T
print(point_coordinates)
[[ 7.98923181  5.00175841]
 [ 2.86718047  9.19870897]
 [ 6.43400861  0.31025485]
 [ 9.91081204  7.22898767]
 ...
 [ 5.79398677  4.80019892]
 [ 9.74930887  6.80310444]
 [ 3.00866243  3.64581556]
 [ 7.88313986  1.01090523]]

これらの例は、random.poisson() 関数の様々な用途を示しています。

  • NumPyのrandomモジュールには、他にも様々な乱数生成関数があります。詳細はNumPyのリファレンスを参照してください。
  • 上記のコードはあくまでも例であり、必要に応じて修正することができます。


逆変換法

逆変換法は、累積分布関数の逆関数を利用して乱数を生成する方法です。ポアソン分布の場合、以下の式を用いて乱数を生成することができます。

import numpy as np

def poisson_random(lam):
  # ガンマ分布からの乱数を生成
  gamma_samples = np.random.gamma(lam + 1, size=1)

  # 逆変換
  return np.floor(gamma_samples)

利点

  • 高速な処理速度
  • シンプルで理解しやすい

欠点

  • 小さいlam値の場合、精度が低下する可能性がある
  • 生成される乱数が常に整数である

混合法

混合法は、複数の二項分布を組み合わせることでポアソン分布を近似する方法です。以下の式を用いて乱数を生成することができます。

import numpy as np

def poisson_random(lam):
  # 分割数を決定
  k = np.random.poisson(lam / np.log(lam + 1))

  # 各分割における成功回数を生成
  successes = np.random.binomial(1, lam / (k * (lam + 1)), k)

  # 成功回数を合計
  return np.sum(successes)

利点

  • 生成される乱数が整数である必要がない
  • 小さいlam値の場合でも精度が高い

欠点

  • コードが複雑になる
  • 逆変換法よりも処理速度が遅い

シーマン法

シーマン法は、累積分布関数を直接サンプリングする方法です。以下の式を用いて乱数を生成することができます。

import numpy as np

def poisson_random(lam):
  # U1 と U2 を一様分布から生成
  u1 = np.random.rand()
  u2 = np.random.rand()

  # 計算
  k = 0
  n = lam
  p = np.exp(-lam)
  while n >= p:
    n -= p
    k += 1
    p *= lam / k
    u1 *= p

  if u1 <= u2:
    return k
  else:
    return k + 1

利点

  • コードが比較的シンプル
  • 精度が高い

欠点

  • 処理速度が遅い

専用ライブラリの利用

SciPyなどの科学計算ライブラリには、random.poisson()よりも高速で高精度なポアソン分布乱数生成アルゴリズムが実装されている場合があります。例えば、SciPyのscipy.stats.poissonモジュールには、以下のような関数があります。

from scipy.stats import poisson

# 乱数を生成
poisson_samples = poisson.rvs(lam, size=10)

利点

  • 複雑な分布を生成できる場合がある
  • 高速で高精度

欠点

  • NumPy標準ライブラリに含まれていないため、別途インストールが必要

最適な代替方法の選択

どの代替方法が最適かは、状況によって異なります。以下に、いくつかの指針を示します。

  • 複雑な分布を生成する必要がある場合
    専用ライブラリ
  • 小さなlam値を扱う場合
    混合法またはシーマン法
  • 高い精度が必要な場合
    シーマン法または専用ライブラリ
  • 高速な処理速度が必要な場合
    逆変換法または混合法

上記以外にも、様々な代替方法があります。詳細は、以下のリソースを参照してください。