LoginSignup
1
0

More than 3 years have passed since last update.

K最近傍法(K-Nearest Neighbor) 分類 基礎

Posted at

K近傍法 (K-Nearest Neighbor) 概要

k近傍法(以下k-NN)はもっとも単純な分類アルゴリズムであり、予測したいデータと距離の近い、k個の訓練データの正解ラベルから予測値を決定するアルゴリズムである。

<メリット>
- モデルの過度な調整無しにある程度の精度が出る
- アルゴリズムの理解が容易

<デメリット>
- データの前処理必須
- 特徴量(数百以上)の多いデータセットでは上手く機能しない
- 疎なデータセットでは精度が出ない
- 処理速度が遅い

上記デメリットから実務上あまり使われることはない。

K-NNの以下の2つのうち分類(Classification)について本記事ではまとめる。

  1. Nearest Neighbor Classification (分類)
  2. 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())

image.png

実際に訓練データ/テストデータに分割の上、予測精度の確認を行う。
ハイパーパラメーターのうち近傍オブジェクト数を変数(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()

image.png

まとめ

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" ]))

image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0