【Python】確率分布とプログラム実装

<h1>はじめに</h1>
今回は、初学者向けに二項分布や正規分布などの確率分布関連の基本知識とそれらに関するPythonでの実装方法について説明していきます！

<h1>離散分布と連続分布</h1>
まず、初めに離散分布と連続分布について説明します。
基本的に、多くの統計データはこれらの二つのカテゴリーに分類される。<br>
<dl>
  <dt>離散分布：データが特定の離散的な値を取る分布　→　ある程度値が決まっているイメージ</dt>
  <dd>例：二項分布・ポワソン分布</dd>
  <dd>使用例：コインの表裏・サイコロの出目(1~6)・不良品の数 (何個中何個が不良品)</dd>
  <br>
  <dt>連続分布：データが連続的な値を取る分布　→　細かく値を刻んでるイメージ</dt>
  <dd>例：正規分布・一様分布・指数分布</dd>
  <dd>使用例：身長・体重（165.5cm, 57.1kg）・気温 (23.4℃)・時間（6.4秒）</dd>
</dl>
<br>
今回は二項分布と正規分布をメインに説明していきます！

<h1>二項分布と正規分布</h1>
<h3>二項分布</h3>
<dl>
  <dt>  二項分布 ：一定回数のベルヌーイ試行で、ある事象が起こる回数を表す確率分布</dt>
  <dd>例：サイコロの表裏（「表」か「裏」）・くじ引き（「アタリ」か「ハズレ」）</dd>
  
:::note info
<strong>ベルヌーイ試行</strong>
ベルヌーイ試行とは、結果が「成功」か「失敗」の2つに分かれる確率試行
→コインの表裏はそれぞれ表(成功)・裏(失敗)の2通りの結果が得られる。
:::
　<dt>二項分布の表現</dt>
ベルヌーイ試行を複数回行ったときに「成功する回数」を確率的に表す分布なので、以下のように表せる。
$$
X \sim B(n, p)
$$
確率変数 $ X \sim B(n, p) $ は...

- $ n $ は試行の回数 (→ 何回繰り返したのか)
- $ p $ は1回の試行で成功する確率 

この表現によって「確率変数$X$は試行回数$n$,確率$p$の二項分布に従う」と表すことができる！
　<dd>実例：コイントスを100回行った。この時、表が55回、裏が45回出た。
 → コイントスの二項分布は $ X \sim B(100, 0.55) $というふうに表すことができる！</dd>
      <div style="text-align: right;">
      ( $ p = \frac{55}{100} = 0.55 $)
      </div>
       
 :::note info
二項分布の表現は頻出なので、$ X \sim B(n, p) $  だけ覚えておこう！
:::
<br> 
　<dt>二項分布の確率関数</dt>
$$
P(X = k) = \binom{n}{k} p^k (1 - p)^{n - k}
$$

- $ k $ は成功する回数（0 から$ n $ までの整数）
- $ \binom{n}{k} $ は「組み合わせ」の数であり、次のように表される：

$$
\binom{n}{k} = \frac{n!}{k!(n - k)!}
$$

この式は、「$ n $ 回の試行でちょうど $ k $ 回成功する確率」を求めるためのもの。

:::note warn
二項分布の確率関数はそこまで重要度は高くないので、仕組みだけ覚えておこう！
:::
<br> 

---
<h3>正規分布</h3>
<dl>
  <dt>  正規分布 ：左右対称の釣り鐘型の連続した確率分布</dt>
　<dt>正規分布の特性</dt>
 
 - 平均値(μ)を中心とした左右対称の釣り鐘型のグラフ
 - $x$軸が漸近線
 - 平均値・中央値・最頻値が一致する

　<dt>正規分布の表現</dt>
$$
X \sim N(\mu , \sigma^2)
$$
正規分布には特徴的な要素として、**平均（$\mu$）** と **分散（$\sigma^2$）** がある。これらは分布の位置や形状を決定する。

- **平均（$\mu$）**：データの中心の位置を表す
- **分散（$\sigma^2$）**：データの広がりの大きさ表す





この表現によって「確率変数$X$は平均$\mu$, 分散$\sigma^2$の正規分布$N$に従う」と表すことができる！

