【機械学習】サポートベクターマシン解説~実装編①~

今回は機械学習手法の一つであるサポートベクターマシンについてpythonを用いて実装をしていきたいと思います。
前回の解説
はじめに
今回は前回扱った機械学習手法の一つであるサポートベクターマシンの実装を行います。サポートベクターマシンの肝である「マージンの最大化」について意識しながら取り組んでいきましょう。
今回の実装はpythonを用いますが、googlecolaboratory上で行います。今回扱ったコードをそのまま使用することで同じような結果を得ることができると思います。
また、前回、線形のサポートベクターマシンのみについて扱ったので今回も線形に絞って解説していきます。
準備
python上で実装を行うためにまずはライブラリのインポートを行う必要があります。これによりモデルを使用することができたり、結果の描写などが容易に出来ます。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs
扱うデータ
今回は人口データを作成し、その人口データの分類を考えていきます。作成した人口データは次のものです。
# 人口データの生成
# 2つのクラスに分けられたデータを生成
X, y = make_blobs(n_samples=100, centers=2, random_state=6)
このように、二次元のデータです。この時、水色のデータと茶色のデータを上手く分類できるような超平面を考えます。プロットすると分かるように今回は線形分離が出来そうです。
モデルの訓練
では、作成した人口データを用いてモデルを作成、および訓練していきます。
# 線形サポートベクターマシンのモデルを訓練
model = svm.SVC(kernel='linear')
model.fit(X, y)
二行目で線形のサポートベクターマシンのモデルを作成し、三行目で人口データを用いてモデルを学習させています。コード上では簡潔に表現されますがこの時、数理的理解の部分で扱ったマージンを最大化させながら最適化問題を解くといった処理がなされています。
結果の描写
では、作成したモデルの結果を描写してみましょう。
# データの描写
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
# 決定境界を描く
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# メッシュグリッドを作成して決定境界を描画
xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 30),
np.linspace(ylim[0], ylim[1], 30))
Z = model.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 決定境界とマージンを描く
ax.contour(xx, yy, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
# サポートベクターを描く
ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100,
linewidth=1, facecolors='none', edgecolors='k')
plt.title("Linear SVM on Generated Data")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()
このように二つのクラスを分離するような決定境界が得られていることが分かります。なお、ここで丸の付いたデータはサポートベクターでありこれらの距離が最大になるようにモデルが作成されています。
未知データに対する予測
それでは作成したモデルを用いて未知のデータが入力されたときにどのように予測するのかを確認していきます。
作成した未知データは以下です。
# 未知データの生成
unknown_data = np.array([[2, 3], [5, 6], [3, 4]])
×で表されているのが未知データです。これは明らかに水色のクラスに所属しそうですがモデルはどの様に予測するのでしょうか。
# 未知データに対する予測
predictions = model.predict(unknown_data)
# 予測結果の表示
for i, point in enumerate(unknown_data):
print(f"Point {point} is predicted to be in class {predictions[i]}")
Point [2 3] is predicted to be in class 0
Point [5 6] is predicted to be in class 0
Point [3 4] is predicted to be in class 0
このようにどの未知データもクラス0、すなわち水色のクラスであるといった結果を得ることができ正しく予測されたことが確認できます。
終わりに
今回はサポートベクターマシンの線形分類における実装を扱いました。実装することで流れやイメージがより掴みやすくなったと思います。
ここまで、線形分離サポートベクターマシンについて直観的理解、数理的理解、実装を行いましたが次回からは非線形サポートベクターマシンを扱いたいと思います。