NumPy Random.random_exponential() 関数で指数分布に従う乱数を生成する方法


random.RandomState.exponential(scale=1.0, size=None)

引数

  • size (int, tuple, None): 生成する乱数の数。None の場合は、単一の乱数を生成します。
  • scale (float, optional): スケールパラメータ。デフォルトは 1.0 です。この値が大きくなるほど、ランダムな値は小さくなります。

戻り値

  • 生成された乱数の NumPy 配列

使い方

import numpy as np

# 乱数生成器を初期化
rng = np.random.RandomState(123)

# 指数分布に従う乱数を 10 個生成
random_numbers = rng.exponential(scale=0.5, size=10)

print(random_numbers)

この例では、スケールパラメータ 0.5 を指定して、10 個の指数分布に従う乱数を生成しています。

指数分布とは

指数分布は、確率密度関数が次の式で表される連続確率分布です。

f(x) = 1/scale * exp(-x / scale)  (x >= 0)

ここで、scale はスケールパラメータです。

指数分布の性質

  • 累積分布関数: F(x) = 1 - exp(-x / scale)
  • 標準偏差: scale
  • 平均: scale
  • ウェブサイトへのアクセス間隔
  • 電話への着信間隔
  • ある機械の故障までの時間
  • スケールパラメータ scale が小さいほど、ランダムな値は大きくなります。
  • random.RandomState.exponential() 関数は、内部的に逆変換法を用いて乱数を生成しています。


import numpy as np

# 乱数生成器を初期化
rng = np.random.RandomState(123)

# スケールパラメータを指定して、10個の指数分布に従う乱数を生成
random_numbers = rng.exponential(scale=0.5, size=10)

print(random_numbers)

このコードは、冒頭の解説で紹介したコードと同じです。

import numpy as np
import matplotlib.pyplot as plt

# 乱数生成器を初期化
rng = np.random.RandomState(123)

# スケールパラメータを指定して、1000個の指数分布に従う乱数を生成
random_numbers = rng.exponential(scale=0.2, size=1000)

# ヒストグラムを作成
plt.hist(random_numbers, bins=20)
plt.xlabel("値")
plt.ylabel("度数")
plt.title("指数分布のヒストグラム (scale=0.2)")
plt.show()

このコードでは、スケールパラメータ 0.2 を指定して、1000 個の指数分布に従う乱数を生成します。その後、生成された乱数のヒストグラムを作成します。

import numpy as np

# 乱数生成器を初期化
rng = np.random.RandomState(123)

# スケールパラメータを指定して、1000個の指数分布に従う乱数を生成
random_numbers = rng.exponential(scale=0.3, size=1000)

# 平均と標準偏差を計算
mean = np.mean(random_numbers)
stddev = np.std(random_numbers)

print("平均:", mean)
print("標準偏差:", stddev)

このコードでは、スケールパラメータ 0.3 を指定して、1000 個の指数分布に従う乱数を生成します。その後、生成された乱数の平均と標準偏差を計算します。



以下に、random.RandomState.standard_exponential() の代替方法をいくつか紹介します。

逆変換法

逆変換法は、確率分布に従う乱数を生成するための一般的な手法です。指数分布の場合、以下の式を用いて乱数を生成することができます。

import numpy as np

def exponential_rv(scale=1.0):
    u = np.random.random()
    return -scale * np.log(u)

この関数は、random.random() 関数で生成された一様乱数を用いて、指数分布に従う乱数を生成します。

ガンマ分布からのサンプリング

ガンマ分布は、指数分布を一般化した確率分布です。ガンマ分布からサンプリングすることで、指数分布に従う乱数を生成することができます。

import numpy as np
from scipy.stats import gamma

def exponential_rv_gamma(scale=1.0):
    shape = 1.0
    rate = 1.0 / scale
    return gamma.rvs(shape, rate)

この関数は、scipy.stats.gamma モジュールの rvs() 関数を使用して、ガンマ分布からサンプリングすることで、指数分布に従う乱数を生成します。

専用のライブラリの使用

NumPy 以外にも、乱数を生成するためのライブラリはたくさんあります。例えば、scikit-learn や statsmodels などのライブラリには、指数分布に従う乱数を生成するための関数があります。

from sklearn.random_distributions import exponential_distribution
import statsmodels.distributions.exponential as sm_exponential

def exponential_rv_sklearn(scale=1.0):
    rng = exponential_distribution(scale=scale)
    return rng.rvs()

def exponential_rv_statsmodels(scale=1.0):
    dist = sm_exponential.Exponential(scale=scale)
    return dist.rvs()

これらの関数は、それぞれのライブラリに特有の機能を利用して、指数分布に従う乱数を生成します。

どの代替方法を選択すべきか

どの代替方法を選択するかは、状況によって異なります。

  • 特定のライブラリ を既に使用している場合は、そのライブラリの関数を使用するのが効率的です。
  • 精度 を重視する場合は、ガンマ分布からのサンプリング がおすすめです。
  • シンプルさ を重視する場合は、逆変換法 がおすすめです。

上記の代替方法は、あくまでも例です。状況に応じて、他の方法も検討することができます。

また、random.RandomState.standard_exponential() 関数は、高速で効率的に乱数を生成することができます。上記の代替方法は、より汎用性が高い一方で、計算速度が遅くなる場合があることに注意が必要です。

random.RandomState.standard_exponential() 関数は、標準指数分布に従う乱数を生成する便利な関数ですが、状況によっては、代替方法が必要になる場合があります。