ナイーブベイズ分類器は、ベイズの定理に基づく確率的分類アルゴリズムであり、「ナイーブ(単純)」という名前は、特徴量間の独立性を仮定することに由来する。つまり、各入力特徴がクラスラベルに対して互いに独立であると仮定してモデルを構築する。
主な特徴
- 古典的な確率論に基づいており、計算効率が高く、特に高次元データ(例:テキスト)に適している。
- 欠損値に対する頑健性があり、学習アルゴリズムも比較的シンプル。
- 分類性能が高く、リアルタイム推論にも向いている。
制約事項
特徴量の独立性仮定が現実のデータと乖離している場合、性能が劣化することがある。特に特徴間に強い相関があるデータセットでは注意が必要である。
ガウシアンナイーブベイズによるアヤメ分類
from sklearn.naive_bayes import GaussianNB
from sklearn import datasets
from sklearn.model_selection import train_test_split
# データロードと分割
iris = datasets.load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# モデル学習と評価
model = GaussianNB()
model.fit(X_train, y_train)
accuracy = model.score(X_test, y_test) # 約0.83
# 単一サンプルの予測と確率出力
sample = X_test[1].reshape(1, -1)
pred_class = model.predict(sample)
pred_proba = model.predict_proba(sample)
print("予測クラス:", pred_class)
print("クラス確率:", np.round(pred_proba, 2))
手書き数字認識への適用
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
import numpy as np
digits = load_digits()
X, y = digits.data, digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=2020)
clf = GaussianNB()
clf.fit(X_train, y_train)
test_accuracy = clf.score(X_test, y_test) # 約0.83
y_pred = clf.predict(X_test)
print("予測結果(先頭10件):", y_pred[:10])
print("正解ラベル(先頭10件):", y_test[:10])
# 特定サンプルのクラス確率(対数確率も利用可能)
log_proba = clf.predict_log_proba(X_test[3].reshape(1, -1))
proba = np.exp(log_proba) # 対数から元の確率に戻す
print("クラス確率(サンプル4):", np.round(proba, 2))
ニュース記事分類:MultinomialNBとTF-IDFの活用
テキスト分類では、MultinomialNBがよく使われる。これは離散的な特徴(例:単語出現頻度)に適しており、TF-IDF(Term Frequency–Inverse Document Frequency)と組み合わせて使用されることが多い。
TF-IDFは、文書内の単語の重要度を評価する手法で、特定の文書で頻出しつつ全体では希少な単語ほど高いスコアを持つ。
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
# ニュースデータセットの読み込み
news = fetch_20newsgroups(subset='all', data_home='./data')
texts, labels = news.data, news.target
# TF-IDF変換
vectorizer = TfidfVectorizer(max_features=5000, stop_words='english')
X_tfidf = vectorizer.fit_transform(texts)
# 小規模テスト用に分割
X_train, X_test, y_train, y_test = train_test_split(
X_tfidf, labels, test_size=0.01, random_state=2020
)
# 多項分布ナイーブベイズで学習
text_clf = MultinomialNB()
text_clf.fit(X_train, y_train)
test_score = text_clf.score(X_test, y_test) # 約0.87
log_probs = text_clf.predict_log_proba(X_test[10])
print("対数確率(サンプル11):", np.round(log_probs, 2))