:::note info
正規分布の表現は頻出なので、$ X \sim N(\mu , \sigma^2)$は覚えておこう！
:::      

<br> 
　<dt>正規分布の確率関数</dt>
$$
f(x) = \frac{1}{\sqrt{2 \pi \sigma^2}} exp({-\frac{(x - \mu)^2}{2 \sigma^2}})
$$
<br>

$ exp(x)$ は指数関数 $e^{x}$ を表しているので、以下のような形でも表現することができる。
$$
f(x) = \frac{1}{\sqrt{2 \pi \sigma^2}} e^{-\frac{(x - \mu)^2}{2 \sigma^2}}
$$

この式は、確率変数 $ X $ が値 $ x $ を取る確率密度を表している。

:::note info
正規分布の確率密度関数は頻出なので、$f(x) = \frac{1}{\sqrt{2 \pi \sigma^2}} e^{-\frac{(x - \mu)^2}{2 \sigma^2}}$は覚えておこう！
:::   

　<dt>正規化と標準正規分布</dt>
 - **標準化**：データを標準正規分布に変換するために行う操作
 →標準化には以下の式を用いて、計算する。

 $$
 Z = \frac{X - \mu}{\sigma}
 $$

 - **標準正規分布** ：標準正規分布は平均が$0$、標準偏差が$1$の正規分布（ガウス分布）
 →データを標準正規分布に変換することで、標準正規分表を利用して、確率を求めることができるようになる！
 <img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741767/d7ff8458-7c70-16b8-6859-e1ba1490a595.png">

<br> 

<h1>二項分布と正規分布のプログラム</h1>

<h4>二項分布とプログラム</h4>
ここでは、二項分布の例題を通して、プログラムの実装の方を軽くやっていきます。
<h6>例題1 - 問題</h6>
ある工場では製品の不良率が 5% です。製品を 20 個ランダムに選んだときに、以下の確率を求めてください。

1. **不良品が 2 個以下である確率**
2. **不良品が 1 個以上 3 個以下である確率**
3. **不良品が 4 個以上である確率**

<h6>例題1 - 解説</h6>
この問題では、成功確率 $ p=0.05 $ で試行回数 $ n=20 $ の二項分布 $ B(n, p) $ に従う。

確率変数$ X $ を「20 個の製品中の不良品の個数」とすると、$ X $は次のように表される

$$
X \sim B(20, 0.05)
$$
以下に確率を求めるプログラムを記載する。

```Python:Binom1.py
import numpy as np
from scipy.stats import binom
from scipy.stats import norm

n = 20      # 試行回数
p = 0.05    # 成功確率

# 1. 不良品が2個以下である確率
prob_2_or_less = binom.cdf(2, n, p)

# 2. 不良品が1個以上3個以下である確率
prob_1_to_3 = binom.cdf(3, n, p) - binom.cdf(0, n, p)

# 3. 不良品が4個以上である確率
prob_4_or_more = 1 - binom.cdf(3, n, p)

# 結果の表示
print("1. 不良品が2個以下である確率 =", prob_2_or_less)
print("2. 不良品が1個以上3個以下である確率 =", prob_1_to_3)
print("3. 不良品が4個以上である確率 =", prob_4_or_more)
```
このプログラムは、二項分布を累積分布関数として、ある特定の範囲の確率を求めることができることを利用して、特定の条件を満たした範囲の確率を算出するプログラムである。

:::note info
<strong>累積分布関数とは</strong>
累積分布関数は確率変数$X$がある値$x$以下（$X \leq x$）の値となる確率
→範囲内の最小値からある値$x$までのそれぞれの確率が全て含まれている状態
:::   
<h6>例題1 - 解答</h6>
1. 不良品が2個以下である確率 = 0.9245163262115037 →92.4%程度<br>
2. 不良品が1個以上3個以下である確率 = 0.6256125515716942　→62.5％程度<br>
3. 不良品が4個以上である確率 = 0.01590152601976358 →1.5%程度<br>

<h6>scipy.stats.binomの仕様</h6>
解説内のプログラムで使用した binom.cdf関数について説明する。この関数は二項分布の累積分布関数を計算するためのもので、scipy.statsライブラリからインポートして使用することができる。

