Python によるサポートベクターマシンの実装とハイパーパラメータ最適化

サポートベクターマシン(SVM)の概要

サポートベクターマシン(Support Vector Machine: SVM)は、統計的学習理論に基づく強力な分類アルゴリズムです。主に二値分類問題に用いられますが、多クラス分類や回帰分析にも拡張可能です。SVM の核心は、異なるクラス間のマージン(余白)を最大化する決定境界(超平面)を構築することにあります。

主要な特徴と適用領域

  • 分類タスク:本来は二値分類のために設計されましたが、One-vs-One や One-vs-Rest 戦略により多クラス分類へ拡張できます。
  • 高次元データ:特徴量の数がサンプル数を超える場合でも効果的に機能します。
  • 非線形問題:カーネルトリックを用いることで、データを高次元空間へimplicitly に映射し、非線形な決定境界を学習可能です。
  • 適用分野:テキスト分類、画像認識、バイオインフォマティクス(遺伝子解析など)などで実績があります。

利点と課題

SVM の主な利点は、汎化誤差の理論的上界が最適化されるため過学習に強く、メモリ効率が良い点です(予測時にサポートベクトルのみを使用)。一方で、大規模データセットにおける訓練時間の増大、ハイパーパラメータ(カーネル種類、正則化項など)への敏感性、欠損値への対処必要性といった課題も存在します。

Python における SVM 実装

Python の機械学習ライブラリ「scikit-learn」を用いると、効率的に SVM モデルを構築できます。以下では、アヤメ数据集を用いた分類実装例を示します。データの前処理とモデル訓練をパイプライン化することで、コードの保守性を高めています。

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import classification_report

# データセットの読み込み
dataset = load_iris()
features = dataset.data
labels = dataset.target

# 訓練データとテストデータの分割
train_feat, test_feat, train_lbl, test_lbl = train_test_split(
    features, labels, test_size=0.3, random_state=42
)

# パイプラインの構築(標準化 + SVM)
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('classifier', SVC(kernel='rbf', probability=True))
])

# モデルの訓練
pipeline.fit(train_feat, train_lbl)

# 予測と評価
pred_labels = pipeline.predict(test_feat)
print(classification_report(test_lbl, pred_labels))

上記のコードでは、StandardScaler によって特徴量のスケールを揃えた後、RBF カーネルを用いた SVC で分類を行っています。パイプラインを使用することで、テストデータへの変換適用漏れを防ぐことができます。

モデル性能の評価と可視化

分類モデルの性能を多角的に評価するため、混同行列や ROC 曲線を用いることが一般的です。

混同行列の作成

混同行列は、予測結果と正解ラベルの対応関係を矩阵形式で示します。

from sklearn.metrics import ConfusionMatrixDisplay
import matplotlib.pyplot as plt

# 混同行列の計算と表示
disp = ConfusionMatrixDisplay.from_estimator(
    pipeline, test_feat, test_lbl, display_labels=dataset.target_names
)
disp.plot(cmap=plt.cm.Blues)
plt.title("Confusion Matrix")
plt.show()

ROC 曲線の描画

多クラス分類における ROC 曲線を描画するには、ラベルを二値化し、クラスごとに曲線をプロットします。

from sklearn.metrics import roc_curve, auc
from sklearn.preprocessing import label_binarize
import numpy as np

# ラベルの二値化
y_score = pipeline.predict_proba(test_feat)
y_bin = label_binarize(test_lbl, classes=[0, 1, 2])
n_classes = y_bin.shape[1]

# 各クラスの FPR, TPR, AUC 計算
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_bin[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])

# プロット
plt.figure(figsize=(8, 6))
colors = ['blue', 'green', 'red']
for i, color in zip(range(n_classes), colors):
    plt.plot(fpr[i], tpr[i], color=color, lw=2,
             label='ROC curve of class {0} (area = {1:0.2f})'.format(i, roc_auc[i]))

plt.plot([0, 1], [0, 1], 'k--', lw=2)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()

ハイパーパラメータの調整戦略

SVM の性能を最大化するには、適切なハイパーパラメータの設定が不可欠です。主要なパラメータとその調整方針は以下の通りです。

  • C(正則化パラメータ):誤分類に対するペナルティの強さを制御します。値を大きくすると訓練データへの適合度が高まりますが、過学習のリスクが増加します。逆に小さい値だと汎化性能が向上しますが、未学習になる可能性があります。
  • kernel(カーネル関数):データの変換方法を定義します。線形分離可能な場合はlinear、非線形な場合はrbfpolyが選択されます。
  • gamma(カーネル係数):RBF カーネルなどで使用され、単一のサンプルが持つ影響範囲を決定します。値が大きいほど決定境界が複雑になり、各データ点に敏感になります。
  • degree(多項式次数):多項式カーネルを使用する場合の次数です。次数を増やすとモデルの表現力が高まります。

最適化手法

パラメータ探索には以下の手法が一般的です。

  • グリッドサーチ:指定したパラメータの組み合わせを全て試行し、最も性能の良い組み合わせを見つけます。
  • ランダムサーチ:パラメータ空間からランダムにサンプリングして探索します。計算コストを抑えられる場合があります。
  • ベイズ最適化:過去の評価結果に基づいて次に試すパラメータを決定し、効率的に最適解へ収束させます。

グリッドサーチによるチューニング実装

GridSearchCV を使用して、交差検証を行いながら最適なパラメータ組合せを自動探索する例を示します。

from sklearn.model_selection import GridSearchCV

# 探索対象のパラメータ定義
param_space = {
    'classifier__C': [1, 10, 100],
    'classifier__gamma': [0.01, 0.1, 1],
    'classifier__kernel': ['rbf', 'linear']
}

# グリッドサーチオブジェクトの作成
grid_search = GridSearchCV(
    pipeline, 
    param_space, 
    cv=5, 
    scoring='accuracy',
    verbose=1
)

# 最適パラメータの探索
grid_search.fit(train_feat, train_lbl)

print("最適パラメータ:", grid_search.best_params_)
print("最高スコア:", grid_search.best_score_)

この実装では、パイプライン内のclassifierステップに対するパラメータを指定しています。交差検証(cv=5)により、データの偏りに依存しない安定したパラメータ選定が可能になります。

タグ: support-vector-machine Scikit-learn hyperparameter-tuning machine-learning Python

7月8日 21:08 投稿