以下のコードでは「Pythonではじめる機械学習」の著者が公開しているmglearn
を使用します。
$ pip install mglearn
リンク
データセット
クラスタデータモデルを使用。
from sklearn.datasets import make_blobs import mglearn import matplotlib.pyplot as plt X, y = make_blobs(centers=4, random_state=8) y = y % 2 mglearn.discrete_scatter(X[:,0], X[:,1], y) plt.xlabel("Feature 0") plt.ylabel("Feature 1")
2次元でのフィッティングを行ってみても...
from sklearn.svm import LinearSVC liner_svm = LinearSVC().fit(X, y) mglearn.plots.plot_2d_separator(liner_svm, X) mglearn.discrete_scatter(X[:,0], X[:,1], y) plt.xlabel("Feature 0") plt.ylabel("Feature 1")
このように現在の特徴量では線形で分類できないデータセットとなる。
但し、Feature1の特徴量を見ると、Feature1の量で分類できるようなデータセットとして受け取れる。傾向は0に近いクラスと上下に分散されているクラスがある。
Feature1の特徴量を"高さ"として扱う
片方のクラスのFeature1の特徴量が0に近いので、2乗することで特徴量を切り出し、次元追加を行う。
import numpy as np X_new = np.hstack([X, X[:, 1:] ** 2]) from mpl_toolkits.mplot3d import Axes3D, axes3d figure = plt.figure() ax = Axes3D(figure, elev=-152, azim=-26) mask = y == 0 ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c="b", cmap=mglearn.cm2, s=60) ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c="r", marker="^", cmap=mglearn.cm2, s=60) ax.set_xlabel("Feature0") ax.set_ylabel("Feature1") ax.set_zlabel("Feature1 ** 2")
このように次元追加を行いFeature1**2でのクラスタの纏まりが確認できる。
サポートベクタマシンで学習を行う
分類の学習を行います。
from sklearn.svm import LinearSVC liner_svm_3d = LinearSVC().fit(X_new, y) coef, intercept = liner_svm_3d.coef_.ravel(), liner_svm_3d.intercept_ figure = plt.figure() ax = Axes3D(figure, elev=-152, azim=-26) xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50) yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50) XX, YY = np.meshgrid(xx, yy) ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2] ax.plot_surface(XX, YY, ZZ, rstride=8, cstride=8, alpha=0.3) ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c="b", cmap=mglearn.cm2, s=60) ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c="r", marker="^", cmap=mglearn.cm2, s=60) ax.set_xlabel("feature0") ax.set_ylabel("feature1") ax.set_zlabel("feature1**2")
このように2次元では分類できないデータセットに次元追加を行い非線形データを分類することができる。
カーネル関数
また、上記の次元追加には実装を行ったんだけど、実際はサポートベクタマシンに特徴量に応じてカーネル関数を利用したりする。
from sklearn.svm import SVC kernel_name = 'linear' # or 'rbf' or 'poly' or 'sigmoid' liner_svm_3d = SVC(kernel=kernel_name).fit(X_train, y_train)
リンク