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()
関数は、標準指数分布に従う乱数を生成する便利な関数ですが、状況によっては、代替方法が必要になる場合があります。