はじパタ全力解説: 第5章 k最近傍法(kNN法)

[「はじめてのパターン認識」](https://amzn.to/2JlEWRz)の第5章「k最近傍法(kNN法)」解説です。
**最近傍法**は[Andrew Ng先生の機械学習入門コース](https://qiita.com/FukuharaYohei/items/b2143413063376e97948)になかった内容です。名前とイメージだけは知っていて詳しく調べたことがなかった最近傍法をようやく理解できました。
第4章に比べるとわかりやすく感じますが、私にとっては視覚的な内容をブログに書くのに時間がかかりました(最後はかなり省略していますが・・・)。第3章を理解している前提での内容でもあり、簡単なわけではありません。
[はじめてのパターン認識 第5章 k最近傍法(k_nn法)](https://www.slideshare.net/moa108/5-kknn)が詳しく書いてくれていて非常に参考になりました。
※はじパタ勉強系は[記事「文系社会人がはじパタで機械学習を数式含めて理解した奮闘記」](https://qiita.com/FukuharaYohei/items/c56eaaa06bc85237f2f5)にまとめました。

# 内容
## 5.1 最近傍法とボロノイ境界
最近傍法を概要レベルで理解すると図のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/78668779-ecc2-8502-7638-14cfd36b0677.png)

以下の式はk個のクラス、i番目クラスの学習データ数が$N(i)$個の場合です。**最近傍法(Nearest Neighbor法)**では、ユークリッド距離で計算します。学習データを**鋳型**(template)と呼びます(鋳型はクラス単位ではなく1件の観測データ単位です)。
※$d$は距離を示しています。

|内容|式|
|:-:|:-:|
|K個のクラス|$\Omega=\\{C_1, \cdots, C_k\\}$|
|i番目のクラスの学習データ数|$N(i)$|
|i番目のクラスの学習データ数の集合|$S_i=\\{x_1^{i}, \cdots, x_{N(i)}^{i}\\}$|
|入力データ($x$)と学習データ($x_j^{(i)}$)の類似度<br>ユークリッド距離|$d(x,x_j^{(i)})=&#124;&#124;x-x_j^{(i)}&#124;&#124;$|

以下が識別規則で$t$はリジェクトするためのしきい値です。$\min_{i,j} d(x,x_j^{(i)})$は、クラス$i$の中で一番近い観測データとの距離を示しています。

```math
{  \begin{cases}
    \arg \min_i \{ \min_j d(x, x_j^{(i)})\} & \Leftarrow \min_{i,j} d(x,x_j^{(i)}) < t のとき \\
    リジェクト & \Leftarrow \min_{i,j} d(x,x_j^{(i)}) \ge t のとき \\
  \end{cases}
}
```

### 5.1.1 ボロノイ図
**最近傍法のポイントは入力データに最も近い鋳型を見つける**ことです。鋳型ごとに自身の支配領域(その領域に観測データが入った場合に鋳型の属するクラスに識別)を持ち、その領域をボロノイ領域、その境界をボロノイ境界と呼びます。[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%AD%E3%83%8E%E3%82%A4%E5%9B%B3)がわかりやすいです。
ボロノイ境界等を2次元、２つの鋳型で例示すると以下の図のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/1408c84a-cb43-566c-f852-61fa088ddb54.png)

鋳型が3つ以上の場合の$x_i$のボロノイ領域は、各鋳型間の半空間の積集合は以下の式と図です(鋳型の集合を$S=\\{x1, \cdots, x_N\\}$とします)。

```math
VR(x_i,S) = \displaystyle\bigcap_{x_j \in S, j \ne i}{D(x_i, x_j)}
```

(汚い図で恐縮ですが)3つの鋳型で例を書きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/38e5ba67-91a7-192f-e0e0-d8e00875d6f6.png)

### 5.1.2 鋳型の数と識別性能
最近傍法は学習データ数が多いほど精度が向上します。

## 5.2 kNN法
最近傍の鋳型を近いものから$k$個とってきて、鋳型が最も多く所属するクラスに識別する方法をk最近傍法(kNN法)と呼びます。所属する鋳型数が同数の場合はリジェクトとする場合と、ランダムに決定する場合があります。
下図の例だと$k=3$としたら、クラス1よりクラス2に属する鋳型数が多いのでクラス2とし、$k=6$の場合は逆でクラス1に識別します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/26d28cbd-19ca-ba9f-6c0f-9862c0496128.png)

