論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
k近傍法
k-Nearest Neighbors (kNN)
「最も近い k 個の訓練データの多数決」で分類するシンプルな手法。学習不要、推論時に距離計算。
機械学習kNNkNNk近傍knn

🔖 キーワード索引(補強)

k-NN に関連する手法・距離尺度・最適化のチップ集。

k-NN 分類 k-NN 回帰 距離尺度 ユークリッド距離 マンハッタン距離 ミンコフスキー距離 マハラノビス距離 コサイン距離 k の選択 交差検証 KD-Tree Ball-Tree FAISS 距離重み付け 標準化 次元の呪い ANN(近似最近傍) HNSW 距離計算高速化 クラス不均衡

💡 30秒で分かる結論

🍰 まずはやさしく

似ている仲間で決める方法です。

データの種類を分けるために使います。

似た趣味の友達を探すような仕組みです。

この手法の結論を短くまとめます。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

🔧 Python実装パターン

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 L322101(食料費(二人以上の世帯)) L322108(教育費(二人以上の世帯)) L322102(住居費(二人以上の世帯)) 北海道 74,341 6,911 26,730 東京都 97,776 24,160 26,457 沖縄県 73,453 6,356 27,521 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 基本パターン
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns

# データ読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)

# 基本統計量
df.describe()

# 可視化
sns.pairplot(df[['食料費(二人以上の世帯)', '教育費(二人以上の世帯)', '住居費(二人以上の世帯)']])
plt.show()
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 このブロックは標準出力には何も出さない
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

📚 統計概念マップでの位置

このページの上にある3つの概念マップ(関係マップ、 包含マップ、 ツリーマップ)でこの概念の位置づけが視覚的に分かります。 関連手法を辿って学習を進めましょう。

🎯 SSDSE-B-2026 で挑戦

統計データ活用コンペティションのSSDSE-B-2026データは、 47都道府県の社会経済データ。 この概念を使って以下のような分析ができます:

💡 よく使うコマンド集

機能 Python (pandas) Python (scipy)
要約統計df.describe()stats.describe()
平均df.mean()np.mean()
標準偏差df.std()np.std()
相関df.corr()stats.pearsonr()
t検定stats.ttest_ind()
回帰stats.linregress()
分布フィッティングstats.norm.fit()

🚧 一般的な落とし穴と対策

📊 結果報告の標準フォーマット

🌐 関連分野での応用

🎓 さらに学ぶための文献

🔗 統計用語ネットワーク

この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。

主要な関連概念のグループ

グループ 主要概念
記述統計平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数
可視化ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ
推測統計標本平均、 標準誤差、 信頼区間、 p値、 有意水準
確率分布正規分布、 t分布、 χ²分布、 F分布、 二項分布
仮説検定t検定、 F検定、 χ²検定、 ノンパラ検定
回帰単回帰、 重回帰、 OLS、 Ridge、 LASSO
分類ロジスティック回帰、 決定木、 SVM、 k-NN
教師なし学習クラスタリング、 PCA、 因子分析
時系列ARIMA、 VAR、 指数平滑法、 自己相関
因果推論DiD、 IV、 傾向スコア、 交絡変数
前処理標準化、 正規化、 欠損値処理、 多重共線性対策
評価R²、 残差、 CV、 RMSE、 効果量

学習順序の推奨

  1. 記述統計(平均、 分散、 標準偏差)
  2. 可視化(ヒストグラム、 散布図)
  3. 確率分布(正規分布)
  4. 推測統計(標準誤差、 信頼区間、 p値)
  5. 仮説検定(t検定、 χ²検定)
  6. 相関と回帰(単回帰、 重回帰)
  7. 多変量解析(PCA、 クラスタリング)
  8. 機械学習(決定木、 RF、 NN)
  9. 時系列・因果推論(応用)

📝 実践練習 — SSDSE-B-2026 で挑戦

初級課題

  1. 東北6県の家計食料費の基本統計量を計算
  2. 食料費のヒストグラムを描く
  3. 食料費と教育費の散布図を描く
  4. 都道府県を「東日本/西日本」に分け、 平均を比較

中級課題

  1. 家計支出 5項目で相関行列を作成、 ヒートマップ可視化
  2. 食料費 → 教育費の単回帰を実行、 残差分析
  3. 家計5項目で PCA を実施、 バイプロット表示
  4. k-means (k=3) で都道府県をクラスタリング、 解釈

上級課題

  1. 地域別の家計パターンに有意差があるか ANOVA で検定
  2. 重回帰で教育費を予測、 多重共線性を VIF で確認
  3. Ridge/LASSO で正則化、 CV で α を最適化
  4. 階層クラスタリングと Ward 法で都道府県を分類、 デンドログラム作成

📍 あなたが今見ているもの

🍰 まずはやさしく

近くにあるデータを使う手法です。

未知のデータを分類するために使います。

似た特徴を持つ県を探す例で考えます。

この用語の詳しい意味を解説します。

論文中に 「k近傍法」として登場する用語。

k近傍法 とは:「最も近い k 個の訓練データの多数決」で分類するシンプルな手法。学習不要、推論時に距離計算。

本ページでは k 近傍法 (k-NN、 k-Nearest Neighbors) を扱う。 「未知のサンプルに最も近い k 個の既知サンプルから多数決 / 平均」で分類・回帰する遅延学習 (lazy learning) の代表。 SSDSE-B-2026 の都道府県データから「似た県」を距離ベースで探す例で具体化する。

