データの性質で選ぶナイーブベイズのサブタイプ

はじめに

機械学習ライブラリScikit-learnには、ナイーブベイズ分類器として4つの異なるクラスが用意されています。これらはそれぞれ異なるデータ特性を想定しており、タスクに応じて適切に使い分けることが重要です。しかし、どのクラスをいつ使えば良いのか、迷うことも少なくありません。

この記事を書いたひと

デジタルリアクタ合同会社 代表
機械学習・統計、数値計算などの領域を軸としたソフトウェアエンジニアリングを専門としています。スタートアップからグローバル企業まで、さまざまなスケールの企業にて、事業価値に直結する計算システムを設計・構築してきました。主に機械学習の応用分野において、出版・発表、特許取得等の実績があり、また、IT戦略やデータベース技術等の情報処理に関する専門領域の国家資格を複数保有しています。九州大学理学部卒業。日本ITストラテジスト協会正会員。

本記事では、これら4つのナイーブベイズクラス(MultinomialNB, BernoulliNB, GaussianNB, ComplementNB)がどのようなデータに適しているのか、そしてどのような場面で使い分けるべきかを、具体的なコード例と直感的な比喩を交えて解説します。理論的な詳細や実験結果は省き、各手法の核心的な考え方と実践的な使いどころに焦点を当てます。

対象読者:

  • ナイーブベイズの基本的な理論は理解しているが、Scikit-learnでの実装やクラスの使い分けに迷っている方
  • テキスト分類などのタスクで、どのナイーブベイズモデルを選択すべきか、その判断基準を知りたい方

記事のポイント:

  • Scikit-learnで提供される4つのナイーブベイズクラスの役割と適用場面が明確になる
  • テキストデータの前処理(CountVectorizerなど)とナイーブベイズモデルの適切な組み合わせがわかる
  • 各モデルの背後にある直感的なアイデアを比喩によって深く理解できる

ナイーブベイズの基本

まず、すべてのクラスに共通するナイーブベイズの基本原理を再確認しましょう。ナイーブベイズは、ベイズの定理に基づき、与えられた特徴量xを持つデータがクラスyに属する確率を最大化することで分類を行います。その中心となる式は以下の通りです。

\hat{y} = \argmax_{y} P(y) \prod_{i=1}^{n} P(x_i \mid y)

この式のポイントは2つあります。1つは、特徴量同士が互いに独立であるという「ナイーブな」仮定です。そしてもう1つが、クラスyが与えられたときの各特徴量x_iの確率分布P(x_i \mid y)の仮定です。

Scikit-learnの4つのクラスは、まさにこのP(x_i \mid y)の仮定がそれぞれ異なっており、扱うデータの種類によって使い分ける必要があります。例えば、単語の出現回数のようなカウントデータなら多項分布を、特徴の有無のようなバイナリデータならベルヌーイ分布を、そして連続値データならガウス分布を仮定します。この違いが、各クラスの得意な領域を決定づけているのです。

4つのクラスの役割と使いどころ

それでは、Scikit-learnが提供する4つのクラスを具体的に見ていきましょう。それぞれのモデルがどのようなデータ分布を仮定し、どのような場面で活躍するのかを解説します。

MultinomialNB:カウントデータの王道

MultinomialNBは、単語の出現回数のような、非負の整数で表されるカウントデータを扱うのに最も適しています。そのため、テキスト分類タスクでCountVectorizerと組み合わせる際の第一候補と言えるでしょう。

  • 適用データ: 単語の出現回数などのカウントデータ(非負整数)
  • 最小コード:

    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.naive_bayes import MultinomialNB
    
    vec = CountVectorizer(max_features=1000, stop_words='english')
    Xtr = vec.fit_transform(X_train_text)
    Xte = vec.transform(X_test_text)
    clf = MultinomialNB(alpha=1.0).fit(Xtr, y_train)
    pred = clf.predict(Xte)
  • 直感的な理解:
    このモデルは「単語による票集計」と考えると分かりやすいです。各単語が、その出現回数に応じて特定のクラスに「票」を投じます。重要なパラメータであるalphaはラプラススムージングを制御し、学習データに一度も出現しなかった単語にも最低限の票を与えることで、ゼロ頻度の問題に対応し過学習を防ぎます。

BernoulliNB:特徴の有無で判断する

MultinomialNBが「単語の出現回数」を見ていたのに対し、BernoulliNBは「単語が出現したか、しなかったか」という二値(バイナリ)特徴を扱います。特徴量の値は0か1のみを想定します。

  • 適用データ: バイナリ特徴(0/1)。単語の出現有無のみを扱う場合など。
  • 最小コード:

    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.naive_bayes import BernoulliNB
    
    # binary=Trueで特徴量を0/1に変換
    vec = CountVectorizer(max_features=1000, stop_words='english', binary=True)
    Xtr = vec.fit_transform(X_train_text)
    Xte = vec.transform(X_test_text)
    clf = BernoulliNB(alpha=1.0).fit(Xtr, y_train)
  • 直感的な理解:
    BernoulliNBの振る舞いは「持っているか・いないかのスタンプ判定」に似ています。各特徴(単語)は、文書中に存在するかどうかで一票だけを投じます。出現回数は考慮されません。このため、文章の長さに関わらず、特定の単語の存在自体が重要な手がかりとなるようなタスク(例:短文のテキスト分類)で効果を発揮することがあります。

