データ分析初心者の備忘録

不定期で更新していきます。

scikit-learnで使える機械学習手法まとめ


機械学習ライブラリscikit-learnを活用して実行できるアルゴリズムの特徴と実行方法、実行結果をまとめました。 アルゴリズムの実行にはUIC Machine Learning Repositoryに登録されているBreast Cancer Wisconsinデータセットを用いています。 なお、理論の説明というよりは使用する際の注意点や実行方法をメインに記載しています。

目次

  • 使用するデータセットの確認
  • パーセプトロン
  • ロジスティック回帰
  • SVM (サポートベクトルマシン)
  • 決定木
  • ランダムフォレスト
  • k近傍分類器(KNN: k-nearest neighbor classifier)

使用するデータセットの確認

UIC Machine Learning Repositoryに登録されているBreast Cancer Wisconsinデータセットを用います。 データセットの1列目はユニークIDで、2列目がクラスラベル(M、Bの2値)です。

import pandas as pd
import urllib

#データセットの読み込み
#breast cancer wisconsin dataset
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases'
                     '/breast-cancer-wisconsin/wdbc.data', header=None)

print('rows, columns:', df.shape)
df.head()

f:id:kuze3110:20171015234448p:plain

なお、決定境界を可視化したい都合上、特徴量を2つに絞って学習に使います。

#使用する特徴量2個に絞った上でデータの確認
X = df.loc[:,[4,14]]
X.head()

データの確認のため、MとBのラベルごとにデータをプロットします。

%matplotlib inline
import matplotlib.pyplot as plt

X1 = df[df[1] == 'M'] #クラスラベルがMのデータを抽出
X1.head()
X1_array = X1.loc[:,[4,14]].values

X0 = df[df[1] == 'B'] #クラスラベルがBのデータを抽出
X0.head()
X0_array = X0.loc[:,[4,14]].values

plt.scatter(X1_array[:,0], X1_array[:,1], c = 'blue', marker = "x") #Mは青色で☓のマーカー
plt.scatter(X0_array[:,0], X0_array[:,1], c = 'red', marker = "s") #Bは赤色で■のマーカー

plt.title("scatterplot")
plt.xlabel("feature1")
plt.ylabel("feature2")
plt.show()

f:id:kuze3110:20171015234852p:plain

使用するデータセットをトレーニングデータとテストデータに分割

データセットを8:2の比率で分け、それぞれトレーニングデータ、テストデータとします。

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20, random_state = 1)

データの標準化

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

パーセプトロン

線形識別関数を用いたネットワークモデル。  完全な線形分離が不可能なデータセットでは収束しないため、一般に実務のデータ解析で使われることは少ない。

実行例

from sklearn.linear_model import Perceptron

#エポック数40, 学習率0.1でパーセプトロンのインスタンスを生成
ppn = Perceptron(n_iter=40, eta0=0.1, random_state=0)
#トレーニングデータをモデルに適合させる
ppn.fit(X_train_std, y_train)

#テストデータで予測を実施
y_pred = ppn.predict(X_test_std)
#誤分類のサンプルの個数を表示
print('Misclassified samples: %d' % (y_test != y_pred).sum())
#Misclassified samples: 12

from sklearn.metrics import accuracy_score
#分類の正解率を表示
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
#Accuracy: 0.89

f:id:kuze3110:20171015235528p:plain

コード中に出てくる「正解率」の定義は「1-誤分類率」。 不均衡データの場合はモデルの精度が悪くても正解率の値が高くなりがちなので注意が必要。

ロジスティック回帰

「回帰」という名前だが、回帰ではなく分類のためのモデルであり、 線形分離と二値分類に関して、パーセプトロンより優れた分類モデル。

実行例

from sklearn.linear_model import LogisticRegression
#ロジスティック回帰のインスタンスを生成
lr = LogisticRegression(C=1000.0, random_state=0)
#トレーニングデータをモデルに適合させる
lr.fit(X_train_std, y_train)

#サンプルの所属確率を予測
y_pred = lr.predict(X_test_std)
print('Misclassified samples: %d' % (y_test != y_pred).sum())
#Misclassified samples: 12

#正解率
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))
#Accuracy: 0.89

f:id:kuze3110:20171028164940p:plain

SVM (サポートベクトルマシン)

パーセプトロンの拡張と見なせる。 マージン(クラスを分離する境界線である「超平面」とこの超平面に最も近いトレーニングサンプルとの距離)を最大化させることが目的。 マージンの小さいモデルは過学習に陥りがち。 γパラメータの値を小さくするとトレーニングサンプルの影響力が大きくなり、到達範囲が大きくなることで決定境界がなめらかになる。

《利点》 カーネルトリックを使って非線形問題の解を求めることが可能である。 ロジスティック回帰よりも外れ値の影響を受けにくい。

《欠点》 予測を適切に行うために調節しなければならないパラメータの数が多い。

《補足》
バイアスとバリアンス
バリアンスが高い→過学習が発生しているモデル
バイアスが高い→学習不足になっているモデル

正則化
共線性(特徴量の間の相関の高さ)を処理する手法で、データからノイズを取り除き最終的に過学習を防ぐ
一般的にL2正則化が使われる
なお、正則化を正常に機能させるためには標準化が必要

実行例 (線形SVM)