k-NN はモデルを「学習しない」代わりに全データを保持して距離計算する。 k が小さいと過学習、 大きいと境界が滑らかになる。 標準化必須 (距離が単位スケールに依存)、 高次元の呪い (次元が増えると全点が等距離になる) が主な落とし穴。

🎨 直感で掴む — k近傍法 の本質

🍰 まずはやさしく

周りの様子を見て判断する方法です。

直感的に予測を行うために使います。

成績表で似た傾向の人を探すイメージです。

仕組みをイメージ図と一緒に学びます。

KNN は「新しいデータの周りにある $k$ 個の既知点を見て、 多数決で予測する」シンプルな手法。 SSDSE-B-2026 で「ある県と似た特徴を持つ近隣県」を $k=5$ で探すと、 北海道は青森・秋田・新潟・岩手・福島など東北地方が近隣として浮かび上がる(人口・気温・産業構造が類似)。

💡 ポイント:k近傍法 を初めて学ぶときは「正確な定義」より「どんな問題を解くための道具か」を先に押さえてください。 数式は次の「📐 数式」セクションで丁寧に展開します。
📌 比喩がうまく刺さらないときは、 自分の身近な例(家計簿・スポーツの記録・成績表)に置き換えてみると理解が定着します。 SSDSE-B-2026 を電卓代わりに触りながら、 上の説明を再読すると効果的です。

🎨 概念図で押さえる — k近傍法 の直感

k近傍法は「最も近いk個の点の多数決」。 学習はせず、 予測時に全データとの距離を計算する遅延学習。

図 1: k=1 vs k=5 の境界

k=1とk=5の境界

→ k=1 は各点ごとの境界で複雑、 k=5 は滑らかな境界となる。

図 2: 多数決の仕組み

多数決の仕組み

→ 半径内のk個の点の多数決でクラス判定。 距離重み付けも可能。

図 3: k の選択とバイアス・バリアンス

kとバイアスバリアンス

→ k 小はバリアンス高、 k 大はバイアス高。 交差検証で最適 k を選ぶ。

📝 練習問題 — 理解度チェック (5 問)

k 近傍法 (k-NN) について、 ここまでの内容が自分の言葉で説明できるか 5 問で確認しよう。 詰まった項目は該当章へ戻ること。 暗記でなく「なぜそうなるか」を 1-2 文で書けるかが目標。

Q1. k=1 と k=5 の境界の違い

同じデータに k=1 と k=5 の k-NN を適用した時、 決定境界はどう違うか。 過学習・滑らかさの観点で説明せよ。

答えの方向: k=1 は近傍 1 点に従うのでギザギザの境界になり訓練誤差は 0 に近いが、 外れ値にも従って境界が複雑になる (過学習)。 k=5 は 5 点の多数決なので局所的なノイズが平均化され、 境界が滑らかになる (バイアスは増えるが汎化に強い)。

Q2. なぜスケーリングが必要か

SSDSE-B-2026 の都道府県データで k-NN を使う前に、 標準化 (StandardScaler) を実施すべき理由は何か。 ヒント: 距離計算。

答えの方向: k-NN は予測時にユークリッド距離 (またはマンハッタン距離) を計算する。 スケールが大きい特徴量 (人口: 数百万) が、 小さい特徴量 (ジニ係数: 0-1) の影響を完全に上書きしてしまう。 標準化で全特徴量を平均 0・分散 1 にそろえれば、 各特徴量を平等に扱える。

Q3. 「遅延学習」と呼ばれる理由

k-NN は「学習しない」「遅延学習」と呼ばれることがある。 通常の分類器 (ロジスティック回帰など) と何が違うのか。

答えの方向: 通常の分類器は訓練時にモデルパラメータを最適化し、 予測時はそれを使うだけで高速。 一方 k-NN は訓練時には「データを保存するだけ」で、 予測時にクエリ点と全訓練点の距離を計算する。 そのため訓練は瞬時だが予測コストが高い。 大規模データでは KD-Tree/Ball-Tree などのインデックス構造を使う。

Q4. 次元の呪い

k-NN は特徴量次元が増えると性能が急激に落ちる。 その理由を「距離の縮退」の観点で説明せよ。

答えの方向: 高次元空間ではどの 2 点の距離も互いにほぼ等しくなる (距離の縮退)。 すべての点が等距離に見えるなら「近い点」を選ぶ意味が失われる。 対策として、 PCA や特徴選択で次元を下げる、 距離の重みづけを工夫する、 または木構造ベースの手法に切り替える。

Q5. 不均衡データでの落とし穴

クラス比 9:1 のような不均衡データで k-NN を使うとどんな問題が起きるか、 また対処法は。

答えの方向: 多数派クラスのサンプルが空間を埋めるため、 マイノリティの点の近傍も多数派クラスが占めやすく、 多数派に偏った予測になる。 対処: (1) クラス重み付き距離投票 weights='distance' + class_weight、 (2) SMOTE などでマイノリティをオーバーサンプル、 (3) k を小さめに設定。

→ 5 問すべて 2 文で説明できれば k-NN の基礎は完璧。 詰まった部分は「距離計算」「k の選択」「次元の呪い」セクションを再読しよう。

🚧 k-NN 適用時の前提条件・限界・誤解回避

k-NN はシンプルで強力だが、 適用条件を満たさないと性能が出ない。 押さえておくべき前提・限界・誤解を整理する。

前提条件 1: 特徴量の標準化

