統計学入門③ 確率とScipy

f:id:monozukuri-bu:20190513232541j:plain

こんにちは。ふじもんです。
GWに実家に帰ったら子猫がいました。
調子に乗って構い過ぎたらブチ切れられて手をズタボロにされました。
痛い。

さて、今回の記事では確率についてのお話と、確率の計算をPythonで簡単にやってしまおうというお話をしたいと思います!

確率、組み合わせ、順列

そもそも確率とは、

ある事象の起こりやすさを割合であらわしたもの

のことを言います。
その確率を計算するのに出てくるのが、 中学校の時に習った組み合わせや順列。

では実際に「組み合わせ」と「順列」とはどのように違うのでしょうか?

組み合わせと順列の違い

組み合わせ(combination)は

n個の物の中からr個を取り出した時の組み合わせの数

のことを言います。
それに対し、順列(Permutation)とは

n個の物の中からr個を取り出して一列に並べた数

のことを言います。
この二つの大きな違いは、 「順番を区別するかどうか」 です。

言葉だけ聞いてもわかりにくいため、例えを一つ出してみます。

「1」「2」「3」と書かれた3枚のカードがあったとします。
この中から2枚のカードを選んだ時、組み合わせと順列では何通りの選び方があるでしょうか?

この場合、組み合わせは「組み合わせの数」のことを言いますので、
「1」と「2」
「1」と「3」
「2」と「3」
3通りです。
組み合わせは、以下の式から導き出せます。


{}_{n}C_{r}=\frac{n!}{r!(n-r)!}

そして、順列では組み合わせに加え「一列に並べた数」のことを言いますので、
順番を考慮しなければなりません。
なので、組み合わせでは
「1」と「2」=「2」と「1」
でしたが、順列では順番を考慮しなければならないので、「1」「2」のカードの順番が入れ替わった時点で別物扱いになります。
そのため、順列は
「1」と「2」
「1」と「3」
「2」と「1」
「2」と「3」
「3」と「1」
「3」と「2」
6通りになります。
順列は、以下の式から導き出せます。


{}_{n}P_{r}=\frac{n!}{(n-r)!}

順列は順番を考慮しなければならない分、組み合わせより数が増えますね。

事象に関する考え方

さて、組み合わせと順列はわかったが、じゃあそれと確率って何が関係あるの?
というお話が出てきた時に、欠かせないのが 「事象」 です。
事象とは、

試行の結果として起こる事柄

のことを言います。
ちなみに試行とは、

同じ状態のもとで繰り返し行なうことができ,その結果が予想通りになるかどうか実験や観察を行い試すこと

を言います。
例えば、 「3枚のうちから1枚カードを引いた結果、2を引いた」 ということがあった場合、
「3枚のうちから1枚カードを引く」 ことが試行で、
「カードを引いた結果、2を引いた」 ことが事象です。

そして、確率を計算するには起こりうる事象を全て考えた上で計算する必要があります。
上記の例だと、「2のカードを引く」以外にも、「1のカードを引く」「3のカードを引く」事象が考えられます。
起こりうる全ての事象を全事象といい、この場合は全事象は3通りあります。

この全ての事象を計算する上で組み合わせや順列を使用し、確率の計算へと繋がっていきます。

基礎的な確率の計算

今までのことを踏まえ、確率を計算してみましょう。

「1」が3枚、「2」が2枚、「3」が1枚の計6枚のカードが用意されていたとします。
その中で、6枚のカードの中から2枚同時に引き、「1」と「3」である確率を計算してみます。

この場合は同時に引く確率であり、順番は関係ありません。
そのため、組み合わせの計算を行います。

まず、組み合わせの全事象の数を計算します。
6枚のカードの中から2枚引く組み合わせの数は


{}_{6}C_{2}=\frac{6!}{2!(6-2)!} = \frac{6\times5\times4\times3\times2\times1}{2\times1\times4\times3\times2\times1} = 15

となります。

次に、「1」と「3」を同時に引く事象の数を計算します。
「1」は3枚含まれているので、「1」を引くのは


{}_{3}C_{1}=\frac{3!}{1!(3-1)!} = \frac{3\times2\times1}{1\times2\times1} = 3

「3」は1枚のみなので、「3」を引くのは


{}_{1}C_{1}=\frac{1!}{1!(1-1)!} = \frac{1}{1\times1} = 1

