np.randomのメモ
np.randomについて調べたことをメモしておく。
np.random.Generator() の利用が推奨されている。
これは、オブジェクトごとにseed値を管理できるので、seed値がどこかで変更され影響を受けることを避けることができる。これは、ありがたい。
import numpy as np
# 乱数の生成 np.random.default_rng(seed)
#
# seed
# 指定すると、毎回同じ系列を使用した乱数が生成される(動作確認時は便利)
# seed値は、正の整数 np.random.default_rng(42)
#
# デフォルトのビット生成器は PCG64
# 乱数生成器を変更するときは、np.random.Generator()
# from numpy.random import Generator, PCG64
# rng = Generator(PCG64())
# rng.standard_normal()
# ビット生成器は PCG64, MT19937, Philox など
#
# np.random.Generator()の利用を推奨
# オブジェクトごとで、seedを管理できる
# 従来の方法だと、seed値がどこかで変更されると影響を受ける(発見しづらいバグとなる)
rng = np.random.default_rng(seed=42) # シードを固定
# --------------------------------------------------
# 一様分布の乱数
# --------------------------------------------------
# 整数 .integers(low, high, size)
# low以上、high未満 sizeは個数
# low=0 は省略でき、0以上high未満
# endpoint=True で、high以下
rnd_int=rng.integers(low=0, high=100, size=10)
print(type(rnd_int),rnd_int) # <class 'numpy.ndarray'> [ 8 77 65 43 43 85 8 69 20 9]
# float( 0.0以上 1.0未満 ) .random(size)
print(rng.random()) # 0.9756223516367559
print(rng.random(3)) # [0.7611397 0.78606431 0.12811363]
print(rng.random((2,3))) # [[0.45038594 0.37079802 0.92676499]
# [0.64386512 0.82276161 0.4434142 ]]
# 乱数値の範囲指定 .uniform(low, high, size)
# low以上 high未満 size=個数
print(rng.uniform(-5.0, 5.0, 3)) # [-2.72761278 0.54584787 -4.36182744]
# --------------------------------------------------
# 正規分布の乱数
# --------------------------------------------------
# 標準正規分布 .standard_normal(size)
print(rng.standard_normal(5)) # [ 0.8784503 -0.04992591 -0.18486236 -0.68092954 1.22254134]
# 正規分布 .normal(loc, scale, size)
# loc: 平均 (μ), scale: 標準偏差 (σ), size: データ数
print(rng.normal(loc=50, scale=10, size=5)) # [48.45470518 45.71672178 46.4786645 55.32309186 53.65444064]これを利用して、モンテカルロ法による円周率を計算させてみた。
グラフの作成は関数とした。
1回の計算に利用するサンプル数をランダムに設定し、1000個分の円周率を計算させた。サンプル数を固定するより、いい結果となった。
import matplotlib.pyplot as plt
# 日本語Font対応 ['IPAexGothic']
import matplotlib_fontja
def graph2(g_data,g_labels,g_true):
fig, axes = plt.subplots(1, 2, figsize=(10, 4)) # 1行2列のレイアウト
x=np.arange(1, len(g_data)+1, dtype=int)
y=g_data
m=np.mean(y).round(6) # 平均
s=np.sqrt(np.mean((y-m)**2)).round(7) # 標準偏差
e=np.sqrt(np.mean((y-g_true)**2)).round(7) # 誤差 RMSE
print(f'平 均 = {m}\n標準偏差 = {s}\n RMSE = {e}')
# ヒストグラムの表示
axes[0].hist(y, bins=15, color='blue', edgecolor='k', alpha=0.5) # ヒストグラム
axes[0].axvline(x=m,color='red',alpha=0.5,linestyle='--') # 平均
axes[0].axvspan(xmin=m-s,xmax=m+s,color='red',alpha=0.2) # 標準偏差 -s ~ s
axes[0].set_title(g_labels[0])
axes[0].set_xlabel(g_labels[1])
axes[0].set_ylabel(g_labels[2])
axes[0].grid(True)
# 誤差の分布
axes[1].axhline(y=g_true,color='red',alpha=0.5,linestyle='--') # 真値
axes[1].axhspan(ymin=g_true-e,ymax=g_true+e,color='red',alpha=0.2) # 誤差 -e ~ e
axes[1].scatter(x,y,marker='o',s=3)
axes[1].set_title(g_labels[3])
axes[1].set_xlabel(g_labels[4])
axes[1].set_ylabel(g_labels[5])
axes[1].grid(True)
plt.tight_layout() # グラフの間隔を自動調整
plt.show() import numpy as np
rng = np.random.default_rng(seed=42) # シードを固定
data=np.array([]) # 円周率を保存する変数
for _ in range(1000): # 円周率を1000個計算
n=rnd_int=rng.integers(low=100, high=1000000, size=1)[0] # サンプル数をランダムに選ぶ
# モンテカルロ法
x=rng.random(n)
y=rng.random(n)
z=x**2+y**2 # 原点から点(x,y)までの距離
count_in=len(z[z<=1]) # 半径1の円内にある点の個数
data=np.append(data,count_in / n * 4.0) # 円周率
# グラフ
g_labels=['度数分布','円周率','度数','モンテカルロ法による円周率の分布','データ数','円周率']
Pi=3.14159265358
graph2(data,g_labels,Pi)
'''実行結果
平 均 = 3.141565
標準偏差 = 0.0053029
RMSE = 0.005303
'''
