見出し画像

文科省研修用教材を検討する(6)シミュレーション

 昨年,「高等学校「情報Ⅰ」文科省研修用教材を検討する(1)〜(5)」を書いた。
その後,Pythonを勉強して,少しわかるようになった。
わかるようになってくると,今まで見えていなかったものが見えてくるようになる。
昨年記事を書いたときは,シミュレーションに関してはあまり検討していなかった。書かれているコードを批判するだけの知識がなかったからだ。
今年になって,matplotlib について調べた。それで知識が増えて,見えてきたものがある。

 学習16の確率モデル。モデル化とシミュレーションは現行教科書にも載っていて,出版社によって異なるが,硬貨投げやモンテカルロ法による円周率の近似などがある。教員研修用教材にはさいころ投げとモンテカルロ法があるのだが,そのコードをあらためて見て,まてよ,という気持ちがしている。

まず,さいころ投げ。このようなテーマだ。

画像1

 「4人でグループを作り・・」とあるのだから,実際にさいころを投げて,表計算ソフトで集計する,という想定で,その上で,これをコンピュータでシミュレートする,ということなのだろう。
 そのあとのコードでは,100回乱数を発生して,1から6の整数(目)が出現した回数を求めている。

画像2

つぎに,これを視覚化するために,matplotlib を使って棒グラフにしている。

画像3


これはこれでいいのだが,コンピュータでシミュレーションをするなら,
(1)「数えた数値は毎回異なる」だけではなく,何回か試行を行って,その結果をリストにして見る。
(2) さいころを投げる回数を増やし,度数分布の変化を見る。
ということをやるべきだろう。
(1) では,ばらつきの具合が見やすくなるし,(2) では,どれも1/6 に近くなってくることが期待される。(そうなるかどうかをシミュレーションする)
これは,演習3として,次のものが示されているが,意味のわかりにくい課題である。

画像4


 次は,コードについて。「度数をカウントして棒グラフにする」は確かによいが,カウントしなくても hist() 関数でヒストグラムが描けるし,度数分布もわかる,ということに言及すべきだろう。実際に授業でそれをするかどうかは別として,教員なら知っておきたい。「ヒストグラムの描き方」を学ぶのでなく,出てきた結果を分析するならなおさらだ。ちなみに筆者は,今まではRを使っていて,やはり hist() 関数でヒストグラムを作成し,階級境界値を変える,箱ひげ図と比較する,といった実習を行っている。
 hist() を使うなら次のようになる。matplotlib のhist() 関数には戻り値があって,その中に度数のリストが入っているから,カウントする必要はない。

import numpy as np
import matplotlib.pyplot as plt
me = np.random.randint(1, 7, 100)
k = np.arange(0.5, 7.5, 1)
ret = plt.hist(me,bins=k, rwidth=0.8)
print('度数は1から順に', ret[0])
plt.title('SAIKORO SIMURATION')
plt.xlabel("ME")
plt.ylabel('KAISUU')
plt.show()

画像5

次にモンテカルロ法。

画像6

 初めに見たときに「点が大きいな」と思っていた。面積の比が原理なのだから,点はもっと小さくして,点の数も多くして埋めていきたい。
 それと,「散布図」であるが,違和感はないだろうか。
 そもそも,「散布図」は何の目的で使うのか。2種類のデータについて,その関係(相関関係)を調べるために使うのではないか。入試における内申書と学力検査の相関,試験の科目間の相関,体力テストの朱も区間の相関,etc。
 乱数でとったx座標とy座標の相関などまったく無意味だから,散布図を描くというのはおかしい。単に,座標平面上にプロットするべきだ。

import numpy as np
import matplotlib.pyplot as plt
plt.axis('equal')
plt.axhline(0, lw=1.5, color='k') 
plt.axvline(0, lw=1.5, color='k')
kaisu = 5000
incount = 0
for i in range(kaisu):
   x = np.random.random()
   y = np.random.random()
   if x**2 + y**2 < 1.0:
       incount += 1
       plt.plot(x, y, 'ro', markersize=0.5) 
   else:
       plt.plot(x, y, 'bo', markersize=0.5) 
print("円周率:", incount*4.0/kaisu) 
plt.title("Monte Carlo method")
plt.show()

画像7

また,「このプログラムを何度か実行してみると,毎回結果が異なることがわかる。また,点の総数を増やすほど,結果が円周率に近づくことも分かる。」という説明があるなら,それもやってみるべきだろう。
 次のコードは,1000個の点から始めて,1000個ずつ増やしていったときの様子を示す。

import numpy as np
import matplotlib.pyplot as plt
kaisu = 1000
result = []
for n in range(20):
   incount = 0
   for i in range(kaisu):
       x = np.random.random()
       y = np.random.random()
       if x**2 + y**2 < 1.0:
           incount += 1
   result.append([kaisu, incount, 4.0*incount/kaisu])
   kaisu += 1000
for i in result:
   print(i)
plt.show()

画像8

もちろん,これらを全部テキストに載せるのでは分量が多いかもしれない。しかし,研修ではできるだろうし,教員としてはできることを知っておく必要はあるだろう。少なくとも,ヒストグラムが描ける関数があることは知っておきたいし,散布図としての意味がない散布図を描くようなおかしなことはするべきではない。