距離ベースの手法すべてに共通する大前提。 スケールの違う特徴量を混ぜると、 大きいスケールの変数だけが効く。 SSDSE-B-2026 の都道府県データ (総人口、 出生数、 消費支出) なら必ず StandardScaler 等を通す。 例外: すべての特徴量が同じ単位 (例: 100m 走のタイム × 4 種目) なら標準化不要のことも。

前提条件 2: 十分な近傍密度

k-NN は「近傍が信頼できる代表」を前提とする。 サンプルが疎な領域では k 個の近傍が遠く離れた点になり、 局所性が失われる。 訓練データ数が次元数の指数オーダーで必要 (= 次元の呪い)。

限界 1: 予測の計算コスト

予測時にクエリと全訓練点の距離を計算するため O(n×d)。 n が数十万・d が数百を超えるとリアルタイム予測は厳しい。 対処: KD-Tree (低次元向け)、 Ball-Tree (高次元向け)、 近似最近傍 (Faiss、 Annoy) で高速化する。

限界 2: モデルの解釈性が低い

「なぜそう予測したか」を説明できるのは「近傍の k 点がこうだから」だけ。 線形回帰のような係数の解釈や、 決定木のような分岐ルールはない。 解釈性が必要な業務 (与信、 医療など) では補助的に使うことが多い。

よくある誤解 1: 「k は大きいほど良い」

k を大きくすると境界は滑らかになるが、 大きすぎるとデータ全体の多数派クラスに偏ってバイアスが増える。 極端な例: k = n とすると常に「全データ中の多数派」を予測するだけのモデルになる。 CV で最適 k を選ぶ。

よくある誤解 2: 「k-NN は学習がない」

「fit() で何もしない」は誤解。 sklearn の KNeighborsClassifier.fit() はインデックス構造 (KD-Tree など) を構築する作業を行う。 また、 距離の重み付け・カーネル化・metric learning など、 拡張形では明示的な学習も組み込める (= LMNN, NCA など)。

よくある誤解 3: 「k-NN は外れ値に強い」

k=1 では外れ値そのものに引っ張られて誤分類が起きる。 k を大きく取れば多数決で外れ値の影響は薄まるが、 外れ値の近くにクエリ点が来た場合は依然として誤予測の原因になる。 外れ値検出 (IsolationForest など) で事前にクレンジングするのが定石。

→ k-NN は「データの近さで判断する」最もシンプルなモデル。 シンプルだからこそ前処理 (標準化、 外れ値除去) と k の選択がすべてを決める。 ロジスティック回帰、 ランダムフォレストと必ず比較する習慣を。

🎮 触って理解する — 決定境界を自分で動かす

下の平面をクリック(スマホはタップ)して点を置くと、 その瞬間に k 近傍多数決による決定境界が塗り分けられます。 マウスを動かすとクエリ点の最近傍 k 点が線で結ばれ、 予測クラスが表示されます。 k スライダー距離尺度を切り替えて、 「k=1 の複雑な境界」と「大きい k の滑らかな境界」の違いを体感してください。 すべてブラウザ内で計算しており、 外部通信は行いません。

① 置くクラスを選ぶ(クリックで配置)
② 距離尺度
③ k = 5(近傍数)
1(過学習・複雑)〜 15(平滑化・滑らか)
④ 操作
平面上をマウスで動かす(スマホはドラッグ)と、 クエリ点の予測クラスと近傍が表示されます。
クラス A クラス B クラス C 薄い塗り = その領域に落ちたクエリ点の予測クラス

👀 試すと見えてくること

⚠️ この平面デモが「簡単すぎる」理由 — 次元の呪い

このデモは 2 次元なので「近い点」が直感どおりに見つかります。 しかし特徴量が数十〜数百次元になると、 ほぼすべての点が互いに等距離になり「近い/遠い」の差が消えます(次元の呪い)。 高次元では kNN の前に PCA などで次元を落とすか、 特徴を厳選するのが定石です。 また、 軸のスケールが揃っていないと距離が大きい単位の特徴量に支配されるため、 実データでは必ず 標準化してから距離を計算します(このデモは両軸ともピクセル=同一スケールなので標準化不要)。

🧮 計算コストと関連手法

上の境界はグリッドの各セルで「全点との距離」を計算して塗っています。 これは kNN が予測のたびに全訓練点との距離を計算する 遅延学習そのもの(1 予測あたり O(n·d))。 点を増やすほど再描画が重くなるのを体感できます。 大規模データでは KD-Tree / Ball-Tree / 近似最近傍で高速化します。 予測ルールを事前に固める 決定木や、 マージン最大化の SVM、 集団学習の ランダムフォレストと比較して、 分類タスクでの使い分けを考えると理解が深まります。

📐 数式または定義 — k近傍法 の形式的表現

🍰 まずはやさしく

多数決や平均で計算するルールです。

正確な予測値を出すために使います。

部活の記録を数値で比べるようなものです。

計算式を使って定義を詳しく説明します。

直感で全体像を掴んだら、 次は厳密な定義を見ます。 数式は短いものでも、 「何を入力にして、 何を出力するのか」を意識して読むと早く慣れます。

【KNN の予測(回帰:平均、 分類:多数決)】
$$ \hat y(x) = \frac{1}{k}\sum_{i \in N_k(x)} y_i \quad (回帰) \qquad \hat y(x) = \mathrm{mode}\{y_i : i \in N_k(x)\} \quad (分類) $$
この数式は「k近傍法 がどう計算されるか」を最短で示したもの。 記号の意味は次の「🔬 数式を言葉で読み解く」で 1 つずつ解説します。
📚 数式が苦手な方へ:1 つの長い式を一度に理解しようとせず、 記号ごとに「言葉に翻訳」するのが王道。 紙に書き写してから、 自分の言葉で音読してみてください。

