コンテンツにスキップ

E.C.2 K 近傍法

KNN の近傍投票図

KNN は、新しいサンプルの近くにあるラベル付きサンプルを見て投票します。学習コストはほとんどありませんが、予測時に距離比較が必要なため、データが大きいと重くなります。

  • Python 3.10+
  • 現在の安定版 scikit-learnnumpy
Terminal window
python -m pip install -U scikit-learn numpy
  • K:投票に参加する近傍点の数。
  • 距離尺度:「近い」をどう計算するか。
  • Lazy learning(遅延学習):学習時の作業が少なく、予測時の作業が多い方式。
  • Scaling(スケーリング):特徴量の範囲が違うときに必要。

knn_vote.py を作成します。

import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X = np.array([
[1, 1],
[2, 2],
[2, 1],
[8, 8],
[9, 9],
[8, 9],
])
y = np.array([0, 0, 0, 1, 1, 1])
model = make_pipeline(
StandardScaler(),
KNeighborsClassifier(n_neighbors=3),
)
model.fit(X, y)
pred = model.predict([[3, 3], [8.5, 8.2]])
print("predictions:", pred.tolist())

実行します。

Terminal window
python knn_vote.py

期待される出力:

Terminal window
predictions: [0, 1]

このモデルは複雑な式を学習していません。サンプルを保持し、特徴量をスケーリングし、距離を測り、投票します。

n_neighbors=315 に変更します。K が小さいほど局所的な点に敏感で、K が大きいほど判断はなめらかになります。

KNN を試す場面:

  1. データセットが小さい。
  2. 特徴量の距離に意味がある。
  3. すぐに説明しやすいベースラインがほしい。
  4. 予測レイテンシが厳しくない。

巨大データや高 QPS のリアルタイムサービスでは、デフォルトにしないほうが安全です。

KNN をレビューするときは、最終ラベルだけを見ないでください。少なくとも 1 つの予測について、近傍点、近傍ラベル、距離値を残します。これで、意味のある類似性から結果が出たのか、スケールの大きい特徴量に引っ張られたのかが分かります。

KNN は説明しやすい baseline です。同時に誤用もしやすいです。scaling の有無で予測が大きく変わる場合や、dataset が大きくなって latency が悪化する場合は、その制約を baseline の結論に書きます。

このページを終えたら、この証拠カードを残します。

モデルファミリー
SVM、KNN、Naive Bayes、LDA、または別の古典的ベースライン
データセット表示
特徴量スケール、クラスの偏り、決定境界、train/test 分割
指標
accuracy/F1、confusion matrix、margin、近傍の挙動、または投影の品質
失敗確認
スケーリング、高次元性、弱い仮定、リーク、またはベースライン適合性の低さ
期待される成果
1つの制約メモ付きの古典的 ML ベースライン結果
  • 特徴量のスケーリングを忘れる。
  • KNN が「学習済み」だから軽いと思い、予測時のコストを見落とす。
  • 特徴量が本当に類似性を表しているか確認せず、K だけを調整する。

値が 10000 前後の3つ目の特徴量を追加します。StandardScaler() を外し、距離投票がどう歪むか観察してください。

参考実装と解説

スケーリングしない場合、10000 前後の大きな特徴量がユークリッド距離を支配します。その結果、元の2特徴量のほうがクラスパターンを表していても、KNN は大きな尺度の特徴量だけで投票してしまうことがあります。

よい解答では、StandardScaler() ありとなしの予測を比較し、どの特徴量が距離を支配したかを説明します。KNN は距離に強く依存し、悪い距離の形を自動で補正する重みを学習しない、という点が重要です。