第18回「scikit-learnの使い方(4)サポートベクタマシン」

こんにちは、小澤です。

前回は、教師あり学習の基本的な概念と、その主要なタスクである分類と回帰について解説しました。今回は、scikit-learnを用いてサポートベクタマシン(SVM)を実装し、データセットの分類に活用する方法を見ていきましょう。教科書『Pythonによる新しいデータ分析の教科書(第2版)』では、4.4.2章「分類」のサポートベクタマシン(228〜236ページ)の箇所です。

サポートベクタマシン(SVM)とは?

サポートベクタマシン(Support Vector Machine;SVM)は、分類や回帰に利用される機械学習アルゴリズムの一つです。特に、データが線形分離可能な場合に強力な性能を発揮しますが、カーネル関数を使用することで非線形データの分類も可能です。SVMの目的は、データを最も効果的に分離する最適な決定境界(超平面、ハイパープレーン)を見つけることです。

SVMの基本的な概念

1.決定境界(超平面、ハイパープレーン)

  • SVMは、データをクラスごとに最も適切に分離する「決定境界(ハイパープレーン、超平面)」を見つけることを目的とします。
  • 決定境界は、2次元データの場合は直線、3次元データでは平面、それ以上では超平面になります。

2.マージンの最大化

  • SVMは、クラス間のマージン(データと決定境界の距離)を最大化するように学習します。
  • マージンの境界付近に位置するデータポイントをサポートベクタと呼びます。

3.カーネル法による非線形分類

  • データが線形分離できない場合、カーネル関数を使用して高次元空間に変換し、線形分離を可能にします。

SVMの主な特徴

  • 高次元空間での有効性
     SVMは、高次元の特徴空間でも効果的に機能します。カーネルトリックと呼ばれる技術を活用し、データをより高次元の空間にマッピングすることで、線形分離可能な決定境界を見つけることができます。このため、特徴量の数が多いデータセットにも適用しやすく、次元の呪いの影響を受けにくいという利点があります。
  • 優れた汎化性能
    SVMは、マージン最大化の考え方を基に学習を行うため、過学習を抑制しながらモデルを構築できます。トレーニングデータへの適合度だけでなく、未知のデータに対する汎化性能を高めることが可能です。サポートベクタ(決定境界付近のデータポイント)のみを学習に使用するため、外れ値の影響を受けにくいという特徴もあります。
  • カーネルトリックによる柔軟な分類
    SVMは、データが線形分離できない場合でも、カーネルトリックを用いることで分類を可能にします。カーネルトリックとは、データを高次元空間に変換する手法で、代表的なカーネル関数に次のようなものがあります。
    • 線形カーネル(linear):データが線形分離可能な場合に最適。
    • 多項式カーネル(poly):より複雑な決定境界を学習可能。
    • RBF(ガウシアン)カーネル(rbf):非線形データの分類に最も一般的に使用される。
    • シグモイドカーネル(sigmoid):ニューラルネットワークの活性化関数に類似。

scikit-learnによるSVMの実装

ここでは、scikit-learnを用いてIrisデータセットを分類する例を示します。

(1)データの準備

まず、Irisデータセットを読み込み、学習用データとテスト用データに分割します。

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# データセットのロード
iris = datasets.load_iris()
X = iris.data[:, :2]  # がく片の長さ・幅を使用(2Dに制限)
y = iris.target  # ラベル

# データの分割(80%を学習用、20%をテスト用)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

# 特徴量の標準化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

(2)SVMモデルの訓練

次に、SVMモデルを学習させます。ここでは、RBFカーネルを使用します。RBFカーネルは、データが線形分離できない場合でも高次元空間に写像することで線形分離を可能にするといった特徴があります。

from sklearn.svm import SVC

# SVMモデルの作成
# kernel=’rbf’ → RBFカーネルを使用(非線形分類)
# C=1.0 → 正則化パラメータ(大きいほど誤分類を許容しにくくなる)
# gamma=’scale’ → データの分布に応じたスケールを適用
model = SVC(kernel=’rbf’, C=1.0, gamma=’scale’)
model.fit(X_train, y_train)