GaussianNB:連続値を正規分布で捉える

これまでの2つが主にテキストデータを想定していたのに対し、GaussianNB連続値(実数)を扱うためのモデルです。各クラスにおける特徴量の分布が、正規分布(ガウス分布)に従うと仮定します。

  • 適用データ: Irisデータセットの花弁の長さなど、正規分布に近似できる連続値。
  • 最小コード:

    from sklearn.naive_bayes import GaussianNB
    
    clf = GaussianNB().fit(X_train_cont, y_train)
    pred = clf.predict(X_test_cont)
  • 直感的な理解:
    このモデルは「鐘形カーブ(正規分布)への当てはまり度で点数をつける」方法と考えることができます。各クラスごとに特徴量の平均と分散を計算し、入力されたデータがそのクラスの分布からどれくらい離れているかを評価します。そのクラスの典型的な値に近ければ近いほど、高いスコアが与えられます。

ComplementNB:不均衡データに強い改良版

ComplementNBは、MultinomialNBを改良したモデルで、特にクラス不均衡なデータセットに強いという特徴があります。MultinomialNBと同様にカウントデータを扱います。

  • 適用データ: カウントデータ(特にクラスのサンプル数に偏りがある場合)
  • 最小コード:

    from sklearn.feature_extraction.text import CountVectorizer
    from sklearn.naive_bayes import ComplementNB
    
    vec = CountVectorizer(max_features=500, stop_words='english')
    Xtr = vec.fit_transform(X_train_text)
    Xte = vec.transform(X_test_text)
    clf = ComplementNB(alpha=1.0).fit(Xtr, y_train)
  • 原理と直感的な理解:
    通常のナイーブベイズが「このデータはクラスyにどれだけ当てはまるか」を計算するのに対し、ComplementNBは「このデータはクラスy補集合(y以外)にどれだけ当てはまらないか」を計算します。数式で示すと、その重み付けは以下のような考え方に基づいています。

    \log P(y \mid x) \propto \log P(y) - \sum_i x_i \log P(x_i \mid \overline{y})

    ここで\overline{y}はクラスyの補集合です。この式は、クラスyである確率が、補集合\overline{y}における特徴量の出現確率が低いほど高くなることを示しています。

    直感的には、「そのクラス“以外”でよく出る言葉ほど、減点が大きくなる減点方式」と理解できます。例えば「スポーツ」と「医療」の分類を考えたとき、「team」や「game」のような一般語は両方のカテゴリに関連するため、補集合側でも頻出し、減点が大きくなります。一方、「virus」や「diagnosis」のような医療専門用語は「スポーツ」カテゴリの補集合ではあまり出現しないため、減点が小さく、「医療」クラスの強い証拠として機能します。

    この仕組みにより、多数派クラスに属する一般的な単語の影響が抑制され、クラス不均衡なデータでも少数派クラスを正しく分類しやすくなります。

前処理とモデル選択の対応表

ここまで見てきた4つのクラスを、データの前処理方法と合わせて整理すると、モデル選択の指針が見えてきます。

データタイプ 前処理 推奨クラス
テキスト(出現回数) CountVectorizer MultinomialNB / ComplementNB
テキスト(出現/非出現) CountVectorizer(binary=True) BernoulliNB
テキスト(不均衡データ) CountVectorizer ComplementNB
連続値 標準化など(任意) GaussianNB

実用上のヒント

最後に、これらのモデルを実務で使う上でのいくつかのヒントを紹介します。

  • TF-IDFでベクトル化されたデータをGaussianNBで扱うことは可能ですが、TF-IDF値が正規分布に従うとは限らないため、分布の仮定との整合性には注意が必要です。
  • ナイーブベイズの「独立性の仮定」は現実のデータではほとんど成り立ちませんが、それでも実用上は十分に高い性能を発揮することがよくあります。ただし、特徴量間に非常に強い相関がある場合は、他のモデルも検討する価値があります。
  • alphaパラメータ(ラプラススムージング)の調整は、特にデータがスパース(ゼロが多い)な場合に有効です。Grid Searchなどで最適な値を見つけることをお勧めします。

まとめ

本記事では、Scikit-learnの4つのナイーブベイズクラスについて、その特徴と使い分けを解説しました。ナイーブベイズは、その名の通り「ナイーブな」独立性仮定を持つシンプルなモデルですが、データの性質に合わせて適切なクラスを選択することで、特にテキスト分類などのタスクで強力なベースラインとなります。

重要なのは、手元のデータがどのような性質を持つか(カウント、バイナリ、連続値)を見極め、それに合った分布仮定を持つクラスを選ぶことです。テキストデータであればCountVectorizerと組み合わせてMultinomialNBを、クラス不均衡が懸念されるならComplementNBを、特徴量の有無が重要ならBernoulliNBを、そして連続値データにはGaussianNBを、というように使い分けることが成功の鍵となります。