クラス分類問題において、K近傍法による識別手法を実装・解説します。
本シリーズでは、Pythonを使用して機械学習を実装する方法を解説します。
また各アルゴリズムの数式だけでなく、その心、意図を解説していきたいと考えています。
K近傍法(KNeighbors Classifier)は、以下のscikit-learnマップの黒矢印に対応します。
START→データが50以上→カテゴリーデータ→ラベルありデータ→データ数10万以下→Linear SVCがうまくいかない→[K近傍法]
K近傍法は識別平面の式を生成しないタイプのクラス分類手法です。
式を生成しないので、ノンパラパラメトリックモデルであり、怠惰学習と呼ばれたりもします。
実装例
まずはじめに実装例を紹介します。
使用するデータは第2回のカーネル近似と同じくXORの分類データです。
これに対してK近傍法を行うと、以下のような結果となります。
カーネル近似のときより、キレイに識別面ができ、平均正答率も高いです。
コードは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | # 1:ライブラリのインポート-------------------------------- import numpy as np #numpyという行列などを扱うライブラリを利用 import pandas as pd #pandasというデータ分析ライブラリを利用 import matplotlib.pyplot as plt #プロット用のライブラリを利用 from sklearn import neighbors, metrics, preprocessing, cross_validation #機械学習用のライブラリを利用 from mlxtend.plotting import plot_decision_regions #学習結果をプロットする外部ライブラリを利用 from sklearn.kernel_approximation import RBFSampler #カーネル近似用の関数 from matplotlib.colors import ListedColormap #plot用 # 2:XORのデータを作成する(x=正、y=正)=0,(x=正、y=負)=1, 的な-------------- np.random.seed(0) X_xor=np.random.randn(200,2) y_xor=np.logical_xor(X_xor[:,0]>0, X_xor[:,1]>0) y_xor=np.where(y_xor,1,0) pd.DataFrame(y_xor) #この行を実行するとデータが見れる # 3:プロットしてみる------------------------------------------------------ %matplotlib inline plt.scatter(X_xor[y_xor==1, 0], X_xor[y_xor==1, 1], c='b', marker='x', label='1') plt.scatter(X_xor[y_xor==0, 0], X_xor[y_xor==0, 1], c='r', marker='s', label='0') plt.legend(loc='best') plt.show # 4:データの整形------------------------------------------------------- X_std=X_xor z=y_xor # 解説5:機械学習で分類する--------------------------------------------------- n_neighbors = 5 clf_result=neighbors.KNeighborsClassifier(n_neighbors, weights = 'distance') #weights = 'uniform' # 6:K分割交差検証(cross validation)で性能を評価する--------------------- scores=cross_validation.cross_val_score(clf_result, X_std, z, cv=10) print("平均正解率 = ", scores.mean()) print("正解率の標準偏差 = ", scores.std()) # 7:トレーニングデータとテストデータに分けて実行してみる------------------ X_train, X_test, train_label, test_label=cross_validation.train_test_split(X_std,z, test_size=0.1, random_state=0) clf_result.fit(X_train, train_label) #正答率を求める pre=clf_result.predict(X_test) ac_score=metrics.accuracy_score(test_label,pre) print("正答率 = ",ac_score) #plotする X_train_plot=np.vstack(X_train) train_label_plot=np.hstack(train_label) X_test_plot=np.vstack(X_test) test_label_plot=np.hstack(test_label) #plot_decision_regions(X_train_plot, train_label_plot, clf=clf_result, res=0.01) #学習データをプロット plot_decision_regions(X_test_plot, test_label_plot, clf=clf_result, res=0.01, legend=2) #テストデータをプロット # 8:任意のデータに対する識別結果を見てみる------------------ #predicted_label=clf_result.predict([1.0,-1.0]) #print("このテストデータのラベル = ", predicted_label) |
コードに関してはカーネル近似やLinear SVCのときとほぼ同じです。
今回は正規化が既にされているのでしていませんが、正規化は必須です。
解説5の部分だけ異なります。
#解説 5:機械学習で分類する—————————————————
n_neighbors = 5
clf_result=neighbors.KNeighborsClassifier(n_neighbors, weights = ‘distance’)
識別器としてKNeighborsClassifierを使用します。
識別したい点から何点の近傍を考慮するのかを、n_neighbors = 5で設定しています。
またweightsは近傍にあった5点を評価するさいに、’uiform’だと点までの距離を考慮しないです。
一方weightsを’distance’にすると距離も考慮して、分類を決定します。
それでは「結局、K近傍法って何をやっていたの?」を説明します。
K近傍法の心
正確な情報は以下をご覧ください。
●scikit-learnのNNeighborsの解説ページ
●scikit-learnのKNeighbors Classifierの解説ページ
K近傍法では識別したいデータ点から、距離が近いK点の学習データを探します。
そしてK点のうち一番ラベルが多かったクラスを識別結果とします。
ただそれだけの手法です。
アルゴリズムは非常に単純ですが、割と精度が出る面白い手法です。
ただし、欠点があります。
それは識別平面が式で書けないことです。
(ノンパラメトリック手法と呼びます)
そのため、新たな点を分類したい場合、学習データすべてと距離を計算する必要があります。
多くの機械学習では、学習に時間がかかっても識別は一瞬でできるのですが、K近傍法では識別に時間がかかるという欠点があります。
(怠惰学習と呼びます)
また識別平面の式がないので、どのパラメータがどう重要なのかの意味付けが得られにくいです。
ですが、ただ分類したいだけなら非常に強力な手法なので頭に入れておくと良いと思います。
以上、Pythonとscikit-learnで学ぶ機械学習入門|第4回:クラス分類 -K近傍法-でした。
次回は、カーネルSVCについて解説します。