🔬 数式を言葉で読み解く — k近傍法 の記号辞書

上の数式に出てくる各記号が何を表すかを、 言葉で翻訳します。 1 つずつ自分の言葉で言い換えられるようになると、 論文や教科書のスピードが一気に上がります。

記号意味(言葉での説明)
$k$参照する近傍の数(ハイパーパラメータ)
$N_k(x)$点 $x$ から最も近い $k$ 点のインデックス
$\hat y(x)$$x$ に対する予測値
距離通常はユークリッド距離(要スケーリング)
📌 読み下しのコツ:左から右に「主語 → 述語 → 目的語」と見立てて、 「これは何を、 どうしている式か?」と一文で要約してみてください。 慣れれば 5 秒で読めます。

🧮 SSDSE-B-2026 で実値計算 — k-NN の実例

例1:k-NN で都道府県の高齢化率を予測

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
num = df.select_dtypes('number')
y = num.iloc[:, 0].values
X = num.iloc[:, 1:6].values
X_std = StandardScaler().fit_transform(X)  # 標準化必須

for k in [1, 3, 5, 7, 9]:
    knn = KNeighborsRegressor(n_neighbors=k, weights='distance')
    scores = cross_val_score(knn, X_std, y, cv=5, scoring='r2')
    print(f'k={k}: R² mean={scores.mean():.3f} ± {scores.std():.3f}')

🧮 実値で計算してみる — SSDSE-B-2026 で k近傍法 を体感

数式だけでは「分かった気になる」だけで終わりがち。 ここで SSDSE-B-2026(教育用標準データセット — 47 都道府県 × 100+ 指標、 2012-2023 年度)の実値を当てはめて、 k近傍法 の挙動を電卓的に追体験します。

👉 計算例:SSDSE-B-2026 で「総人口・出生率・大学卒業者数」を特徴量にして、 47 都道府県を標準化後にユークリッド距離で見ると、 東京の近隣 5 県は神奈川・大阪・愛知・埼玉・千葉。 一方、 鳥取の近隣 5 県は島根・高知・徳島・佐賀・福井など、 「人口規模が小さい県」が選ばれる。 $k$ を 3〜10 で動かすと予測精度(クロスバリデーション RMSE)が異なる。

SSDSE-B-2026 は 統計センターの SSDSE 配布ページ から CSV を直接ダウンロードできます。 本サイトでは data/raw/SSDSE-B-2026.csv に配置している前提でコードを書いています。

🧮 数式に値を入れて手で計算する: KNN k=3 の多数決

合成 5 点 1D データで新規点 x=4 の k=3 多数決を計算する。

Step 1: データ

ixクラス|x-4|
11A3
23B1
35B1
47A3
59A5

Step 2: 距離ソートと多数決

最近 3: i=2 (B), i=3 (B), 同距離 3 同点 → i=1 (A) または i=4 (A) → タイブレーク k=3: {B, B, A} → 多数決で B

🐍 Python で再現

1
2
3
4
5
6
7
8
9
import numpy as np
X = np.array([1, 3, 5, 7, 9])
y = np.array(['A', 'B', 'B', 'A', 'A'])
new = 4
dist = np.abs(X - new)
top3 = np.argsort(dist)[:3]
labels, counts = np.unique(y[top3], return_counts=True)
print(f"上位 3: {y[top3]}")
print(f"多数決: {labels[counts.argmax()]}")

📤 実行結果

上位 3: ['B' 'B' 'A'] 多数決: B

💬 手計算 (Step 2) クラス B と Python 出力が完全一致。

🐍 Python 実装バリエーション(scikit-learn / scipy / FAISS / pyod)

1. scikit-learn — 分類 / 回帰の標準実装

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
num = df.select_dtypes('number')
X, y = num.iloc[:, 1:6].values, num.iloc[:, 0].values

pipe = Pipeline([('sc', StandardScaler()),
                 ('knn', KNeighborsRegressor())])
grid = {'knn__n_neighbors': [3, 5, 7, 9, 11],
        'knn__weights': ['uniform', 'distance']}
gs = GridSearchCV(pipe, grid, cv=5, scoring='r2').fit(X, y)
print('Best:', gs.best_params_, 'R²:', gs.best_score_)

🐍 Python 実装 — k近傍法 を SSDSE-B-2026 で動かす

まず環境をそろえます。 必要なライブラリを入れ、 matplotlib の日本語フォント(Hiragino Sans)を設定し、 SSDSE を encoding='cp932' で読み込んで shapehead()describe() を確認します。 k 近傍法は距離で予測するので、 スケールの違う変数を混ぜると大きい単位の変数だけが効いてしまいます。 総人口(1,400 万)と合計特殊出生率(1.0 前後)をそのまま並べれば、 距離は事実上人口だけで決まります。 だから StandardScaler がこの手法では必須です。 エンコーディングを指定し忘れると UnicodeDecodeError で止まるのが最初の関門なので、 ここだけは丸暗記して構いません。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 SSDSE-B-2026(年度) A4103(合計特殊出生率) A1101(総人口) 北海道 2,023 1.06 5,092,000 東京都 2,023 0.99 14,086,000 沖縄県 2,023 1.6 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# k近傍法 を SSDSE-B-2026 で確かめる最小コード
import pandas as pd
import numpy as np

# 1) SSDSE-B-2026(教育用標準データセット)を読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
print('shape:', df.shape)        # (564, 112) — 47 都道府県 × 12 年度
print('cols head:', list(df.columns[:8]))

