ナイーブベイズ

入門

2.2.6

ナイーブベイズ

最終更新 2020-04-08 読了時間 3 分
まとめ
  • ナイーブベイズは特徴量が条件付き独立であると仮定し、ベイズの定理で尤度と事前確率を組み合わせて分類します。
  • 学習も推論も高速で、テキスト分類やスパム検知のような高次元・疎なデータの強力なベースラインになります。
  • ラプラス平滑化や TF-IDF 特徴量と組み合わせると未知語や頻度差に頑健になります。
  • 独立性の仮定が強過ぎる場合は、特徴選択や他モデルとのアンサンブルを検討します。

直感 #

ベイズの定理は「事前確率 × 尤度 ∝ 事後確率」という関係を与えます。特徴量が条件付き独立であれば、尤度は各特徴の確率の積で近似できます。ナイーブベイズはこの近似を用いて、少量の学習データでも安定した分類が可能です。

flowchart LR A["入力x"] --> B["クラスごとの\n尤度P(x|y)を計算"] B --> C["事前確率\nP(y)を乗算"] C --> D["事後確率\nP(y|x)"] D --> E["argmax\n最大確率クラス"] E --> F["予測ラベル"] style A fill:#2563eb,color:#fff style D fill:#1e40af,color:#fff style F fill:#10b981,color:#fff

数式で見る #

クラス \(y\) と特徴ベクトル \(\mathbf{x} = (x_1, \ldots, x_d)\) に対して

$$ P(y \mid \mathbf{x}) \propto P(y) \prod_{j=1}^{d} P(x_j \mid y) $$

と近似します。テキスト分類では出現回数を扱う多項ナイーブベイズ、出現/非出現を扱うベルヌーイ型、連続値にはガウス型など、課題に合わせて尤度の形を選べます。

アルゴリズムの詳細 #

ガウシアンナイーブベイズ #

連続値の特徴量に対しては、各特徴量\(x_j\)がクラス\(y\)のもとで正規分布に従うと仮定します。

$$ P(x_j \mid y) = \frac{1}{\sqrt{2\pi\, \sigma_{yj}^2}} \exp\left(-\frac{(x_j - \mu_{yj})^2}{2\, \sigma_{yj}^2}\right) $$

パラメーター\(\mu_{yj}\)と\(\sigma_{yj}^2\)は、クラス\(y\)に属する学習データから最尤推定で求めます。

$$ \mu_{yj} = \frac{1}{|C_y|} \sum_{i \in C_y} x_{ij}, \qquad \sigma_{yj}^2 = \frac{1}{|C_y|} \sum_{i \in C_y} (x_{ij} - \mu_{yj})^2 $$

多項ナイーブベイズ #

テキスト分類など、特徴量が出現回数(カウントデータ)の場合に使います。クラス\(y\)のもとで特徴量\(j\)が出現する確率は、ラプラス平滑化を加えて以下で推定します。

$$ \hat{\theta}_{yj} = P(x_j \mid y) = \frac{N_{yj} + \alpha}{N_y + \alpha\, V} $$

ここで\(N_{yj}\)はクラス\(y\)の全文書における特徴量\(j\)の総出現回数、\(N_y = \sum_j N_{yj}\)はクラス\(y\)の総単語数、\(V\)は語彙サイズ、\(\alpha\)は平滑化パラメーター(\(\alpha = 1\)がラプラス平滑化)です。

\(\alpha = 0\)の場合、学習データに1度も出現しない単語があると\(P(x_j \mid y) = 0\)となり、積全体が0になってしまいます。ラプラス平滑化はこのゼロ確率問題を回避します。

対数空間での計算 #

実際の実装では、確率の積を直接計算すると数値的にアンダーフローを起こすため、対数空間で計算します。

$$ \log P(y \mid \mathbf{x}) = \log P(y) + \sum_{j=1}^{d} \log P(x_j \mid y) + \text{const.} $$

予測クラスは対数事後確率が最大のものを選びます。

$$ \hat{y} = \arg\max_{y} \left[ \log P(y) + \sum_{j=1}^{d} \log P(x_j \mid y) \right] $$

対数空間での加算は元の空間での乗算に対応するため、数値的に安定した計算が可能です。

計算量 #

処理計算量
学習\(O(n \cdot d)\) — 各サンプルの各特徴量を1回走査
予測(1サンプル)\(O(K \cdot d)\) — 各クラスについて\(d\)個の尤度を計算

