PyLearnPR 01: 一様分布

一様分布とは、ある特定範囲のデータをすべて同じ確率で発生させる確率密度関数のことを言います(厳密な定義ではありませんが)。

一様分布の基本

例えばpythonでは、numpyにあるrandom.rand()を用いることで、0以上1未満の一様分布に従う乱数を生成することができます。 以下のコードは、この乱数を1000個生成する機能を持ちます。

In [1]:
import numpy as np
Val01 = np.random.rand(1000)
print(np.shape(Val01))
(1000,)

shapeで次元を確認したところ、確かに1000個のデータがあることを確認できました。 0以上1未満の乱数が1000個あるわけですから、その平均値はだいたい0.5になるはずです。 また、最小値は0付近(ただし0を下回らない)、最大値は1付近(ただし1以上とならない)となるはずです。 これを確認してみます。

In [2]:
print('平均値: ', np.mean(Val01))
print('最小値: ', np.min(Val01))
print('最大値: ', np.max(Val01))
平均値:  0.5094376606214092
最小値:  0.0007226022073659744
最大値:  0.9994860534553406

確かにそうなることを確認できました。 ところで、乱数の訳ですから当然、実行のたびに結果が変わってしまいます。 「すごい結果が出ました、結果は再現できませんが!」ではいけませんので、研究で乱数を使用する場合には、結果を再現できる乱数を使用する必要があります。プログラミング上で再現可能な乱数を生成することを、シードを固定する、と呼びます。シードを固定するには、numpyにあるrandom.seedを利用します。

In [3]:
np.random.seed(1)
print(np.random.rand(1))

np.random.seed(1)
print(np.random.rand(1))
[0.417022]
[0.417022]

乱数のシードを1から2に変更してみます。

In [4]:
np.random.seed(2)
print(np.random.rand(1)) # 乱数その1

np.random.seed(2)
print(np.random.rand(1)) # 乱数その2
[0.4359949]
[0.4359949]

乱数のシードを固定させた後、複数の乱数を生成してみます。

In [5]:
np.random.seed(2)
print('*** 1セット目 ***')
print(np.random.rand(1))
print(np.random.rand(1))
print(np.random.rand(1))

np.random.seed(2)
print('*** 2セット目 ***')
print(np.random.rand(1))
print(np.random.rand(1))
print(np.random.rand(1))
*** 1セット目 ***
[0.4359949]
[0.02592623]
[0.54966248]
*** 2セット目 ***
[0.4359949]
[0.02592623]
[0.54966248]

1回〜3回目で毎回違う値が出ていますが、seedを再度記述すると、その乱数が再現されて出てくることが確認されました。 乱数を使うプログラムを組むときは、プログラムの一番上に1回だけseedを記述するようにしましょう。 多くの場合、乱数を使いたいときは、毎回ばらばらな値が出て欲しいときです。 ここで、乱数を使う直前に毎回seedを置くと、同じ乱数が出てしまいます。 これは不適切ですので、勘違いしないように注意してください。

ヒストグラムによる分布の確認

それでは、生成した乱数が本当に一様分布となっているのか、ヒストグラムを描き確認してみます。

In [6]:
import matplotlib.pyplot as plt
plt.hist(x=Val01, bins=10, rwidth=0.9)
plt.xlabel("x-label")
plt.ylabel("y-label")
plt.title("histogram")
Out[6]:
Text(0.5, 1.0, 'histogram')

ビンを10にしてヒストグラムを書いたところ、ひとつのビンが100個くらいデータが集まっていることを確認できます。 乱数は1000個で1つのビンあたり100個のデータが集まっているので、確かに、0以上1未満の間で同程度の確率によりデータが発生していそうなことを確認できます。

範囲の指定

0以上1未満の一様分布に従う乱数の生成方法についてはわかりました。ただし、ときとしてa以上b未満の乱数が欲しい場合もあります。これを実現するには、以下のように記述する必要があります。

In [7]:
RangeMin=5  # ここから
RangeMax=10 # ここまでの乱数が欲しい
Val02 = (RangeMax-RangeMin) * np.random.rand(1000) + RangeMin

plt.hist(x=Val02, bins=10, rwidth=0.9)
plt.xlabel("x-label")
plt.ylabel("y-label")
plt.title("histogram")
Out[7]:
Text(0.5, 1.0, 'histogram')

多次元の一様乱数

引数を2つ入れると、多次元の一様乱数を生成してくれます。 例えば以下のコードは、1000*1000の一様乱数を生成します。

In [8]:
Val02 = np.random.rand(100,100)
print(np.shape(Val02))
(100, 100)

以上、

  • 0以上1未満の一様分布に従う乱数生成
  • a以上b未満の一様乱数に従う乱数生成
  • 多次元の一様分布に従う乱数生成
  • 乱数シードの固定方法

について述べました。なんでやるのかよくわからないかもしれませんが、データ分析の際、乱数を使用することはかなり多いです。ぜひマスターしてください。