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は予測値の評価に用いる。
#必要なライブラリの読み込み
%matplotlibinlineimportnumpyasnpimportmatplotlib.pyplotaspltimportpandasaspdfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_report#sklean cancer dataの読み込み
fromsklearn.datasetsimportload_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)とし、予測精度の変化をプロットする。
fromsklearn.neighborsimportKNeighborsClassifier#データセットを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する。
forn_neighborsinrange(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"]))