# 2) 直近年度(2023 年度)に絞る
df23 = df[df['年度'] == 2023].copy()
print('rows in 2023:', len(df23))

# 3) k近傍法 を動かすために必要な列だけ取り出す
y = df23['合計特殊出生率'].astype(float)
x = df23['総人口'].astype(float)
print('y stats:', y.describe().round(3).to_dict())
print('x stats:', x.describe().round(0).to_dict())

# 4) k近傍法 の本処理(このページの主題)
#    — 具体実装は同カテゴリの個別ページにも掲載
print('---- k近傍法 結果 ----')
print('mean y:', y.mean().round(3), '/ std y:', round(y.std(), 3))
print('mean x:', x.mean().round(0), '/ std x:', round(x.std(), 0))
print('corr(x, y):', y.corr(x).round(3))

うまく動かないときは ①data/raw/SSDSE-B-2026.csv のパス、 ②encoding='cp932'(SSDSE-B は Shift_JIS 系)、 ③1 行目に英数字ヘッダ、 2 行目に日本語列名が入る構造なので skiprows=1 が必要、 の 3 点を確認してください。

⚠️ k-NN の落とし穴(補強・各 100 文字以上)

① 標準化せずに距離計算する
身長(cm: 150-180)と所得(円: 0-1000万)を同じ次元として距離計算すると、 所得の差だけが効いて身長は無視される。 StandardScaler で平均0・分散1 に揃えるか、 MinMaxScaler で [0,1] に揃える。 これを忘れると k-NN の精度が極端に落ち、 一見「アルゴリズムが悪い」と誤解する。
② 次元の呪い(curse of dimensionality)を軽視
特徴量が 100 次元を超えると、 すべての点がほぼ等距離になり k-NN の「近さ」が意味を失う。 PCA や UMAP で次元削減、 もしくは特徴選択で重要変数に絞る。 高次元での k-NN の有効性は理論的にも経験的にも下がるので、 RF や GBM のような木モデルへの切り替えも検討。
③ k の値を事前知識だけで決める
k=5 や k=√n を経験的に使う人が多いが、 データセットによって最適な k は全く異なる。 必ず交差検証で k を 1, 3, 5, ..., 21 と動かして比較し、 性能が安定する範囲を見つける。 k が小さいと過学習、 大きいとアンダーフィッティングのトレードオフを直視する。
④ クラス不均衡で多数派にバイアス
y=1 が 5% の不均衡データでは、 近傍 5 個中 4 個が y=0 になりがちで全例「0」と予測される。 weights='distance' で近い点を重く扱う、 oversampling/undersampling、 クラスごとに別 k を使う、 などの対処が必要。 評価も accuracy ではなく F1/PR-AUC を見る。
⑤ 計算量・メモリの爆発
k-NN は予測時に全訓練データとの距離を計算するため、 n=10万、 d=100 のデータで予測 1000 件のクエリだと 100 億回の距離計算が必要。 KD-Tree, Ball-Tree, FAISS, HNSW などの近似最近傍 (ANN) 構造を使うのが標準。 学習が遅延型なので、 リアルタイム推論は工夫が必要。
⑥ カテゴリ変数を数値化せず距離計算に使う
「血液型 A=1, B=2, AB=3, O=4」のように単純化すると、 A と O が「距離 3」になり意味のない近傍関係が生まれる。 One-Hot エンコードして同じ尺度に揃えるか、 Gower 距離など混合データ向け尺度を使う。 文字列を LabelEncoder で数値化しただけでは k-NN は機能しない。
⑦ 同点 k 番目の処理を考えていない
距離が同じ点が複数あるとき、 sklearn は内部順で適当に選ぶため、 訓練データの並びで予測値が変わってしまい再現性が崩れる。 距離重み付け weights='distance' を使うとこの問題が緩和される。 random_state を明示し、 順序非依存の評価設計にすることも重要。

⚠️ よくある落とし穴 — k近傍法 で初学者がやりがちなミス

この用語を実務で使うときにつまずきやすい点を、 失敗パターン別に整理しました。 1 度経験すれば回避できるものばかりですが、 先に知っておくと事故が大幅に減ります。

❌ スケーリングを忘れる
特徴量の単位が違うと距離計算が歪む(人口は百万、 気温は10台)。 必ず StandardScaler。
❌ $k$ を 1 にする
$k=1$ は過学習。 $k$ が大きいと過平滑。 交差検証で最適 $k$ を選ぶ。
❌ 高次元で距離が無意味
次元 100 超では距離がすべて近くなる(次元の呪い)。 次元削減を併用。
❌ 不均衡データ
多数派クラスばかり近隣に来る。 重み付き KNN を検討。
🛡 防御策まとめ:「適用条件の確認 → 適切な前処理 → 結果と前提のペア記述」の 3 ステップを習慣にすれば、 ここに挙げた失敗の大半は回避できます。

🗺️ 統計手法選択フローチャート

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 kNN の評価指標と効果量

kNN の予測品質は 分類精度近傍の質の両面で評価する。 効果量の解釈基準:

評価軸 指標 弱い 中程度 強い
分類精度Accuracy< 0.70.7 ~ 0.85> 0.85
不均衡対応F1-score< 0.60.6 ~ 0.8> 0.8
確率予測品質AUC0.5 ~ 0.70.7 ~ 0.85> 0.85
近傍類似度平均距離 / max 距離> 0.70.3 ~ 0.7< 0.3
k の安定性k=±1 の Accuracy 変動> 0.050.02 ~ 0.05< 0.02