「1」を「3」同時に引く事象の数は


3\times1 = 3

となります。

全事象15通りのうち、「1」を「3」同時に引くのは3通りのため、


\frac{3}{15} = \frac{1}{5} = 0.2

となり、「1」が3枚、「2」が2枚、「3」が1枚の計6枚のカードの中から「1」を「3」同時に引く確率は 20% と計算できます。

期待値の求め方

期待値とは、起こりうるあたいの平均値のことを言います。
と言われても、やっぱりイメージがつきにくいと思うので、またひとつ例を出して考えてみましょう。
「1」が3枚、「2」が2枚、「3」が1枚の計6枚のカードでゲームを行います。
「3」のカードを引いたら10000円が貰える
「2」のカードを引いたら1000円が貰える
「1」のカードを引いたら5000円を払う

…なかなかギャンブルです。
では実際にこのゲームの期待値はどれほどになるか計算してみましょう。
今回のゲームの条件と確率をまとめると以下のようになります。

カード 1 2 3
金額(x) -5000 1000 10000
確率(p) 3/6 2/6 1/6

そして、期待値は以下の式から導き出せます。


μ=E[X]=p_{1}x_{1}+p_{2}x_{2}+…+p_{n}x_{n}

上記の情報を使って期待値を計算すると、


μ=E[X]=-5000\times\frac{3}{6}+1000\times\frac{2}{6}+10000\times\frac{1}{6}\\
 =-2500+333.33+1666.67\\
 =-500

期待値は-500、つまりこのゲームを繰り返していくと 1回あたり-500円の損失となります。
このゲームに繰り返し挑戦すると損してしまいますね。

ただし、「繰り返し行うと1回あたり500円の損失の見込み」であり、
「1回やれば確実に500円損する」というわけではありません。
(そもそもこの条件では1回きりで500円の損失はありえない)

繰り返し試行した結果の平均が期待値、ということが重要です。

Scipyで簡単に計算する方法

さてここまで長々と計算のお話でしたが、やっと技術ブログらしいところまでたどり着きました!
今までしてきた計算、そこまで難しくはないですがちょっと面倒に感じてしまいますね。
なんとこのちょっと面倒な計算、Pythonを使用するとさらっと簡単に計算できてしまいます!
嬉しい!!!

今回掲載する情報は、以下の環境で動作確認しています。

Python 3.6.8
numpy 1.16.3
scipy 1.2.1

さて、今回の確率計算のために使った組み合わせと順列の計算を、
PythonのライブラリのひとつであるScipyでパパッとしちゃいましょう。
ちなみにScipyとは、高度な科学計算ができるライブラリです。
統計とかにはもってこいです。

まずは組み合わせでも順列でも出てきたあの「!」 階乗の計算をScipyでやってみます。
序盤で6!=6・5・4… とやっていたのが、Pythonだとなんと

>>> from scipy.special import factorial
>>> factorial(6, exact=True)
720

これだけで!
とっても簡単に計算できちゃいます。
ちなみに階乗を計算する関数factorialに渡すのは整数でも配列でも大丈夫です。
全部返してくれます。

なので、

>>> factorial( [30, 22, 15, 3], exact=True)
array([265252859812191058636308480000000, 1124000727777607680000,
       1307674368000, 6], dtype=object)

配列にしていっぱい渡したら、いっぱい返ってきます。
また、オプションのexactはデフォルトではFalseになっており、Falseの場合は近似値を返します。
正確な値が欲しい場合はexact=Trueと指定してあげましょう。

次に組み合わせと順列の計算をやってみます!
6C2だと分母が2の階乗の〜…とかやっていたのが、Scipyの関数comb permを使うと

>>> from scipy.special import comb, perm
>>> comb(3, 2, exact=True)
3
>>> perm(3, 2, exact=True)
6

拍子抜けするほど簡単。

まとめ

今回は確率に関する基礎的な計算の仕方と、Pythonの高度計算ライブラリScipyを使ったプログラムの書き方を紹介しました!
手計算だと時間がかかるものも、Scipyを使うと簡潔且つあっという間に計算できますね。
今回は基礎的な部分のみでしたが、次ではこの知識を使ったちょっと高度な計算もご紹介します!




ちなみに期待値の計算をしていて、だから人はソシャゲでガチャを回すことをやめられないんだなあとおもいました。
ふじもん