最近傍法の場合は、他クラスの鋳型に囲まれる孤立点ができます。kNN法にすると、多数決型なので一定程度の異常値を許容し孤立点が少なくなります。

## 5.3 kNN法とベイズ誤り率
kNN法とベイズ誤り率との関係です。
2値分類とした場合の仮想データで、ベイズ識別規則および1NN, 2NNの誤り率を出しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/5c81c09c-f514-8f20-6746-94022fc52508.png)
今回の場合は、誤り率について以下の大小関係となっています。これを一般化したときにどうなるかを見ていきます。

```math
\hat{\epsilon}_{2NN} \leq \hat{\epsilon}^* \leq \hat{\epsilon}_{1NN}
```

### 5.3.1 漸近仮定とkNN誤り率の期待値
最近棒法の理想として鋳型の数が無限大にあるとするとします(この仮定を**漸近仮定**と呼ぶっぽい)。
入力$x$の最近傍鋳型を$x_{1NN}$とし、N個の鋳型の集合を$T_N$としたときに以下の式が成り立ちます。これは、「ユークリッド空間に無限に鋳型あれば、一番近い鋳型との距離は0」ってことです。

```math
\lim_{N \to \infty} T_N \Rightarrow d(x, x_{1NN}) \rightarrow 0
```

その前提のもとに、kNN誤り率とベイズ誤り率との間に次の大小関係が成立します。

```math
\frac{1}{2} \epsilon^* \le \epsilon_{2NN} \le \epsilon_{4NN} \le \cdots \le 
\epsilon^* \le  \cdots \le \epsilon_{3NN} \le \epsilon_{1NN} \le  2\epsilon^*
```

**偶数NN**が真ん中より左で**NNの数が少ないほど誤り率が少ない**です。
**奇数NN**は真ん中より右で**NNの数が少ないほど誤り率が多い**です。
私の理解では、二値分類で偶数NNの場合はリジェクトが起こる可能性があり、誤り率低下に寄与します。リジェクトはNNの数が少ないほど起きやすいので2NNが最も誤り率が少なくなりやすいです。逆に二値分類で奇数NNは、リジェクトが起きません。そのため、必ずベイズ誤り率よりも誤り率が高くなります。そして、鋳型が無限あると仮定するとNNの数が多い方が、誤りが起きにくいです。
証明部分の解説は省略します。

### 5.3.2 漸近仮定は成り立つか
**次元数が多いと漸近仮定は成り立ちません**。
[第1章の「次元の呪いとサンプル間の距離」](https://qiita.com/FukuharaYohei/items/728b3fc15b5ddc9d9762#%E6%AC%A1%E5%85%83%E3%81%AE%E5%91%AA%E3%81%84%E3%81%A8%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E9%96%93%E3%81%AE%E8%B7%9D%E9%9B%A2)で書いたのですが、次元が多い場合にデータは近傍に集まらず遠い場所に集まってしまいます。そのため、$\lim_{N \to \infty} T_N \Rightarrow d(x, x_{1NN}) \rightarrow 0$とはなりません。

## 5.4 kNN法の計算量とその低減法
kNNは計算量が多く計算時に必要なメモリ容量も多いため、それらを低減する方法がいくつかあります。

### 5.4.1 誤り削除型kNN
kNNで誤って識別されたデータを削除します。削除後に識別境界が変わるので再帰的に繰り返すことも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/5be70540-122d-f791-4056-77d9d7ef8b55.png)

### 5.4.2 圧縮型kNN
識別境界以外のデータはあまり重要ではないので消します。
消す際には、以下の条件付きベイズ誤り率が小さくなるようにします。

