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
'''
円周率を計算した結果のグラフ


いいなと思ったら応援しよう!