kNN(k最近傍法)#
入力\(\boldsymbol{x}^{\text{test}}\)に最も近い\(k\)個の訓練データ\(\boldsymbol{x}_1^{\text{train}}, \dots, \boldsymbol{x}_k^{\text{train}}\)のサンプルの平均を使って予測するシンプルな機械学習アルゴリズム
例#
以下のデータを例として使う
予測の処理は、ユークリッド距離
を個々のデータ点同士について計算して\(k\)個の近傍点で平均をとることにする。
計算量を考えると、本当はKDTreeなどの高速な最近傍探索アルゴリズムを使ったほうがよい。
k = 10
X_train = X
y_train = y
def predict(x_test: np.array) -> int:
# testのデータ点と訓練データの点の距離
distances = np.linalg.norm(X_train - x_test, axis=1)
neighbors_idx = np.argsort(distances)[:k]
neighbors = y_train[neighbors_idx]
proba = np.mean(neighbors)
y_pred = 1 * (proba >= 0.5)
return y_pred
識別境界を簡単に確認してみる。格子状に点をとって判別結果を描く方法をとってみる。
k=0の最近傍法#
仮想的に\(k=0\)と置いた0近傍法が理論上の最適レートを達成するらしい。
モンテカルロ・シミュレーションでバイアスとバリアンスを測ると、\(k\)を大きくするほどバリアンスは小さくなるがバイアスは大きくなるトレードオフがある。\(k\)がゼロに近くなるとバリアンスは非常に大きくなるがバイアスは小さくなる。
仮想的な0近傍推定量
ユーザーが指定する\(1 \leq k_1 < k_2 < \cdots < k_V \leq n\)を用いて
各 \(k_v\) について \(k\) 近傍推定量 \(\hat{\eta}_{k_v}^{(k N N)}\) を計算
各 \(k_v\) について距離 \(r_{k_v}:=\left\|x_{\left(k_v\right)}-x_*\right\|_2\) を計算
回帰関数 \(f_\theta\left(r_{k_v}\right)\) により, \(r_{k_v}\) を介して \(k_v\) 近傍推定量を予測する:
\(r_0=0\) に外挿した \(f_{\hat{\theta}}(0)\) を特に「マルチスケール \(k\) 近傍推定量」と呼び、 これが仮想的な0近傍推定量に相当する。
\(C=\max \{\gamma \in \mathbb{N} \cup\{0\} \mid \gamma < \beta / 2\}\) とした多項式関数
を回帰関数として用いると、仮想的な0近傍推定量は高次のバイアスを補正し、最適レートを達成することが証明できる。 さらにプラグイン型の分類器 \(\mathbb{1}(\hat{\eta}(X_*) \geq 1 / 2)\) を用いると分類問題における最適レートを達成する (Okuno and Shimodaira (2020) Theorem 2)
重み付き近傍法との関係#
仮想的な0近傍推定量は重み付き近傍法
として考えることができる。
試してみる#
モンテカルロ・シミュレーションでkごとの予測値の平均と標準偏差を見る
たしかに、論文中にあったような図になる。kが小さいほうがbiasは小さい傾向がある
各\(k\)についてkNN推定値を計算し、それらをつかって線形回帰して\(k=0\)を外挿してみる。
常にベストになるわけではなが、ほどほどに良い\(k\)を選んだときと同程度にはなるっぽい