```math
\epsilon(x) = min[P(C_1 \mid x), P(C_2 \mid x)]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/66cd811c-5b9e-8b1f-7a95-c7f6240feba4.png)

### 5.4.3 分枝限定法
分枝限定法と呼ばれる探索方法があります(kNNに限らない手法のようです)。データを階層型クラスタリングで構造化します([「言語処理100本ノック-98本目」](https://qiita.com/FukuharaYohei/items/8648da8bbad27c841479)でやりました)。
例えば、2次元のデータを階層型クラスタリングしたイメージ図です。最上位では$S_1, S_2, S_3$の3つに分け、$S_3をさらにS_4とS_5$に分けています。
ここでそれぞれのクラスタに平均ベクトル$m_i$(図の青の矢印)と平均ベクトルから最も遠いデータまでの距離$d_i$(図の緑の矢印)を計算しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/c698f641-a605-55b2-30b6-4732a32ee449.png)

そして、図のように探索をしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/08dd74e5-bd49-46fb-22a3-ee64d494a858.png)

探索をしてクラスタ$S_4$に属する最も近い$x_{38}$を見つけた場合、クラスタ$S_5$に属するデータと比較する必要がないかを以下の計算式でチェックします。

```math
d(x,m_5) > d(x, x_{38}) +d_5
```

すごい汚いですが、1次元で表すとこういうことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/e01c4a23-7437-cbe0-a3fe-201e3e1bc279.png)

### 5.4.4 近似最近傍探索
自身のデータを$q$、各鋳型を近い順に$x_D, x_A, x_B, x_C, x_E$とします。$q$は$x_D$に所属。

1. 超空間を分割していく(分割した結果は二分木で表現できる)
2. 所属する超空間のデータとの距離を計算: $d(q, x_D)$を求める
3. 最も近い(データではなく)分割した超空間($A$)との距離($d(q, A)$)を計算
4. 現時点での最短なデータとの距離を$1+\epsilon$で割った値と超空間との距離を比較し、近似最近傍かを判断
あとは、判断結果によって3と4を繰り返します。

```math
{  \begin{cases}
    x_Dが近似解 & \Leftarrow  \frac{d(1, x_D)}{1+\epsilon} \le d(q, A)\\
    次の超空間へ進む & \Leftarrow  \frac{d(1, x_D)}{1+\epsilon} > d(q, A) \\
  \end{cases}
}
```

(データではなく)領域までの大小関係が判断できれば、データに対する大小関係も成り立ちます。

```math
d(q, x_D) < (1 + \epsilon) d(q, A) < (1 + \epsilon) d(q, x_A)
```

# 「はじパタ」勉強系記事リンク

|章|項目|時間(h)|難易度|学んだこと|
|:-:|:--|:-:|:-:|:--|
|1|[はじめに](https://qiita.com/FukuharaYohei/items/728b3fc15b5ddc9d9762)|8.9|:star:|特徴の型, 特徴空間, 次元の呪い|
|2|[識別規則と学習法の概要](https://qiita.com/FukuharaYohei/items/0bae9bbaef0099627751)|12|:star:|ホールドアウト法,交差確認法 ,一つ抜き法 ,ブートストラップ法 ,バイアス・分散トレードオフ, 過学習|
|3|[ベイズの識別規則](https://qiita.com/FukuharaYohei/items/1f05e6550ed73329febd)|14.8|:star:|ベイズ識別規則, ROC曲線|
|4|[確率モデルと識別関数](https://qiita.com/FukuharaYohei/items/10979bbd934410e82c42)|18|:star::star:|平均ベクトル, 共分散行列, 標準化, 無相関化, 白色化, 正規分布, 最尤推定|
|5|[k最近傍法(kNN法)](https://qiita.com/FukuharaYohei/items/0314f73cebb471deb515)|8|:star::star:|最近傍法, ボロノイ境界, kNN|
|6|[線形識別関数(前半)](https://qiita.com/FukuharaYohei/items/d1b4300055584d3f1727)|30.4|:star::star:|正規方程式|
|6|[線形識別関数(後半)](https://qiita.com/FukuharaYohei/items/f1933c0430704f86c60a)|前半に時間は含む|:star::star::star:|フィッシャーの線形判別関数, 判別分析法, ロジスティック回帰|
|7|[パーセプトロン型学習規則](https://qiita.com/FukuharaYohei/items/410655034fdef5204879)|13.5|:star::star:|多層パーセプトロン, 誤差逆伝播法, シグモイド関数|
|8|[サポートベクトルマシン](https://qiita.com/FukuharaYohei/items/5375d9bfe6bd471288ea)|14.7|:star::star:|カーネルトリック, ν-SVM|
|9|[部分空間法](https://qiita.com/FukuharaYohei/items/47624bac931b2668e888)|15.4|:star::star::star:|主成分分析, 特異値分解, CLAFIC法, カーネル主成分分析, カーネル部分空間法|
|10|[クラスタリング](https://qiita.com/FukuharaYohei/items/c58f6eea336ce5d9c00f)|8.4|:star::star:|距離の公理, ミンコフスキー距離, K-平均法, 融合法, 混合正規分布モデル|
|11|[識別機の組み合わせによる性能強化](https://qiita.com/FukuharaYohei/items/502d2d2b99ccd3980d75)|11.6|:star::star:|ノーフリーランチ定理, 決定木, バギング, アダブースト, ランダムフォレスト|