畳み込み(convolution)は、2つの独立な確率変数 $X$ と $Y$ が存在したとき、その和 $Z = X + Y$ の分布を導出する方法です。
例えば、2つの正規分布を足したときにどのような分布になるだろう?その確率関数はどのようになるだろう?と考えたときに、畳み込みの考え方が必要になります。
統計学のテキストでは次のような数式で登場することが多いです。
$$ \begin{equation} f_Z(z) = \int_{-\infty}^{\infty} f_X(z – t) f_Y(t) \, dt \end{equation} $$
今回は、確率変数の和の分布を求めるのに必要な畳み込みについて、できる限り図を用いてわかりやすく解説します。
本記事の内容
- 離散分布での畳み込み(サイコロの例)
- 連続分布での畳み込み積分
- 畳み込みの性質
- Python での実装と可視化
前提知識
- 確率変数と確率分布の基本
- 積分の基本
サイコロの例で畳み込みを理解する
2つのサイコロの出目の和
2つの独立なサイコロの出目の合計がどのような分布になるかを考えましょう。
サイコロ1の出目を $X$、サイコロ2の出目を $Y$ とし、$Z = X + Y$ を求めます。
例えば $Z = 7$ になる組み合わせは $(1,6), (2,5), (3,4), (4,3), (5,2), (6,1)$ の6通りで、確率は $\frac{6}{36} = \frac{1}{6}$ です。
一般に、離散確率変数の畳み込みは、
$$ \begin{equation} P(Z = z) = \sum_k P(X = k) \cdot P(Y = z – k) \end{equation} $$
と表されます。
連続分布の畳み込み
連続確率変数 $X, Y$ が独立で、それぞれ確率密度関数 $f_X(x), f_Y(y)$ を持つとき、$Z = X + Y$ の確率密度関数は (1) 式の畳み込み積分で求められます。
導出
$Z = X + Y$ の累積分布関数は、
$$ \begin{align} F_Z(z) &= P(Z \leq z) = P(X + Y \leq z) \\ &= \int_{-\infty}^{\infty} \int_{-\infty}^{z-x} f_X(x) f_Y(y) \, dy \, dx \end{align} $$
$t = x$ と置いて微分すると、
$$ \begin{equation} f_Z(z) = \int_{-\infty}^{\infty} f_X(t) f_Y(z – t) \, dt = (f_X * f_Y)(z) \end{equation} $$
$*$ は畳み込み演算を表します。
具体例: 一様分布の畳み込み
$X \sim U(0,1)$, $Y \sim U(0,1)$ のとき、$Z = X + Y$ の分布は、
$0 \leq z \leq 1$ のとき: $$ f_Z(z) = \int_0^z 1 \cdot 1 \, dt = z $$
$1 < z \leq 2$ のとき: $$ f_Z(z) = \int_{z-1}^1 1 \cdot 1 \, dt = 2 - z $$
これは $[0, 2]$ 上の三角分布になります。
畳み込みの性質
- 交換法則: $f_X * f_Y = f_Y * f_X$
- 結合法則: $(f_X * f_Y) * f_Z = f_X * (f_Y * f_Z)$
- モーメント母関数との関係: $M_{X+Y}(t) = M_X(t) \cdot M_Y(t)$
性質3により、再生性を持つ分布では畳み込みの結果が簡潔に求まります。
Python での実装
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
np.random.seed(42)
n_samples = 200000
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 左上: サイコロ2個の和の分布
ax1 = axes[0, 0]
die1 = np.random.randint(1, 7, n_samples)
die2 = np.random.randint(1, 7, n_samples)
die_sum = die1 + die2
# 理論値
z_values = np.arange(2, 13)
theory_counts = np.array([min(z-1, 13-z) for z in z_values])
theory_probs = theory_counts / 36
ax1.hist(die_sum, bins=np.arange(1.5, 13.5, 1), density=True, alpha=0.5, color='blue', label='Simulation')
ax1.plot(z_values, theory_probs, 'ro-', linewidth=2, markersize=8, label='Theory')
ax1.set_xlabel('Sum of two dice', fontsize=12)
ax1.set_ylabel('Probability', fontsize=12)
ax1.set_title('Convolution: Two Fair Dice', fontsize=13)
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)
# 右上: 一様分布の畳み込み(1, 2, 3個の和)
ax2 = axes[0, 1]
U1 = np.random.uniform(0, 1, n_samples)
U2 = np.random.uniform(0, 1, n_samples)
U3 = np.random.uniform(0, 1, n_samples)
x_range = np.linspace(-0.5, 3.5, 500)
ax2.hist(U1, bins=80, density=True, alpha=0.3, color='blue', label='1 uniform')
ax2.hist(U1+U2, bins=80, density=True, alpha=0.3, color='green', label='2 uniforms (triangle)')
ax2.hist(U1+U2+U3, bins=80, density=True, alpha=0.3, color='red', label='3 uniforms')
ax2.plot(x_range, norm.pdf(x_range, 1.5, np.sqrt(3/12)), 'k--', linewidth=1.5,
label='N(1.5, 0.25) approx')
ax2.set_xlabel('z', fontsize=12)
ax2.set_ylabel('Density', fontsize=12)
ax2.set_title('Sum of Uniform Variables -> Approaches Normal', fontsize=13)
ax2.legend(fontsize=9)
ax2.grid(True, alpha=0.3)
# 左下: 数値的な畳み込み
ax3 = axes[1, 0]
# 2つの異なる分布の畳み込み
x = np.linspace(-5, 10, 1000)
dx = x[1] - x[0]
f_X = norm.pdf(x, 1, 0.8)
f_Y = norm.pdf(x, 2, 1.2)
f_Z = np.convolve(f_X, f_Y, mode='same') * dx
ax3.plot(x, f_X, 'b-', linewidth=1.5, label='f_X: N(1, 0.64)')
ax3.plot(x, f_Y, 'g-', linewidth=1.5, label='f_Y: N(2, 1.44)')
ax3.plot(x, f_Z, 'r-', linewidth=2, label='f_Z = f_X * f_Y')
ax3.plot(x, norm.pdf(x, 3, np.sqrt(0.64+1.44)), 'k--', linewidth=1.5,
label='N(3, 2.08) theory')
ax3.set_xlabel('z', fontsize=12)
ax3.set_ylabel('Density', fontsize=12)
ax3.set_title('Numerical Convolution of Two Gaussians', fontsize=13)
ax3.legend(fontsize=9)
ax3.grid(True, alpha=0.3)
# 右下: サイコロの個数を増やす
ax4 = axes[1, 1]
for n_dice in [1, 2, 3, 5, 10]:
rolls = sum(np.random.randint(1, 7, (n_dice, n_samples)))
ax4.hist(rolls, bins=50, density=True, alpha=0.3, label=f'{n_dice} dice')
ax4.set_xlabel('Sum', fontsize=12)
ax4.set_ylabel('Density', fontsize=12)
ax4.set_title('Sum of N Dice -> Central Limit Theorem', fontsize=13)
ax4.legend(fontsize=9)
ax4.grid(True, alpha=0.3)
plt.suptitle('Convolution of Random Variables', fontsize=14)
plt.tight_layout()
plt.show()
右下のグラフでは、サイコロの個数を増やすと和の分布が正規分布に近づいていくことが確認できます。これは中心極限定理の直感的な理解にもつながります。
まとめ
本記事では、確率変数の和の分布を求める畳み込みについて解説しました。
- 畳み込みは独立な確率変数の和の分布を求める操作
- 離散の場合は和、連続の場合は積分で表現される
- モーメント母関数の積と対応しており、再生性の数学的基盤
- 一様分布の和は三角分布になり、個数を増やすと正規分布に近づく(中心極限定理)
次のステップとして、以下の記事も参考にしてください。