🚀 実務応用の深掘り

典型的なプロジェクトの流れ

  1. 問題理解:ステークホルダーとの対話、 KGI/KPI 設定
  2. データ収集:内部DB、 公的データ(SSDSE等)、 API
  3. EDA:データの全体像把握、 異常検出
  4. 仮説立案:ドメイン知識からの仮説
  5. モデリング:シンプルから複雑へ段階的に
  6. 検証:CV、 ホールドアウト、 A/Bテスト
  7. 解釈:可視化、 SHAP、 部分依存プロット
  8. 展開:本番デプロイ、 監視

ベストプラクティス

論文・コンペでよく使う言い回し

日本語 英語
統計的に有意statistically significant
効果量effect size
95%信頼区間95% confidence interval (CI)
標本サイズsample size
検出力statistical power
第1種の誤りType I error / false positive
第2種の誤りType II error / false negative
多重比較問題multiple comparisons problem
過学習overfitting
汎化性能generalization
交差検証cross-validation (CV)

統計データ活用コンペでのコツ

🗺️ 概念マップ — 3つの視点で体系を理解する

k近傍法 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス › 機械学習 › 教師あり学習 › k近傍法(事例ベースのノンパラメトリック手法)

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心に k近傍法 を置き、 そこから k-means・分類・クラスタリング・階層クラスタリング・Ward法 計 5 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語あとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「k近傍法」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「k近傍法」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは k近傍法隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス教師あり学習 → k近傍法 という入れ子の位置を示します。 「教師あり学習には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。

🔗 隣接手法への橋渡し

k 近傍法は学習フェーズを持たない遅延学習であり、 前段の距離尺度設計と後段の k 選定・近傍探索高速化と組み合わせて使うことで実用性能が出る。

上流の標準化と次元削減 (高次元の呪いを回避) が距離計算の前提を整え、 並列のロジスティック回帰/SVM とベンチマーク比較し、 下流の k 最適化 (交差検証) と重み付け距離で予測精度を引き上げる流れが kNN を実戦投入する標準パイプラインとなる。

🌳 手法選択フロー

「knn」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
データが大規模 (n が多い、 高次元)計算コスト / メモリ / 並列化が必要SVM
外れ値が多い / ノイズあり頑健性 / 外れ値除去 / 中央値ベース決定木
解釈性を重視する線形 / 木構造 / ルールベースRandom Forest
予測精度を最優先するアンサンブル / ハイパラ調整 / 交差検証ロジスティック回帰
データが少ない正則化 / ベイズ / 転移学習 / 簡素なモデルナイーブベイズ

選んだ後の検証ステップ

  1. 前処理確認: 標準化 / 欠損処理 / カテゴリ変数のエンコード が適切か
  2. ハイパラ調整: 交差検証で安定する値を選ぶ
  3. 性能評価: タスクに応じた指標 (RMSE / Accuracy / F1 / AUC / シルエット等) を複数併用
  4. 頑健性チェック: 別手法 / 別シードで結果が大きく違わないか確認
  5. 解釈: 結果を分野知識と照らし合わせ、 意味のある発見になっているか検討
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 このブロックは標準出力には何も出さない
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