from sklearn.svm import SVC
#線形SVMのインスタンスを生成
svm = SVC(kernel='linear', C=1.0, random_state=0)
#線形SVMのモデルにトレーニングデータを適合させる
svm.fit(X_train_std, y_train)

#予測
y_pred = svm.predict(X_test_std)
print('Misclassified samples: %d' % (y_test != y_pred).sum())
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))

#Misclassified samples: 12
#Accuracy: 0.89

f:id:kuze3110:20171028170704p:plain

実行例 (カーネルSVM)

#RBFカーネルによるSVMのインスタンスを生成
svm = SVC(kernel='rbf', random_state=0, gamma=0.2, C=1.0)
svm.fit(X_train_std, y_train)

#予測
y_pred = svm.predict(X_test_std)
print('Misclassified samples: %d' % (y_test != y_pred).sum())
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))

#Misclassified samples: 13
#Accuracy: 0.89

f:id:kuze3110:20171028170953p:plain

決定木

情報利得(information gain)が最大となるような特徴量でデータを分割する。
特徴量の標準化はしなくてもサンプルの分割に影響しないため、可視化する目的でない場合は標準化しなくても良い。
(決定木では数値の分割条件を値の大小関係として捉えるため、標準化が影響しない)

《補足》
情報利得
「親ノードの不純度」と「子ノードの不純度」の差
子ノードの不純度が低いほど、情報利得は大きくなる

不純度
ノードが純粋ではない程度、すなわちノードに異なるクラスのサンプルがどの程度の割合で混ざっているか定量化する指標
よく使用される不純度の指標としてジニ不純度エントロピー分類誤差がある
ジニ不純度とエントロピーは非常によく似た結果になることが多い

実行例

from sklearn.tree import DecisionTreeClassifier
#エントロピーを指標とする決定木のインスタンスを生成
tree = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=0)
#決定木のモデルにトレーニングデータを適合させる
#決定木は特徴量のスケーリングが不要なため、X_train_stdでなくX_trainを使用
tree.fit(X_train, y_train)

X_combined = np.vstack((X_train, X_test))
y_combined = np.hstack((y_train, y_test))

#予測
y_pred = tree.predict(X_test)
print('Misclassified samples: %d' % (y_test != y_pred).sum())
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))

#Misclassified samples: 15
#Accuracy: 0.87

f:id:kuze3110:20171028171125p:plain

ランダムフォレスト

決定木のアンサンブルである。
個々の決定木をトレーニングする際、全ての特徴量を評価するのではなくその一部をランダムに比較検討するだけ。

《利点》
分類性能が高い
パラメータの調整がそれほど必要でない
決定木ほど過学習に陥りやすくない ハイパーパラメータに適切な値を設定することについては「決定木」に比べてあまり悩む必要はなく、実際に検討が必要なパラメータは選択する決定木の個数(k)だけ

《補足》
アンサンブル
弱い学習アルゴリズムを組み合わせて強い学習アルゴリズムを構築するというもの

強い学習アルゴリズム
汎化誤差が改善され、過学習に陥りにくい

実行例

from sklearn.ensemble import RandomForestClassifier
#エントロピーを指標とするランダムフォレストのインスタンスを生成
forest = RandomForestClassifier(criterion='entropy', #criterionで指標を指定
                                n_estimators=10,  #n_estimatorsで木の数を指定
                                random_state=1,
                                n_jobs=2) #n_jobsパラメータはPCの複数のコアを使うことを指定している

#決定木同様、ランダムフォレストは特徴量のスケーリングが不要なため、X_train_stdでなくX_trainを使用
forest.fit(X_train, y_train)

#予測
y_pred = forest.predict(X_test)
print('Misclassified samples: %d' % (y_test != y_pred).sum())
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))

#Misclassified samples: 14
#Accuracy: 0.88

f:id:kuze3110:20171028171342p:plain

k近傍分類器(KNN: k-nearest neighbor classifier)

怠惰学習(lazy learner)の一つ。
選択された距離指標に基づきデータ点を分類する。
データセットの特徴量に適した距離指標を選択することが重要。
距離指標としては単純なユークリッド距離が使われることが多く、その場合は各特徴量を標準化する必要がある。

《利点》
予測を行うにあたってのトレーニングを必要としない。

《欠点》
予測の計算コストが高い。

《補足》
パラメトリックモデル
トレーニングデータセットからパラメータを推定するため、元のトレーニングデータセットがなくても新しいデータを分類できる。
パーセプトロン、ロジスティック回帰、線形SVMなど。

ノンパラメトリックモデル
固定のパラメータ集合で特徴づけることができず、パラメータの個数はトレーニングデータセットとともに増加する。
決定木、ランダムフォレスト、カーネルSVMなど。

実行例

from sklearn.neighbors import KNeighborsClassifier
#k近傍法のインスタンスを生成
knn = KNeighborsClassifier(n_neighbors=5, p=2, metric='minkowski') #p=2で指標としてユークリッド距離を指定
#k近傍法のモデルにトレーニングデータを適合させる
knn.fit(X_train_std, y_train)

#予測
y_pred = knn.predict(X_test_std)
print('Misclassified samples: %d' % (y_test != y_pred).sum())
print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))

#Misclassified samples: 14
#Accuracy: 0.88

f:id:kuze3110:20171028171638p:plain