0からはじめるPython ~ポアソン分布を使って問題を解く~

# はじめに


こんにちは、現在0からPythonを学んでいる初心者エンジニアです。
この投稿は私が学んだことのアウトプットの場として、そして私と同じ初心者エンジニアさんの少しでも役に立てればと思い、投稿しています。私自身も全くの初心者なので、感想やアドバイスあれば、気軽にコメント頂けると幸いです。

# ポアソン分布に関する演習問題

今回は前回説明したポアソン分布に関する演習問題を実際に解いていこうと思います。
ポアソン分布の説明に関しては前回の記事「[0からはじめるPython ~ポアソン分布とは~](https://qiita.com/0karaPython/items/d6d1edfbbf045f64b4bb)」を参考にして頂ければと思います。
それでは早速演習問題を解いていきましょう。
今回は2つの問題を二項分布でのアプローチ,ポアソン分布でのアプローチの2種類の解き方で解説していきます。

#### 演習問題1

```
演習問題1
サイコロを10回振って1が出る回数が2回以下の確率を求めよ。
```
**解き方**
この問題は平均して0.166$\cdots\left(\frac{1}{6}\right)$の確率で起こる事象が10回のうち2回以下しか起こらない確率なので次の3つの確率の和を求める必要があります。
* 10回中2回1が出る確率確率 P(X=2)
* 10回中1回1が出る確率確率 P(X=1)
* 10回中0回1が出る確率確率 P(X=0)


**二項分布でのアプローチ**
二項分布の公式
```math
P\left(X=k\right)={}_{n} C_k p^k\left(1-p\right)^{n-k}

```
を用いて $n=10,p=\frac{1}{6}$ なので

* 10回中2回1が出る確率確率 P(X=2)
```math
P\left(X=2\right)={}_{10} C_2\left(\frac{1}{6}\right)^2\left(\frac{5}{6}\right)^8=\frac{45\cdot 5^8}{6^{10}}=0.290\cdots

```
* 10回中1回1が出る確率確率 P(X=1)
```math
P\left(X=1\right)={}_{10} C_1\left(\frac{1}{6}\right)^1\left(\frac{5}{6}\right)^9=\frac{10\cdot 5^9}{6^{10}}=0.323\cdots

```
* 10回中0回1が出る確率確率 P(X=0)
```math
P\left(X=0\right)={}_{10} C_0\left(\frac{1}{6}\right)^0\left(\frac{5}{6}\right)^{10}=\frac{5^{10}}{6^{10}}=0.161\cdots

```
よって、$P\left(X=2\right)+P\left(X=1\right)+P\left(X=0\right)=0.775\cdots$ と計算できます。

**ポアソン分布でのアプローチ**
ポアソン分布の公式
```math
P(X=k)=e^{-\lambda}\frac{\lambda^k}{k!}
```

を用いて $\lambda=10\cdot0.166\cdots =1.66\cdots$ なので

* 10回中2回1が出る確率確率 P(X=2)
```math
P\left(X=2\right)=e^{-1.66\cdots}\frac{\left(1.66\cdots\right)^2}{2!}=\frac{(0.188\cdots)\cdot(2.77\cdots)}{2}=0.262\cdots

```
* 10回中1回1が出る確率確率 P(X=1)
```math
P\left(X=1\right)=e^{-1.66\cdots}\frac{\left(1.66\cdots\right)^1}{1!}=(0.188\cdots)\cdot(1.66\cdots)=0.314\cdots

```
* 10回中0回1が出る確率確率 P(X=0)
```math
P\left(X=0\right)=e^{-1.66\cdots}\frac{\left(1.66\cdots\right)^0}{0!}=0.188\cdots

```
よって、$P\left(X=2\right)+P\left(X=1\right)+P\left(X=0\right)=0.765\cdots$ と計算できます。

**演習問題1のポアソン分布でのアプローチのコード**
```Python
from scipy.stats import poisson  # ポアソン分布を利用する


lamb = 5.0/3.0  # 平均1.6666回起こる事象だと定義
psum = 0  # 今後使う関数の初期値を定義

for k in [0,1,2]:  # kが0から2まで繰り返し処理を行う
    p = poisson.pmf(k, lamb)  # 平均lamb回発生する事象がk回発生する確率（これがポアソン分布）
    psum += p  # psumにpをたす

print('p =', psum)  # k=1,2,3の場合の合計を足す
```
**実行結果**
```Python
p = 0.7659955003967784
```

ここで両者の解答に多少のずれが生じてしまいました。このずれの原因は試行回数に起因すると考えられます。理由は[前回の記事](https://qiita.com/0karaPython/items/d6d1edfbbf045f64b4bb)で述べた、ポアソン分布の導出は


>ある一定期間をn等分し、この期間内に事象が起こる期待値が $\lambda$ 回だとすると、等分された各範囲に事象が起こる確率は $p=\frac{\lambda}{n}$ なので、この事象の発生確率は、二項分布 $B(n,\frac{\lambda}{n})$ に従い$P(X=k)={}_n C_k \left( \frac{\lambda}{n}\right)^k\left( 1-\frac{\lambda}{n}\right)^{n-k}$ となります。

上記の分割数nが限りなく大きい時、要するに$（n→\infty)$の時、
```math
\lim_{n\to\infty}P(X=k)=e^{-\lambda}\frac{\lambda^k}{k!}
```
が成り立つので、分割数をさらに大きくすることで、ポアソン分布の値はより二項分布の値に近づきます。
では次は分割数が大きくなる問題を解きます。


#### 演習問題2

```
演習問題2
あるスマホゲームのガチャのSランクのキャラの排出率が2%とする。このガチャを単発で100回回した時、Sランクのキャラが3体以上出る確率を求めよ。
```
**解き方**
この問題は平均して0.02 $\left(\frac{1}{50}\right)$ の確率で起こる事象が100回のうち3回以上起こる確率なので、余事象を用いて全体から次の3つの確率の和を引き求める必要があります。
* 100回中2回Sランクのキャラが出る確率確率 P(X=2)
* 100回中1回Sランクのキャラが出る確率確率 P(X=1)
* 100回中0回Sランクのキャラが出る確率確率 P(X=0)
**二項分布でのアプローチ**
二項分布の公式
```math
P\left(X=k\right)={}_{n} C_k p^k\left(1-p\right)^{n-k}

```
を用いて $n=100,p=\frac{1}{50}$ なので

* 100回中2回Sランクのキャラが出る確率確率 P(X=2)
```math
P\left(X=2\right)={}_{100} C_2\left(\frac{1}{50}\right)^2\left(\frac{49}{50}\right)^{98}=0.273\cdots

```

* 100回中1回Sランクのキャラが出る確率確率 P(X=1)
```math
P\left(X=1\right)={}_{100} C_1\left(\frac{1}{50}\right)^1\left(\frac{49}{50}\right)^{99}=0.270\cdots

```
* 100回中0回Sランクのキャラが出る確率確率 P(X=0)
```math
P\left(X=0\right)={}_{100} C_0\left(\frac{1}{50}\right)^0\left(\frac{49}{50}\right)^{100}=0.132\cdots

```
よって、$1-\left(P(X=2)+P(X=1)+P(X=0)\right)=0.323\cdots$ と計算できます。

**ポアソン分布でのアプローチ**
ポアソン分布の公式
```math
P(X=k)=e^{-\lambda}\frac{\lambda^k}{k!}
```

を用いて $\lambda=100 \cdot 0.02=2$ なので


* 100回中2回Sランクのキャラが出る確率確率 P(X=2)
```math
P\left(X=2\right)=e^{-2}\frac{\left(2\right)^2}{2!}=\frac{(0.135\cdots)\cdot4}{2}=0.270\cdots

```
* 100回中1回Sランクのキャラが出る確率確率 P(X=1)
```math
P\left(X=1\right)=e^{-2}\frac{\left(2\right)^1}{1!}=(0.135\cdots)\cdot2=0.270\cdots

```
* 100回中0回Sランクのキャラが出る確率確率 P(X=0)
```math
P\left(X=0\right)=e^{-2}\frac{\left(2\right)^0}{0!}=0.135\cdots

```
よって、$1-\left(P(X=2)+P(X=1)+P(X=0)\right)=0.323\cdots$ と計算できます。

**演習問題2のポアソン分布でのアプローチのコード**
```Python
from scipy.stats import poisson  # ポアソン分布を利用する


lamb = 2  # 平均2回起こる事象だと定義
psum = 0  # 今後使う関数の初期値を定義

for k in [0, 1, 2]:  # kが0から2まで繰り返し処理を行う
    p = poisson.pmf(k, lamb)  # 平均lamb回発生する事象がk回発生する確率（これがポアソン分布）
    psum += p  # psumにpをたす

print('p =', 1-psum)  # 余事象なので全体からk=0,1,2の場合の合計を引く
```
**実行結果**
```Python
p = 0.3233235838169365
```

上記より、演習問題2の場合はほとんど解は一致しました。ただ、二項分布の場合は100乗の値等を計算しなくてはいけないため、時間がかかります。なので、単位時間の分割数が大きい時はポアソン分布を使った方が効率の良い計算ができるでしょう。
# まとめ
以上が、ポアソン分布に関する演習問題を実際に解いた例になります。
最後まで読んで頂きありがとうございました。引き続き私と一緒に研鑽していきましょう。

# 参考
橋本洋志,牧野浩二."データサイエンス教本 Pythonで学ぶ統計分析・パターン認識・深層学習・信号処理・時系列データ分析".オーム社,2018
[0からはじめるPython ~ポアソン分布とは~](https://qiita.com/0karaPython/items/d6d1edfbbf045f64b4bb)