(3)予測と評価

テストデータを使って予測を行い、分類モデルの性能を評価し、結果の評価を表示します。

from sklearn.metrics import classification_report, confusion_matrix

# 予測
y_pred = model.predict(X_test)

# 結果の評価
print(“混同行列:”)
print(confusion_matrix(y_test, y_pred))
print(“”)
print(“分類レポート:”)
print(classification_report(y_test, y_pred))

(4)メッシュグリッドの作成と分類予測

決定境界を可視化するために、メッシュグリッドを作成し、各点における分類予測を行います。

import numpy as np

# メッシュグリッドの作成(決定境界の描画用)
x_min, x_max = X_train[:, 0].min() – 1, X_train[:, 0].max() + 1
y_min, y_max = X_train[:, 1].min() – 1, X_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100),
                     np.linspace(y_min, y_max, 100))

# 領域の分類予測
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

(5)散布図の描画

import matplotlib.pyplot as plt

plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, alpha=0.3, cmap=’viridis’)  # 背景のクラス領域
scatter = plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=’viridis’, edgecolor=’k’)

# 軸ラベルとタイトル
plt.xlabel(“Sepal Length (Standardized)”)
plt.ylabel(“Sepal Width (Standardized)”)
plt.title(“SVM Classification of Iris Dataset (RBF Kernel)”)

# 凡例の作成
legend_labels = [plt.Line2D([0], [0], marker=’o’, color=’w’, markersize=10, markerfacecolor=plt.cm.viridis(i/2)) for i in range(3)]
plt.legend(legend_labels, iris.target_names, title=”Species”)

# 表示
plt.show()

(6)結果

1.混同行列と分類レポートについて

  • 混同行列:
    • クラス0(setosa)は全て正しく分類されています。
    • クラス1(versicolor)は5個中3個が正しく分類され、2個がクラス2(virginica)と誤分類されています。
    • クラス2(virginica)は7個中5個が正しく分類され、2個がクラス1(versicolor)と誤分類されています。
  • 分類レポート:
    • 全体的な正解率は73%です。
    • クラス0(setosa)の適合率(precision)、再現率(recall)、F1値は全て1.00であり、完璧な分類結果です。
    • クラス1(versicolor)とクラス2(virginica)は、適合率、再現率ともに0.5〜0.7程度であり、分類が難しいことがわかります。

2.散布図について

  • 決定境界:
    • 決定境界が複雑な形状になっているのは、RBFカーネルを使用しているためだと思われます。
    • クラス0(setosa)は、他の2つのクラスと比較的明確に分離できています。
    • クラス1(versicolor)とクラス2(virginica)の間には、重なり合っている部分があり、これが分類を難しくしている要因と考えられます。
  • サポートベクタ:
    • 各クラスの境界付近に位置していると考えられます。

3.考察

  • Irisデータセットは、がく片の長さと幅の2つの特徴量だけでも、ある程度クラスを分類できます。
  • 特にsetosaは、他の2つのクラスと特徴量が大きく異なるため、容易に分類できます。
  • versicolorとvirginicaは、特徴量が似ている部分があり、RBFカーネルを用いても完全に分離することは難しいです。
  • 分類精度を向上させるためには、他の特徴量(花弁の長さや幅など)を追加したり、SVMのハイパーパラメータ(Cやgamma)を調整したり、別の分類アルゴリズムを試したりすることが考えられます。

まとめ

今回は、scikit-learnを用いてサポートベクタマシン(SVM)を実装し、irisデータセットの分類に挑戦しました。SVMは強力な分類アルゴリズムなので、様々な問題に応用できます。ぜひ、色々なデータセットで試してみてください。また、カーネルの種類やハイパーパラメータを調整することで、モデルの性能をさらに向上させることもできます。
次回は決定木です。樹木のような階層構造でデータを段階的に分割することで、分類や回帰を行なう手法です。次回もお楽しみに。

PAGE TOP