\(n\)はサンプル数、\(d\)は特徴量数、\(K\)はクラス数です。学習も予測もデータサイズに対して線形であるため、大規模・高次元データでも実用的な速度で動作します。

flowchart TD A["学習データ (X, y)"] --> B["クラスごとに\nパラメーター推定"] B --> C["ガウス型: μ, σ²\n多項型: θ (+ α平滑化)"] C --> D["事前確率 P(y)\n= |C_y| / n"] D --> E["新しいサンプル x"] E --> F["対数空間で計算\nlog P(y) + Σ log P(x_j|y)"] F --> G["argmax で\n予測クラス決定"] style A fill:#2563eb,color:#fff style F fill:#1e40af,color:#fff style G fill:#10b981,color:#fff

Pythonによる実験 #

以下は人工データにガウシアンナイーブベイズを適用し、決定領域と混同行列を確認する例です。高次元でも高速に学習でき、シンプルな評価指標で性能を把握できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from __future__ import annotations

import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.naive_bayes import GaussianNB

def run_naive_bayes_demo(
    n_samples: int = 600,
    n_classes: int = 3,
    random_state: int = 0,
    title: str = "ガウシアン Naive Bayes の決定領域",
    xlabel: str = "特徴量1",
    ylabel: str = "特徴量2",
) -> dict[str, float | np.ndarray]:
    """Train Gaussian Naive Bayes on synthetic data and plot decision regions."""
    X, y = make_classification(
        n_samples=n_samples,
        n_features=2,
        n_informative=2,
        n_redundant=0,
        n_clusters_per_class=1,
        n_classes=n_classes,
        random_state=random_state,
    )

    clf = GaussianNB()
    clf.fit(X, y)

    accuracy = float(accuracy_score(y, clf.predict(X)))
    conf = confusion_matrix(y, clf.predict(X))

    x_min, x_max = X[:, 0].min() - 1.0, X[:, 0].max() + 1.0
    y_min, y_max = X[:, 1].min() - 1.0, X[:, 1].max() + 1.0
    grid_x, grid_y = np.meshgrid(
        np.linspace(x_min, x_max, 400),
        np.linspace(y_min, y_max, 400),
    )
    grid = np.c_[grid_x.ravel(), grid_y.ravel()]
    preds = clf.predict(grid).reshape(grid_x.shape)

    fig, ax = plt.subplots(figsize=(7, 6))
    ax.contourf(
        grid_x,
        grid_y,
        preds,
        alpha=0.25,
        cmap="coolwarm",
        levels=np.arange(-0.5, n_classes + 0.5, 1),
    )
    ax.scatter(X[:, 0], X[:, 1], c=y, cmap="coolwarm", edgecolor="k", s=25)
    ax.set_title(title)
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    fig.tight_layout()
    plt.show()

    return {"accuracy": accuracy, "confusion": conf}

metrics = run_naive_bayes_demo(
    title="ガウシアン Naive Bayes の決定領域",
    xlabel="特徴量1",
    ylabel="特徴量2",
)
print(f"訓練精度: {metrics['accuracy']:.3f}")
print("混同行列:")
print(metrics['confusion'])

ガウシアンNaive Bayesの決定領域

ナイーブベイズは特徴量の条件付き独立性を仮定しているため、特徴量間に強い相関がある場合は確率の推定値が不正確になります。ただしクラスの順位は保たれることが多く、分類精度自体は大きく低下しないこともあります。確率値を直接使う場合はCalibratedClassifierCVで較正してください。

テキスト分類にはMultinomialNBTfidfVectorizerの組み合わせが定番です。alphaパラメーターでラプラス平滑化の強さを調整し、未知語によるゼロ確率問題を回避してください。

スムージングと決定境界 #

スムージングパラメータを変えると決定境界がどう変化するか確認できます。

まとめ #

  • ナイーブベイズは条件付き独立性の仮定のもと、ベイズの定理で事後確率を計算して分類します。
  • 学習も推論も高速で、高次元・疎なデータ(テキスト分類など)で強力なベースラインになります。
  • ガウス型、多項型、ベルヌーイ型など、データの性質に合わせて尤度の形を選択できます。
  • 独立性の仮定が強いため確率推定は不正確になりがちですが、分類精度は実用的な水準を保つことが多いです。

参考文献 #

  • Manning, C. D., Raghavan, P., & Schütze, H. (2008). Introduction to Information Retrieval. Cambridge University Press.
  • Murphy, K. P. (2012). Machine Learning: A Probabilistic Perspective. MIT Press.