```binom.cdf```の仕様は以下の通りである。

- 関数名：binom.cdf($k$, $n$, $p$)
- 第1引数：成功回数の上限（→成功した回数が$k$回以下である確率）[$ int $]
- 第2引数：試行回数（→$n$回、試行を繰り返す。）[$ int $]
- 第3引数：1回の試行における成功確率（→成功は$p$、失敗は$(1-p)$の確率）[$ float $]
- 返り値：$n$回行なった際に成功した回数が$k$回以下の確率   [$ float $]

```binom.cdf```関数を使用する方法を具体例を交えて、以下に例示する。

<strong> 例</strong>：コインを10回投げて、「表」が3回以下だけ出る確率を求める場合
→成功した回数が3回以下：$k = 3$
→10回、繰り返す：$n = 10$
→表と裏は半々の確率：$p = 0.5$
 したがって、```binom.cdf(3, 10, 0.5)```のようにすれば、3回以下の成功確率が返ってくる。

***
<h4>正規分布とプログラム</h4>
 ここでは、正規分布の例題を通して、プログラムの実装の方を軽くやっていきます。
 
<h6>例題2 - 問題</h6>
平均が50、標準偏差が10の正規分布に従うデータからランダムに1つの値を取ったとき、その値が60以上である確率を求めなさい。
<h6>例題2 - 解説</h6>
この問題では、平均$\mu$ = 50 , 標準偏差$\sigma$ = 10 の正規分布に従うので、確率分布$X$を「データからランダムに取得された1つの値」とすると、$X$は以下のように表せる。

$$
X \sim N(50, 10^2)
$$

:::note info
正規分布は $X\sim N(平均値 ,分散  )$ として表現される。そのため、標準偏差が与えられた場合は、分散に変換する必要がある。標準偏差と分散には以下の関係がある。
$$
(標準偏差)^2 = 分散
$$
:::  

以下に、確率を求めるプログラムを記載する。

```Python: Norm2.py
from scipy.stats import norm

mean, std_dev = 50, 10
prob = 1 - norm.cdf(60, mean, std_dev)
print(f"例題の答え: 値が60以上である確率は {prob:.4f} ")
```
このプログラムでは、全事象の確率から「値が60未満である確率」を引くことで、確率を求めるプログラムである。
<h6>例題2 - 解答</h6>
例題の答え: 値が60以上である確率は 0.1587 　→ 15.87%程度

<h6>scipy.stats.normの仕様</h6>
解説内のプログラムで使用した norm.cdf関数について説明する。この関数は正規分布の累積分布関数を計算するためのもので、scipy.statsライブラリからインポートして使用することができる。

```norm.cdf```の仕様は以下の通りである。
- 関数名：norm.cdf($x$, $mean$, $scale$)
- 第1引数：確率を求めたい値　[$ float $]
- 第2引数：平均値（$\mu$）[$ float $]
- 第3引数：標準偏差（$\sigma$）[$ float $]
- 返り値：$n$回行なった際に成功した回数が$k$回以下の確率   [$ float $]

```norm.cdf```関数を使用する方法を具体例を交えて、以下に例示する。

:::note warn
普通の正規分布はnorm.cdf($x$, $mean$, $scale$)で確率を算出することができるが、標準正規分布の場合は、平均値$\mu$ = $0$ , 標準偏差$\sigma$ = 1 で固定となることに注意しよう！
:::  

<strong> 例</strong>：あるテストの得点が正規分布に従い、平均が70点、標準偏差が10点とする。このとき、80点以下を取る確率を求めよ。

→確率変数：$X = 80$
→平均：$\mu = 70$
→標準偏差：$\sigma = 10$

 したがって、```norm.cdf(80, 70, 10)```のようにすれば、3回以下の成功確率が返ってくる。

<h1>終わりに</h1>
今回は初学者向けに簡単に二項分布と正規分布について説明してきました。

拙い文章で申し訳ないのですが、少しでも確率分布への理解が進めば幸いです。

知識的に分からないことやプログラムで不明なところがあれば、ぜひ質問していただけると助かります