機械学習の具体的な問題にPythonを使って、機械学習もPythonも同時に学んでしまいましょう。今回はサポートベクターマシン(SVM)を使った分類についてまとめました。SVMは、データを分ける最適な境界線(超平面)を見つけるアルゴリズムです。
この記事では scikit-learn(sklearn)ライブラリを用います。適宜
pip install scikit-learn
などによってダウンロード・インストールしてください。
SVMの実装
SVMでは、データを分類するマージン(余白)が最大になるように境界線を決めます。境界線は必ずしも直線である必要はなく、カーネル(kernel)の選択によって、線形分離できないデータも分類可能になります:
ここではまず線形SVMを考えます。実装は以下の通りです:
import numpy as np from sklearn.svm import SVC # サンプルデータ(特徴量Xとクラスy) X = np.array([[1], [2], [3], [6], [7], [8]]) # 特徴量 y = np.array([0, 0, 0, 1, 1, 1]) # クラス(0 or 1) # モデル作成(線形SVM) model = SVC(kernel='linear', C=1.0) model.fit(X, y) # 予測 X_test = np.array([[4], [5]]) # 新しいデータ y_pred = model.predict(X_test) print("予測結果:", y_pred) # 4と5はどのクラスに分類されるか?
予測結果: [0 1]
ポイント
- SVC (kernel='linear', C=1.0)
- 線形SVM を使用(kernel='linear')
- C はマージンの調整(大きいと誤分類を許さない、小さいと汎化性が高まる)
- model.fit(X, y) で学習
- model.predict(X_test) で分類
SVMの決定境界の可視化
上で扱ったデータセットの分類で、SVMがどのようにクラスを分けているのか、グラフを使って可視化してみます。
import numpy as np import matplotlib.pyplot as plt from sklearn.svm import SVC # サンプルデータ(特徴量Xとクラスy) X = np.array([[1], [2], [3], [6], [7], [8]]) # 特徴量 y = np.array([0, 0, 0, 1, 1, 1]) # クラス(0 or 1) # モデル作成(線形SVM) model = SVC(kernel='linear', C=1.0) model.fit(X, y) # 決定境界を可視化 X_test = np.linspace(0, 9, 100).reshape(-1, 1) # 0~9の範囲で細かく分割 y_pred = model.predict(X_test) # 各点の分類結果 # グラフ描画 plt.scatter(X, y, color="blue", label="Data") # 実際のデータ plt.scatter(X_test, y_pred, color="red", s=5, label="SVM classification") # 予測結果 # タイトルとラベル plt.title("SVM Decision Boundary") plt.xlabel("Feature") plt.ylabel("Class") plt.legend() plt.show()
ポイント
- X_test = np.linspace(0, 9, 100).reshape(-1, 1)
- 細かいテストデータを作成して決定境界を確認する
- plt.scatter(X_test, y_pred, color="red", s=5)
- 小さい赤点で各点の予測結果を可視化
非線形な分類
上ではカーネルとして線形の場合を考えましたが、非線形な場合も考えてみましょう。
import numpy as np import matplotlib.pyplot as plt from sklearn.svm import SVC # サンプルデータ(非線形分布) X = np.array([[1], [2], [3], [7], [8], [9]]) # 特徴量 y = np.array([0, 0, 1, 1, 0, 0]) # クラス(0 or 1) # モデル作成(非線形SVM: RBFカーネル) model = SVC(kernel='rbf', C=1.0, gamma='auto') model.fit(X, y) # 決定境界を可視化 X_test = np.linspace(0, 10, 100).reshape(-1, 1) # 0~10の範囲でテストデータ作成 y_pred = model.predict(X_test) # 各点の分類結果 # グラフ描画 plt.scatter(X, y, color="blue", label="Data") # 実際のデータ plt.scatter(X_test, y_pred, color="red", s=5, label="SVM Classification") # 予測結果 # タイトルとラベル plt.title("SVM (RBF kernel) Decision Boundary") plt.xlabel("Feature") plt.ylabel("Class") plt.legend() plt.show()
ポイント
- kernel='rbf' で 非線形分類 に対応
- gamma='auto' で データに応じた適切な曲線を引く