機械学習を学んでいると、序盤に必ず尤度と呼ばれる統計量を学ぶことになるでしょう。この尤度というものは、日常生活で暮らしていても確実に出会うものでもなく、概念も理解しにくいです。
一方で、この尤度の概念を正しく理解することは機械学習を学ぶ上で確実に必要になるので、この尤度について一度掘り下げてみましょう。
本記事の内容
- 尤度の直感的な理解と確率との違い
- 尤度関数の数学的な定義
- 最尤推定法の導出とPythonでの実装
尤度とはそもそもなんだ?
確率の統計量は、数式だけでなく、その統計量がどのような量を表しているのか、定性的に理解することが非常に重要です。この「尤度」を定性的に表現するなら、尤度とは現在のパラメータのもとで、観測データが得られる確率の度合いであると言えます。
確率と尤度の違い
尤度を理解する上で最も重要なのは、確率と尤度の違いを明確にすることです。
確率(Probability)と尤度(Likelihood)はどちらも同じ確率分布の式から計算されますが、何を固定して何を変数とみなすかが異なります。
- 確率 $P(x \mid \theta)$: パラメータ $\theta$ を固定し、データ $x$ を変数とみなす。「このパラメータのもとで、このデータが出る確率はどれくらいか?」
- 尤度 $L(\theta \mid x)$: データ $x$ を固定し、パラメータ $\theta$ を変数とみなす。「このデータが観測されたとき、パラメータはどの値がもっともらしいか?」
数式としては同じ関数ですが、視点が逆転しています。
$$ L(\theta \mid x) = P(x \mid \theta) $$
左辺は尤度関数、右辺は確率関数です。式の形は同じですが、$\theta$ を動かすか $x$ を動かすかが異なります。
正規分布を例にした具体的な理解
正規分布 $\mathcal{N}(\mu, \sigma^2)$ を例に、確率と尤度の違いを確認しましょう。
正規分布の確率密度関数は以下で与えられます。
$$ f(x \mid \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left( -\frac{(x – \mu)^2}{2\sigma^2} \right) $$
確率の視点: $\mu = 0$, $\sigma = 1$ と固定して、$x$ を変数として見ると、おなじみの正規分布の釣り鐘型の曲線が得られます。
尤度の視点: 観測データ $x = 2$ が得られたとき、$\mu$ を変数として見ます。このとき、$f(2 \mid \mu, 1)$ は $\mu$ の関数となり、$\mu = 2$ のとき最大値をとります。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-4, 6, 300)
# 確率の視点: mu=0, sigma=1 で固定、xを変数に
mu_fixed = 0
sigma = 1
prob = (1 / np.sqrt(2 * np.pi * sigma**2)) * np.exp(-(x - mu_fixed)**2 / (2 * sigma**2))
# 尤度の視点: x=2 で固定、muを変数に
x_observed = 2
mu_range = np.linspace(-4, 6, 300)
likelihood = (1 / np.sqrt(2 * np.pi * sigma**2)) * np.exp(-(x_observed - mu_range)**2 / (2 * sigma**2))
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 確率の視点
axes[0].plot(x, prob, 'b-', linewidth=2)
axes[0].set_title("Probability: P(x | mu=0, sigma=1)")
axes[0].set_xlabel("x")
axes[0].set_ylabel("P(x)")
axes[0].axvline(x=2, color='r', linestyle='--', label='x=2')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 尤度の視点
axes[1].plot(mu_range, likelihood, 'r-', linewidth=2)
axes[1].set_title("Likelihood: L(mu | x=2, sigma=1)")
axes[1].set_xlabel("mu")
axes[1].set_ylabel("L(mu)")
axes[1].axvline(x=2, color='b', linestyle='--', label='mu=2 (max)')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
左のグラフは確率の視点($x$ を横軸)、右のグラフは尤度の視点($\mu$ を横軸)です。尤度関数は $\mu = 2$ で最大となり、これは「観測データ $x = 2$ をもっともよく説明するパラメータは $\mu = 2$ である」ことを意味しています。
尤度関数の定義
$n$ 個の独立な観測データ $\bm{x} = (x_1, x_2, \dots, x_n)$ が得られたとき、パラメータ $\theta$ に対する尤度関数は以下で定義されます。
$$ L(\theta \mid \bm{x}) = \prod_{i=1}^{n} P(x_i \mid \theta) $$
各データが独立に生成されているため、同時確率は各確率の積として書けます。
実務的には、積の計算は数値的に不安定(非常に小さい値の積はアンダーフローを起こす)なため、対数をとった対数尤度関数を用いることが一般的です。
$$ \ell(\theta \mid \bm{x}) = \log L(\theta \mid \bm{x}) = \sum_{i=1}^{n} \log P(x_i \mid \theta) $$
対数変換により、積が和に変換され、計算が安定します。また、対数関数は単調増加なので、$L$ を最大化する $\theta$ と $\ell$ を最大化する $\theta$ は一致します。
最尤推定法(Maximum Likelihood Estimation)
尤度関数を最大化するパラメータ $\hat{\theta}$ を求める方法を最尤推定法(MLE: Maximum Likelihood Estimation)と呼びます。
$$ \hat{\theta}_{\text{MLE}} = \arg\max_\theta L(\theta \mid \bm{x}) = \arg\max_\theta \ell(\theta \mid \bm{x}) $$
正規分布の最尤推定
正規分布 $\mathcal{N}(\mu, \sigma^2)$ のパラメータ $\mu$ を最尤推定してみましょう。$\sigma^2$ は既知として固定します。
対数尤度関数は以下のようになります。
$$ \begin{align} \ell(\mu) &= \sum_{i=1}^{n} \log f(x_i \mid \mu, \sigma^2) \\ &= \sum_{i=1}^{n} \left[ -\frac{1}{2}\log(2\pi\sigma^2) – \frac{(x_i – \mu)^2}{2\sigma^2} \right] \\ &= -\frac{n}{2}\log(2\pi\sigma^2) – \frac{1}{2\sigma^2}\sum_{i=1}^{n}(x_i – \mu)^2 \end{align} $$
$\mu$ で微分して $0$ とおくと、
$$ \frac{\partial \ell}{\partial \mu} = \frac{1}{\sigma^2}\sum_{i=1}^{n}(x_i – \mu) = 0 $$
$$ \sum_{i=1}^{n} x_i – n\mu = 0 $$
$$ \hat{\mu}_{\text{MLE}} = \frac{1}{n}\sum_{i=1}^{n} x_i = \bar{x} $$
つまり、正規分布の平均 $\mu$ の最尤推定量は標本平均になります。これは直感的にも納得できる結果です。
Pythonでの最尤推定の実装
Pythonで最尤推定を実装し、推定結果を可視化してみましょう。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize_scalar
# 真のパラメータ
mu_true = 3.0
sigma_true = 1.5
np.random.seed(42)
# データ生成
n = 50
data = np.random.normal(mu_true, sigma_true, n)
# 対数尤度関数(sigma は既知として固定)
def neg_log_likelihood(mu, data, sigma):
"""負の対数尤度(最小化するため符号を反転)"""
n = len(data)
ll = -n/2 * np.log(2 * np.pi * sigma**2) - 1/(2 * sigma**2) * np.sum((data - mu)**2)
return -ll
# 解析解
mu_mle_analytic = np.mean(data)
# 数値最適化による解
result = minimize_scalar(neg_log_likelihood, args=(data, sigma_true), bounds=(-5, 10), method='bounded')
mu_mle_numeric = result.x
print(f"真のパラメータ: mu = {mu_true}")
print(f"解析解 (標本平均): mu_MLE = {mu_mle_analytic:.4f}")
print(f"数値最適化: mu_MLE = {mu_mle_numeric:.4f}")
# 対数尤度関数の可視化
mu_range = np.linspace(0, 6, 200)
log_likelihoods = [-neg_log_likelihood(mu, data, sigma_true) for mu in mu_range]
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 左: データのヒストグラムと推定結果
axes[0].hist(data, bins=15, density=True, alpha=0.6, color='steelblue', label='Data')
x_plot = np.linspace(-2, 8, 200)
axes[0].plot(x_plot, (1/np.sqrt(2*np.pi*sigma_true**2)) * np.exp(-(x_plot-mu_true)**2/(2*sigma_true**2)),
'g--', linewidth=2, label=f'True (mu={mu_true})')
axes[0].plot(x_plot, (1/np.sqrt(2*np.pi*sigma_true**2)) * np.exp(-(x_plot-mu_mle_analytic)**2/(2*sigma_true**2)),
'r-', linewidth=2, label=f'MLE (mu={mu_mle_analytic:.2f})')
axes[0].set_xlabel("x")
axes[0].set_ylabel("Density")
axes[0].set_title("Data and Estimated Distribution")
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 右: 対数尤度関数
axes[1].plot(mu_range, log_likelihoods, 'b-', linewidth=2)
axes[1].axvline(x=mu_mle_analytic, color='r', linestyle='--', linewidth=1.5, label=f'MLE: mu={mu_mle_analytic:.2f}')
axes[1].axvline(x=mu_true, color='g', linestyle='--', linewidth=1.5, label=f'True: mu={mu_true}')
axes[1].set_xlabel("mu")
axes[1].set_ylabel("Log-Likelihood")
axes[1].set_title("Log-Likelihood Function")
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
まとめ
本記事では、確率・機械学習における「尤度」について解説しました。
- 尤度とは、観測データが固定されたもとでパラメータの「もっともらしさ」を測る指標
- 確率と尤度の違い: 同じ式でも、データを動かすか(確率)、パラメータを動かすか(尤度)が異なる
- 対数尤度: 数値安定性のために積を和に変換して計算する
- 最尤推定法: 尤度(対数尤度)を最大にするパラメータを求める方法
- 正規分布の平均の最尤推定量は標本平均と一致する
尤度の概念はベイズ推定やEMアルゴリズムなど、機械学習の多くの手法の基礎となっています。