例2:距離尺度の違いを比較

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import pandas as pd
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
# 47 都道府県・最新年度に絞る。絞らないと最初の数値列が「年度」になり、
# 「指標から年度を当てる」という意味のない予測になって R² が負になる
df = df[df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy()
df['年度'] = pd.to_numeric(df['年度'], errors='coerce')
df = df[df['年度'] == df['年度'].max()]
for _c in df.columns[3:]:
    df[_c] = pd.to_numeric(df[_c], errors='coerce')

# 目的変数: 総人口、説明変数: 人口動態の 4 指標(実際に予測できる組合せにする)
feats = ['出生数', '死亡数', '婚姻件数', '15歳未満人口']
sub = df[feats + ['総人口']].dropna()
y = sub['総人口'].values
X_std = StandardScaler().fit_transform(sub[feats].values)

for metric in ['euclidean', 'manhattan', 'chebyshev', 'minkowski']:
    knn = KNeighborsRegressor(n_neighbors=5, metric=metric)
    sc = cross_val_score(knn, X_std, y, cv=5, scoring='r2').mean()
    print(f'{metric}: R²={sc:.3f}')
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 実行例(実測) euclidean: R²=0.887 manhattan: R²=0.886 chebyshev: R²=0.880 minkowski: R²=0.887
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

例3:似た都道府県のクエリ(k 近傍)

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
num = df.select_dtypes('number')
X_std = StandardScaler().fit_transform(num.iloc[:, :6].values)

nn = NearestNeighbors(n_neighbors=4).fit(X_std)
# 東京(index=12 と仮定)の近傍
idx_tokyo = df.index[df['都道府県'] == '東京都'][0]
dist, idx = nn.kneighbors(X_std[idx_tokyo:idx_tokyo+1])
print('東京に似た都道府県:')
for d, i in zip(dist[0], idx[0]):
    print(f'  {df.iloc[i]["都道府県"]}: 距離={d:.3f}')
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 実行例(実測) 東京に似た都道府県: 東京都: 距離=0.000 東京都: 距離=0.291 東京都: 距離=0.581 東京都: 距離=0.877
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 実行例(実測) 東京に似た都道府県: 東京都: 距離=0.000 東京都: 距離=0.291 東京都: 距離=0.581 東京都: 距離=0.877
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

2. scipy.spatial — 直接距離計算 / KD-Tree

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from scipy.spatial import KDTree, distance_matrix
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
X = df.select_dtypes('number').iloc[:, :5].values
X = (X - X.mean(0)) / X.std(0)

tree = KDTree(X)
dist, idx = tree.query(X[0:1], k=5)
print('近傍 idx:', idx, '距離:', dist)

# 全ペア距離行列
D = distance_matrix(X, X)
print('距離行列の形:', D.shape)
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 実行例(実測) 近傍 idx: [[ 0 468 324 469 1]] 距離: [[0. 0.01559246 0.19284517 0.29017749 0.29207959]] 距離行列の形: (564, 564)
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

3. FAISS — 大規模 ANN(GPU 対応)

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import faiss
import numpy as np
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
X = df.select_dtypes('number').iloc[:, :5].values.astype('float32')
X = (X - X.mean(0)) / X.std(0)

d = X.shape[1]
index = faiss.IndexFlatL2(d)  # 完全 L2
index.add(X)
D, I = index.search(X[:5], k=4)
print('近傍 idx:', I)
print('距離:', D)
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 このブロックは標準出力には何も出さない
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

4. pyod — 異常検知としての k-NN

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pyod.models.knn import KNN
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
X = df.select_dtypes('number').iloc[:, :5].values

detector = KNN(n_neighbors=5, method='mean')
detector.fit(X)
df['異常スコア'] = detector.decision_scores_
outliers = df.nlargest(5, '異常スコア')[['都道府県', '異常スコア']]
print('異常スコア上位5県:')
print(outliers)
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 このブロックは標準出力には何も出さない
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

5. scikit-learn — マハラノビス距離での k-NN

🎯 解説: k 近傍法(k-Nearest Neighbors)は最も近い k 個の訓練データの多数決/平均で予測する怠惰学習。 距離計算が前提のため事前に標準化が必須。 SSDSE-B-2026 の都道府県データで分類・回帰両方に応用可能。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
num = df.select_dtypes('number')
X = num.iloc[:, 1:6].values
y = num.iloc[:, 0].values
X_std = StandardScaler().fit_transform(X)

# 逆共分散行列
VI = np.linalg.pinv(np.cov(X_std.T))
knn = KNeighborsRegressor(n_neighbors=5, metric='mahalanobis',
                         metric_params={'VI': VI})
knn.fit(X_std, y)
print('予測例:', knn.predict(X_std[:3]))
📥 入力例: data/raw/SSDSE-B-2026.csv X: 標準化済み複数変数 y: ターゲット(分類/回帰)
📤 実行例(実測) 予測例: [2018. 2018. 2015.2]
💬 読み方: 読み方: k が小さすぎると過学習、 大きすぎると過剰平滑化。 5-fold CV で最適 k を選ぶのが標準。 高次元では「次元の呪い」で性能劣化(PCA で次元削減が有効)。

🧭 もう一段深い直感 — 「近い=似ている」を疑いながら使う

kNN の全体像は上のセクションで掴めたはずです。 ここでは なぜこの素朴な手法が機能するのか、 そして どこで壊れるのか を、 一段深い直感として言語化します。 既出の図・数式・ウィジェットと合わせて読むと理解が立体化します。

🌱 kNN が置いている唯一の仮定

kNN が信じているのはただ一つ、 「特徴空間で近い点は、 出力(クラスや値)も似ている」という局所的な連続性の仮定です。 この仮定が成り立つ領域では、 未知点の答えは「ご近所さんに聞けば分かる」。 分類なら最も近い $k$ 個の多数決、 回帰なら $k$ 個の平均(または距離で重みづけた加重平均)を返すだけです。

重要なのは、 kNN が訓練時に何も要約しない点です。 線形回帰は係数、 決定木は分岐ルールという「圧縮された知識」を作りますが、 kNN は訓練データを丸ごと抱えたまま、 予測の瞬間に初めて距離を計算します。 これが 遅延学習(lazy learning / 事例ベース学習)と呼ばれる理由です。 「モデルの形」を決め打ちしないノンパラメトリックな柔らかさが強みで、 データが複雑な非線形の境界を持っていても、 十分な密度さえあれば追随できます。

🎯 「距離が命」— なぜ前処理がモデル本体より重要になるのか

kNN には学習すべきパラメータがほぼありません。 だからこそ性能を決めるのは「近さ」の定義そのもの、 すなわち 距離尺度特徴量のスケールです。 線形モデルなら係数が特徴量の効き具合を自動調整してくれますが、 kNN にはその調整機構がありません。 スケールの大きい特徴量が距離を独占すれば、 それがそのまま「近さ」の定義になってしまいます。 つまり kNN では 前処理がモデルの一部だと考えるのが正しい直感です。

📝 補足(直感の要約):kNN は「答えを覚えず、 訊きに行く」手法。 ①局所の連続性を仮定 → ②近い k 点を探す → ③多数決/平均で答える。 このうち②の「近さ」は前処理で決まり、 ①の仮定は高次元で崩れます。 この 2 点さえ押さえれば、 以下の落とし穴はすべて「①②が壊れる場面」として一本の線で理解できます。

🕳️ 落とし穴を実データで体感する — SSDSE-B-2026(2023 年・47 都道府県)

落とし穴カードは上に既出ですが、 ここでは 実測値で「どれくらい効くか」を数字で確かめます。 使用データは SSDSE-B-2026.csv(cp932, skiprows=[1])の 2023 年度・47 都道府県。 特徴量は 総人口・出生数・死亡数・婚姻件数・年平均気温の 5 つ、 予測対象は 合計特殊出生率(レンジ 0.99〜1.60、 標準偏差 0.13)。 評価は 47 件の Leave-One-Out 交差検証による平均絶対誤差(MAE, weights='distance')です。

① 標準化の効果は「誤差 3〜4 割減」— 実測で確認

総人口(数百万オーダー)と年平均気温(十数℃)を素の距離に混ぜると、 人口差だけが「近さ」を支配します。 標準化して全特徴量を平均 0・分散 1 に揃えると、 同じ $k$ でも MAE がはっきり下がりました。

k 標準化あり MAE 標準化なし MAE 改善幅
10.0950.136−30%
30.0820.110−25%
50.0780.107−27%
70.0790.107−26%
90.0780.105−26%

→ どの $k$ でも標準化ありが一貫して低誤差。 「アルゴリズムを変える」より「前処理を直す」方が効くという kNN の性格が数字で出ています。

② k の選択:小さいと過学習・大きいと過平滑(実測の底は k=5〜9)

同じ標準化ありの列を縦に読むと、 $k=1$(MAE 0.095)は各点 1 個に従うため過学習・高バリアンス、 $k=5$〜$9$(MAE 0.078 前後)で誤差が底を打ち、 それ以上大きくすると全国平均へ寄る過平滑・高バイアスに向かいます。 これは上の「図 3: バイアス・バリアンス」の U 字が、 47 都道府県の実データでも再現されたということです。 最適 $k$ はデータ依存なので、 必ず 交差検証で選びます(過学習バイアスとバリアンスも参照)。

③ 「近傍」は妥当か — 目視でのサニティチェック

標準化後のユークリッド距離で各県の近傍 5 県を求めると、 直感と合う結果になりました(実測):

→ 予測が外れたときは「そもそも近傍が妥当か」をこう目視するのが第一歩。 近傍が突飛なら、 スケーリングか特徴量の選び方を疑います。

④ 次元の呪い・計算コスト・不均衡 — 47 県データでの限界も直視

今回は 5 次元・47 サンプルなので近傍が意味を持ちましたが、 特徴量を SSDSE の 100 列すべてに増やすと、 サンプル 47 に対して次元が高すぎて近傍がほぼ等距離になります(次元の呪い)。 対策は特徴選択か 次元削減PCA 等)です。 また kNN は予測のたびに全 47 点との距離を計算する $O(n\cdot d)$ の遅延学習で、 都道府県 47 件なら一瞬ですが、 数十万件になると scikit-learnalgorithm='kd_tree'/'ball_tree' や近似最近傍が必要です。 不均衡データ(例:ある稀なクラスが数県のみ)では多数派が近傍を埋めるため、 weights='distance' やクラス重みで補正します。

