#K近傍法 (K-Nearest Neighbor) 概要
k近傍法(以下k-NN)はもっとも単純な分類アルゴリズムであり、予測したいデータと距離の近い、k個の訓練データの正解ラベルから予測値を決定するアルゴリズムである。
<メリット>
- モデルの過度な調整無しにある程度の精度が出る
- アルゴリズムの理解が容易
<デメリット>
- データの前処理必須
- 特徴量(数百以上)の多いデータセットでは上手く機能しない
- 疎なデータセットでは精度が出ない
- 処理速度が遅い
上記デメリットから実務上あまり使われることはない。
K-NNの以下の2つのうち分類(Classification)について本記事ではまとめる。
- Nearest Neighbor Classification (分類)
- Nearest Neighbor Regression (回帰)
#分類: Nearest Neighbor Classification
予測のためのHyper Parameter は以下。
参考=> sklearn
Parameters | 詳細 |
---|---|
n_neighbors | アルゴリズム判断に用いる近傍点の数 (default=5) |
weights | 予測判断に用いる重みの設定 (default="uniform") "uniform":均一な重み "distance":距離に応じた重み |
algorithm | 予測のためのアルゴリズム (default="auto") "ball_tree":BallTreeアルゴリズム "kd_tree":KD Treeアルゴリズム "brute":総当たり探索 "auto": 最適なアルゴリズムを自動で選択 |
leaf_size | KD Tree, Ball Treeアルゴリズムを用いるときのリーフサイズ |
metric | 距離の測定方法 (default="minkowski) |
p | Minkowski metricにおけるPower Parameter |
n_jobs | 利用するCPU数の設定 (default=1) |
#Cancer Datasetでの予測分類
実際にsklearnのcancer datasetにて分類予測を行う。
まず必要なライブラリを読み込む。
classfication_reportは予測値の評価に用いる。
#必要なライブラリの読み込み
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
#sklean cancer dataの読み込み
from sklearn.datasets import load_breast_cancer
Cancer DataSetの詳細を確認する。
sklearn cancer datasetには説明変数(特徴量)が30、569のデータポイントがある。
目的変数(ラベル)のうち"0"が悪性の腫瘍(malignant)、"1"が良性の腫瘍(benign)を示す。
dataset = load_breast_cancer()
# 特徴量 (説明変数)
X = pd.DataFrame(dataset.data,
columns=dataset.feature_names)
#ラベル(目的変数)
y = pd.Series(dataset.target, name='y')
# データ詳細確認
print('X shape: (%i,%i)' %X.shape)
print(y.value_counts())
display(X.join(y).head())
実際に訓練データ/テストデータに分割の上、予測精度の確認を行う。
ハイパーパラメーターのうち近傍オブジェクト数を変数(1~10)とし、予測精度の変化をプロットする。
from sklearn.neighbors import KNeighborsClassifier
#データセットをtest sampleを割合20%でホールドアウトする。
X_train, X_test, y_train, y_test = train_test_split(X,y, random_state=0, test_size=0.2)
#近傍オブジェクト数とその予測スコアを格納するリストを準備
List_n_neighbors = []
List_train_score = []
List_test_score = []
#近傍オブジェクト数を1-10で予測値を比較。訓練データに対してfitする。
for n_neighbors in range(1,11):
clf = KNeighborsClassifier(n_neighbors = n_neighbors).fit(X_train,y_train)
#訓練スコアと予測スコアを算出してリストに格納
List_n_neighbors.append(n_neighbors)
List_train_score.append(clf.score(X_train,y_train))
List_test_score.append(clf.score(X_test,y_test))
#近傍オブジェクト数に対して訓練スコア、テストスコアをプロットする
fig = plt.figure(figsize = (10,6))
plt.plot(List_n_neighbors, List_train_score, label = "training accuracy")
plt.plot(List_n_neighbors, List_test_score, label = "test accuracy")
plt.ylabel("Accuracy")
plt.xlabel("n_neighbors")
plt.xticks(np.linspace(1,11,11))
plt.legend()
#まとめ
Cancer Datasetを用いた予測においては近傍オブジェクト数(k)がk=6あたりが最良の性能であることがうかがえる。ただしK=2の場合でも88%程度の精度が担保されており、特徴量30程度のCancer Datasetに関してはNearest Neighbor Classificationによる分類は十分に機能しているといえる。
以下classification_reportによる結果を確認しても再現率(recall)、適合率(precision)ともに大きな偏りなく精度を保っていることが確認できる。
ただし実際に実務上、ガンの診断に使えるかというと以下classification_reportによる結果を確認するとmalignant再現率(recall)の精度から悪性47件のうち3件程度は悪性腫瘍(malignant)を良性(benign)と判断してしまう点から十分な精度ではないと思われる。
clf = KNeighborsClassifier(n_neighbors = 6).fit(X_train,y_train)
predict_result = clf.predict(X_test)
print(classification_report(y_test,predict_result, target_names=["malignant","benign" ]))