[機械学習のはじめ方] Part14: k近傍法(KNN)の考え方とハイパーパラメータ

機械学習

機械学習のシンプルで強力なアルゴリズムを理解しよう!

1. k近傍法(KNN)とは?

k近傍法(k-Nearest Neighbors, KNN)は、機械学習の中でも特にシンプルで直感的に理解しやすい教師あり学習アルゴリズムの一つです。

新しいデータ点が与えられたとき、その点がどのグループ(クラス)に属するかを、既存のデータの中で「最も近い」 k 個のデータ点の多数決によって決定します。回帰問題の場合は、k 個の近傍点の値の平均を予測値とします。

家の近くの友達の影響を受けやすいように、データも近くのデータ点に似ているだろう、という考え方に基づいています🏡

KNNは以下のような特徴を持っています。

  • ノンパラメトリック: 特定のデータ分布を仮定しません。
  • 遅延学習 (Lazy Learning): 事前に複雑なモデルを学習せず、予測時に計算を行います。
  • 分類と回帰の両方に利用可能: クラス分類だけでなく、数値予測にも使えます。

2. KNNの基本的な考え方 🤔

KNNのアルゴリズムは非常にシンプルです。

  1. k の値を決める: 周囲のいくつのデータ点(近傍点)を参考にするか (k) を決めます。これはハイパーパラメータと呼ばれます。
  2. 距離を計算する: 新しいデータ点と、既存の全てのデータ点との距離を計算します。距離の計算方法にはいくつか種類があります(後述)。
  3. 近傍点を選ぶ: 計算した距離が小さい順に k 個のデータ点を選びます。これが「k個の最近傍点」です。
  4. 予測する:
    • 分類の場合: k 個の近傍点のクラスラベルで多数決を取り、最も多いクラスを新しいデータ点のクラスとして予測します。
    • 回帰の場合: k 個の近傍点の持つ数値の平均値を、新しいデータ点の予測値とします。

例えば、k=3 に設定した場合、新しい点の周りで一番近い3つの点を見つけます。その3つの点が「赤、赤、青」だったら、多数決で新しい点も「赤」だと予測します ❤️

3. Python (scikit-learn) による実装例 🐍

Python の機械学習ライブラリ `scikit-learn` を使うと、KNN を簡単に実装できます。ここでは分類問題を例に示します。


# 必要なライブラリをインポート
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

# 1. データの準備 (例として Iris データセットを使用)
iris = load_iris()
X, y = iris.data, iris.target

# データを訓練用とテスト用に分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)

# 2. モデルの選択とインスタンス化 (k=3 に設定)
knn = KNeighborsClassifier(n_neighbors=3)

# 3. モデルの学習 (KNNではデータを記憶するだけ)
knn.fit(X_train, y_train)

# 4. 予測
y_pred = knn.predict(X_test)

# 5. 評価 (正解率を計算)
accuracy = accuracy_score(y_test, y_pred)
print(f'テストデータの正解率: {accuracy:.4f}')
# >>> テストデータの正解率: 0.9778 (実行ごとに若干変動する可能性があります)
    

回帰問題の場合は、`KNeighborsClassifier` の代わりに `KNeighborsRegressor` を使います。

4. ハイパーパラメータとその影響 ⚙️

KNN の性能は、いくつかのハイパーパラメータによって左右されます。`scikit-learn` の `KNeighborsClassifier` / `KNeighborsRegressor` でよく使われるものを紹介します。

ハイパーパラメータ説明影響・注意点
n_neighbors近傍点の数 (k) を指定します。整数値。最も重要なパラメータ
– k が小さい: モデルが複雑になり、ノイズに敏感になりやすい(過学習のリスク)。
– k が大きい: モデルが単純になり、決定境界が滑らかになるが、細かいパターンを見逃す可能性(未学習のリスク)。
一般的に奇数を選ぶことが多いです(多数決で同数になるのを避けるため)。適切な k はデータによって異なり、クロスバリデーションなどで見つけるのが一般的です。
weights近傍点の投票/平均への影響度(重み)を指定します。'uniform' (デフォルト): 全ての近傍点が均等な重みを持つ。
'distance': 距離が近い点ほど大きな重みを持つ(距離の逆数などで重み付け)。
'distance' は、近くの点の情報をより重視したい場合に有効です。
metricデータ点間の距離を計算する方法を指定します。文字列または callable。'minkowski' (デフォルト): ミンコフスキー距離。下の p パラメータと組み合わせて使う。
'euclidean': ユークリッド距離(ミンコフスキー距離で p=2 の場合と同じ)。最も一般的。
'manhattan': マンハッタン距離(ミンコフスキー距離で p=1 の場合と同じ)。
– その他 ('chebyshev', 'cosine' など)。
データの特性や次元数によって適切な距離尺度が異なる場合があります。
pミンコフスキー距離のパラメータ (metric='minkowski' の場合のみ有効)。整数値。p=1: マンハッタン距離
p=2 (デフォルト): ユークリッド距離
距離尺度の調整に使います。
algorithm近傍点を探索するアルゴリズムを指定します。'auto' (デフォルト): データに基づいて最適なアルゴリズムを自動選択。
'ball_tree', 'kd_tree': データ構造を使って探索を効率化。中〜高次元データで有効な場合がある。
'brute': 総当たり探索。データ数が少ない場合に有効。もしくは metric='precomputed' の場合。 通常は 'auto' のままで問題ありません。

これらのハイパーパラメータは、モデルの性能に大きく影響するため、グリッドサーチやランダムサーチなどの手法を用いて最適な組み合わせを見つけることが重要です。

5. KNNのメリット・デメリット 👍👎

メリット 👍

  • シンプルで理解しやすい: アルゴリズムが直感的で、結果の解釈も比較的容易です。
  • 実装が容易: scikit-learnなどのライブラリを使えば簡単に実装できます。
  • 特別な学習フェーズが不要(遅延学習): 新しいデータへの適応が容易です。
  • ノンパラメトリック: データの分布に対する仮定が少ないため、複雑な決定境界も表現できます。

デメリット 👎

  • 計算コストが高い: 予測時に全ての学習データとの距離を計算するため、データ数や次元数が増えると計算量が膨大になります。
  • メモリ消費が大きい: 全ての学習データを保持する必要があります。
  • 特徴量のスケールに敏感: 値の範囲が大きい特徴量に距離計算が引きずられやすいため、事前に標準化などのスケーリングが必要です。
  • 適切な k の選択が重要かつ難しい: k の値によって性能が大きく変わります。
  • 次元の呪い: 特徴量の次元数が非常に大きい場合、距離尺度の意味が薄れ、性能が低下しやすいです。
  • 不均衡データに弱い: 多数派クラスのデータが多いと、少数派クラスのデータが近くにあっても多数派に分類されやすくなります。

6. まとめ ✨

k近傍法 (KNN) は、そのシンプルさと直感的な理解しやすさから、機械学習の入門として学ぶのに最適なアルゴリズムの一つです。分類・回帰の両方に使え、複雑なデータ構造にもある程度対応できます。

一方で、計算コストやスケーリングの必要性、適切なハイパーパラメータ選択の難しさといったデメリットも理解しておく必要があります。

特にデータ数がそれほど多くなく、解釈性が求められる場面や、他の複雑なモデルを試す前のベースラインとして有用な手法と言えるでしょう。

次のステップでは、決定木やランダムフォレストなど、他の教師あり学習モデルについても学んでいきましょう!🚀

コメント

タイトルとURLをコピーしました