2章 実例を対象とした分類法入門
アイリスデータセット
データの中身はアイリスという花に関するもの。
アイリスデータセットは3つの種類の品種のデータに分類されます。
- がく片の長さ(Sepal length)
- がく片の幅(Sepal width)
- 花弁の長さ(Petal length)
- 花弁の幅(Petal width)
という特徴量がデータの中身です。
まずはデータを可視化します。
import numpy as np from sklearn.datasets import load_iris from matplotlib import pyplot as plt data = load_iris() features = data['data'] feature_names = data['feature_names'] target = data['target'] pairs = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] for i, (p0, p1) in enumerate(pairs): plt.subplot(2, 3, i + 1) for t, marker, c in zip(list(range(3)), ">ox", "rgb"): plt.scatter(features[target == t, p0], features[target == t, p1], marker=marker, c=c) plt.xlabel(feature_names[p0]) plt.ylabel(feature_names[p1]) plt.xticks([]) plt.yticks([]) plt.show()
それでは、データの前処理をしていきましょう。
データはcmで統一されていますが、まずは平均を0、分散を1にする「正規化」という作業をしていきます。
scaler = StandardScaler() scaler.fit(X)
そして、scikit-learnにはPolynomialFeaturesという多項式基底を作成する関数があります。
多項式基底を作ることにより、より分類を強化できます。
poly = preprocessing.PolynomialFeatures(10) X = poly.fit_transform(np.c_[features[:,0], features[:,1], features[:,2], features[:,3]])
さて、前処理がおわったので、分類をしていきましょう。
今回使う分類アルゴリズムは以下の3つです。
- ロジスティック回帰
- K-近傍法
- SVM(サポートベクターマシン)
では早速コードを見て行きましょう。
1.ロジスティック回帰
from sklearn import linear_model LogicReg = linear_model.LogisticRegression(penalty='l2', C=15) LogicReg.fit(X, y)
正則化にはL2正則化を指定します。
正則化についてはこのサイトがわかりやすいです。
breakbee.hatenablog.jp
2.K-近傍法
from sklearn.neighbors import KNeighborsClassifier k_mean = KNeighborsClassifier(n_neighbors=2, algorithm='auto') k_mean.fit(X, y)
ここで指定している”n_neighbors=2”とは...
以下のスライドを見るとわかります
23,24ページ目ぐらいに書いてあります。
3.SVM(サポートベクターマシン)
from sklearn import svm Svm = svm.SVC() Svm.fit(X, y)
SVMは
- コストパラメータ: CC
- RBFカーネルのパラメータ: γ
を決めるとより良い分類器になります。
詳しくは下のリンク先に書いてあります。
今回はデフォルト設定で行いました。
http://qiita.com/sz_dr/items/f3d6630137b184156a67
ここで、3つの分類器の分類結果を見てみましょう。
[ random_state=0 ] LogicReg : 0.977777777778 k-mean : 0.977777777778 svm : 0.977777777778
どれも約98%の精度です。
ここで、random_stateの設定値を変えるとどうなるかを実験してみました。
[ random_state=10 ] LogicReg : 1.0 k-mean : 1.0 svm : 1.0
なんと、random_state=10 にすると100%の精度になりました。
[ random_state=100 ] LogicReg : 0.933333333333 k-mean : 0.977777777778 svm : 0.977777777778
アイリスデータセットは150×4しかデータがないため非常にデータ数が少ないです。
なので、乱数の種によっては運良く分類精度100%になることもありえるということがわかりました。
全体のコードです。
import numpy as np import matplotlib.pyplot as plt from sklearn import decomposition from sklearn import linear_model, preprocessing from sklearn import svm from sklearn.grid_search import GridSearchCV from sklearn.datasets import load_iris from sklearn.cross_validation import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler data = load_iris() features = data['data'] feature_names = data['feature_names'] # ['sepal length (cm)','sepal width (cm)', # 'petal length (cm)','petal width (cm)'] target = data['target'] target_names = data['target_names'] # ['setosa', 'versicolor', 'virginica'] poly = preprocessing.PolynomialFeatures(10) X = poly.fit_transform(np.c_[features[:,0], features[:,1], features[:,2], features[:,3]]) scaler = StandardScaler() scaler.fit(X) X_scaled = scaler.transform(X) y = np.array(target) X, X_test, y, y_test = train_test_split(X_scaled, y, train_size=0.7, random_state=0) LogicReg = linear_model.LogisticRegression(penalty='l2', C=15) LogicReg.fit(X, y) print('LogicReg :', LogicReg.score(X_test, y_test)) k_mean = KNeighborsClassifier(n_neighbors=2, algorithm='auto') k_mean.fit(X, y) print('k-mean :', k_mean.score(X_test, y_test)) Svm = svm.SVC() Svm.fit(X, y) print('svm :', Svm.score(X_test,y_test))