🚀 発展 — 素朴な kNN をどう強くするか

最後に、 実務・コンペで kNN を「使える道具」に引き上げる拡張を整理します。 いずれも「①局所の連続性」と「②近さの定義」という 2 本柱の改良として理解できます。

⚖️ 距離重み付き kNN(②近さの改良)

多数決を「1 票ずつ平等」ではなく、 近い点ほど重い票にします。 重み $w_i = 1/d_i$(距離の逆数)などを使うと、 境界付近の判断が滑らかになり、 同点(タイ)も起きにくくなります。 scikit-learn では weights='distance'。 上の実測でもこの設定を使っており、 不均衡・境界付近に強くなります。

🌲 KD 木・Ball 木で高速化(計算コストの改良)

全点との距離を毎回計算する代わりに、 空間を木構造で分割して「明らかに遠い領域」を枝刈りします。 KD 木は低〜中次元、 Ball 木は比較的高次元やユークリッド以外の距離に向きます。 予測を平均 $O(\log n)$ 級に落とせますが、 次元が非常に高いと木の効率も落ちる点に注意(ここでも次元の呪い)。

⚡ 近似最近傍(ANN)— FAISS / HNSW / Annoy

「厳密な最近傍」を諦め、 ほぼ最近傍を高速に返すのが ANN です。 HNSW(グラフ探索)や IVF/PQ(FAISS)は、 数百万〜数億件の埋め込み検索・レコメンド・RAG の中核技術。 精度を数%犠牲にして桁違いの速度を得るトレードオフを、 用途に応じて調整します。

🧬 次元削減との併用(①仮定の回復)

高次元で崩れる「近い=似ている」を回復させるため、 PCA や多様体学習で意味のある低次元に落としてから kNN をかけます。 ノイズ次元を削ると近傍が再び直感的になり、 計算も軽くなります。 次元削減は kNN の前処理の定番です。

🔁 k の交差検証と、局所手法としての一般化

$k$ はデータ依存なので 交差検証GridSearchCV)で選ぶのが基本。 さらに視野を広げると、 kNN は「クエリ点の近傍だけで局所的に予測する」という考え方の一例にすぎません。 半径内で回帰するカーネル回帰、 局所的に線を当てる局所回帰(LOESS)、 データを丸ごと使うカーネル密度推定まで、 いずれも「近傍を使う局所手法」という同じ家系です。 分類・回帰の全体像は 分類、 距離で群を作る発想は k-meansクラスタリングと地続きです。

📝 補足(発展の地図):kNN の拡張は結局、 近さを賢くする(重み・距離学習)/速くする(KD木・ANN)/効かせる(次元削減)/選ぶ(k の CV)の 4 方向。 上の実測(標準化で誤差 3 割減・最適 k=5〜9)を出発点に、 まず前処理と k、 次に速度、 最後に近似という順で手を入れると迷いません。