人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

一様乱数の生成

Pythonによるモンテカルロ法入門(2014/6/20)

最初にPythonで [0.0, 1.0] 間の一様乱数を生成してみます。

一様分布

一様分布(Uniform distribution)の確率密度関数(pdf)は下の式になります。

f:id:aidiary:20140621114822p:plain
f:id:aidiary:20140621114827p:plain
引用:http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)

numpy.randomによる一様乱数の生成

numpy.random.uniformで一様分布に従う乱数が生成できます。下のスクリプトでは、下限を0.0、上限を1.0とした一様乱数をNsim個生成し、ヒストグラムを描画しています。

# 一様乱数の生成してヒストグラムを描画
import numpy as np
import matplotlib.pyplot as plt

np.random.seed()
N = 10000
x = np.random.uniform(0.0, 1.0, N)
nbins = 50
plt.hist(x, nbins, normed=True)
plt.show()

実行すると

f:id:aidiary:20140621115319p:plain

numpy.random.RandomStateのページを見るとnumpyの乱数生成器には、最強の乱数生成器として名高いMersenne Twisterアルゴリズムが使われているとのこと。

scipy.statsによる一様乱数の生成

乱数を生成するだけだったらnumpy.randomモジュールを使えばよいのだけれど、確率密度関数や累積分布関数を使いたい場合は、scipy.stats.uniformの方が便利そうなのでこちらも試してみます。下の例では、一様分布に従う乱数を生成するとともに真の確率密度関数も赤線で描画しています。locが一様分布の下限値のパラメータaにあたり、scaleが上限値のパラメータbにあたります。

# 上と同じことをscipy.statsで実現
import numpy as np
from scipy.stats import uniform
import matplotlib.pyplot as plt

# 一様分布に従う確率分布からランダムサンプリング
np.random.seed()
N = 10000
# [0.0, 1.0]の一様分布に従う確率変数
rv = uniform(loc=0.0, scale=1.0)
# 一様分布からサンプリング
x = rv.rvs(size=N)
nbins = 50
plt.hist(x, nbins, normed=True)

# 真のPDFを描画
x = np.linspace(rv.ppf(0), rv.ppf(1), 100)
plt.plot(x, uniform.pdf(x), 'r-', lw=2, label='uniform pdf')

plt.show()

実行すると

f:id:aidiary:20140623213221p:plain

scipy.statsの方は一度確率変数のオブジェクトを作成し、その確率変数のオブジェクトのメソッドを使うことで下のようないろいろな値を計算できるみたい(Scipy Statistics Tutorial)。

  • rvs: Random Variates
  • pdf: Probability Density Function
  • cdf: Cumulative Distribution Function
  • sf: Survival Function (1-CDF)
  • ppf: Percent Point Function (Inverse of CDF)
  • isf: Inverse Survival Function (Inverse of SF)
  • stats: Return mean, variance, (Fisher’s) skew, or (Fisher’s) kurtosis
  • moment: non-central moments of the distribution

逆に確率変数オブジェクト(rv)を使わずに下のように各メソッドにパラメータを直接渡すこともできました。同じ分布を何度も使う場合は確率変数オブジェクトを作った方がすっきりしそう。

# 同じことをscipy.statsで実現
# 確率変数オブジェクトを使わないで
import numpy as np
from scipy.stats import uniform
import matplotlib.pyplot as plt

# 一様分布に従う確率分布からランダムサンプリング
np.random.seed()
N = 10000
loc = 0.0
scale = 1.0

# 一様分布からサンプリング
x = uniform.rvs(loc=loc, scale=scale, size=N)
nbins = 50
plt.hist(x, nbins, normed=True)

# 真のPDFを描画
x = np.linspace(uniform.ppf(0, loc=loc, scale=scale), uniform.ppf(1, loc=loc, scale=scale), 100)
plt.plot(x, uniform.pdf(x, loc=loc, scale=scale), 'r-', lw=2, label='uniform pdf')

plt.show()

いろいろな方法があって混乱しそうなので今後はscipy.statsの確率変数オブジェクトを使う最初の書き方で進めていこうかな。