K 最近傍: 遅延分類器
K 最近傍 (KNN) は、最も直感的な機械学習アルゴリズムの 1 つです。 新しい点を分類するには、i を見てください。 K 個の最近接点 トレーニング データセット e 多数派クラスを割り当てます。トレーニング中に明示的なモデルを構築しません (これが呼ばれる理由です) 怠惰な学習者): すべての計算作業は予測時に発生します。 アルゴリズムは特徴空間内で近傍を検索する必要があります。
KNN のシンプルさは長所でもあり短所でもあります。理解と実装が簡単です。 ただし、データセットが大きい場合は、各トレーニング ポイントからの距離を計算する必要があるため遅くなります。 新しい予言。 KD-Tree や Ball Tree などのデータ構造はこの問題を軽減しますが、完全に解決するわけではありません。 完全に。
この記事で学べること
- KNN の仕組みと距離メトリック
- K の最適な値を選択する方法
- K-Means: 最も一般的なクラスタリング
- DBSCAN: 密度ベースのクラスタリング
- ラベルフリークラスタリングを評価する方法
- シルエットスコアとエルボーメソッド
距離メトリクス
KNN は次の概念に基づいています。 距離 特徴空間内の点の間。選択 メトリクスの値は結果に大きく影響します。そこには ユークリッド距離 そこにあります 最も一般的なもの: n 次元空間内の 2 点間の直線。そこには マンハッタンの距離 絶対差の合計を計算します (道路グリッド内を歩く場合など)。そこには の距離 ミンコフスキー これは最初の 2 つを一般化したもので、パラメータ p によって制御されます。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import numpy as np
# Dataset
wine = load_wine()
X, y = wine.data, wine.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Trovare il K ottimale
k_range = range(1, 31)
cv_scores = []
for k in k_range:
pipeline = Pipeline([
('scaler', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=k))
])
scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring='accuracy')
cv_scores.append(scores.mean())
best_k = k_range[np.argmax(cv_scores)]
print(f"Miglior K: {best_k} con accuracy: {max(cv_scores):.3f}")
# Modello finale con il K ottimale
final_pipeline = Pipeline([
('scaler', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=best_k, weights='distance'))
])
final_pipeline.fit(X_train, y_train)
test_accuracy = final_pipeline.score(X_test, y_test)
print(f"Test accuracy con K={best_k}: {test_accuracy:.3f}")
K 平均法クラスタリング
K 平均法 これは最もよく使用されるクラスタリング アルゴリズムです。データを分割する K 個のクラスター、各クラスターは独自に定義されます。 重心 (ポイント 中)。アルゴリズムは、各点を最も近い重心に割り当てることと、i を再計算することの 2 つのフェーズを交互に実行します。 割り当てられたポイントの平均としての重心。収束するまで繰り返します。
K 平均法は、同様のサイズの球状クラスターではうまく機能しますが、重要な制限があります。 Kを事前に指定すると、重心の初期化に敏感になります(部分的に修正されました) K-Means++ より)、不規則な形状や異なるサイズのクラスターを適切に処理できません。
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
import numpy as np
# Dati di esempio: segmentazione clienti
np.random.seed(42)
# 3 gruppi naturali di clienti
group1 = np.random.randn(100, 2) * 0.5 + [2, 2] # Budget
group2 = np.random.randn(100, 2) * 0.8 + [7, 7] # Premium
group3 = np.random.randn(100, 2) * 0.6 + [2, 8] # Frequenti
X = np.vstack([group1, group2, group3])
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Elbow method: trovare il K ottimale
inertias = []
silhouettes = []
K_range = range(2, 11)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = kmeans.fit_predict(X_scaled)
inertias.append(kmeans.inertia_)
silhouettes.append(silhouette_score(X_scaled, labels))
# Risultati
for k, inertia, sil in zip(K_range, inertias, silhouettes):
marker = " <-- ottimale" if k == 3 else ""
print(f"K={k}: Inertia={inertia:.1f}, Silhouette={sil:.3f}{marker}")
# Modello finale
kmeans_final = KMeans(n_clusters=3, random_state=42, n_init=10)
clusters = kmeans_final.fit_predict(X_scaled)
print(f"\nDistribuzione cluster: {np.bincount(clusters)}")
DBSCAN: 密度ベースのクラスタリング
DBSCAN (ノイズを含むアプリケーションの密度ベースの空間クラスタリング) それはアルゴリズムです クラスター数を事前に指定する必要のないクラスタリング。クラスターを次のように識別します 低密度領域によって分離された高密度領域。 2 つのパラメータは動作を制御します。 eps (近接半径) e min_samples (最低ポイント数 クラスターを形成します)。
DBSCAN はポイントを 3 つのカテゴリに分類します。 コアポイント (少なくとも min_samples が以内に近いもの) eps)、 境界点 (コアポイントに近いが、適切な近傍がほとんどない) e ノイズポイント (コアでも境界でもありません)。 K 平均法とは異なり、DBSCAN は任意の形状のクラスターを処理し、 外れ値を自動的に識別します。
from sklearn.cluster import DBSCAN, AgglomerativeClustering
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
from sklearn.datasets import make_moons
import numpy as np
# Dataset con cluster non sferici (mezzalune)
X, y_true = make_moons(n_samples=300, noise=0.1, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# DBSCAN
dbscan = DBSCAN(eps=0.3, min_samples=10)
labels_dbscan = dbscan.fit_predict(X_scaled)
n_clusters = len(set(labels_dbscan)) - (1 if -1 in labels_dbscan else 0)
n_noise = list(labels_dbscan).count(-1)
print(f"DBSCAN: {n_clusters} cluster, {n_noise} punti rumore")
if n_clusters > 1:
mask = labels_dbscan != -1
sil = silhouette_score(X_scaled[mask], labels_dbscan[mask])
print(f" Silhouette (escluso rumore): {sil:.3f}")
# Clustering Gerarchico (Agglomerativo)
agg = AgglomerativeClustering(n_clusters=2, linkage='ward')
labels_agg = agg.fit_predict(X_scaled)
sil_agg = silhouette_score(X_scaled, labels_agg)
print(f"\nHierarchical (Ward): Silhouette = {sil_agg:.3f}")
# K-Means per confronto (fatica con mezzalune)
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2, random_state=42, n_init=10)
labels_km = kmeans.fit_predict(X_scaled)
sil_km = silhouette_score(X_scaled, labels_km)
print(f"K-Means: Silhouette = {sil_km:.3f}")
クラスタリングの評価指標
クラスタリングの評価は教師付き分類よりも困難です。 参照ラベルはありません。の シルエットスコア 各ポイントがいくらであるかを測定します 近隣のクラスターと比較したクラスターの類似度: -1 (不正な割り当て) から 1 (密なクラスター) までの範囲 そしてよく分離されています)。の デイビス・ボールディン指数 クラスター間の平均類似性を測定します。 低いほど良いです。の カリンスキー・ハラバス指数 ~の間の関係を測定します クラスター間およびクラスター内の分散: 高いほど優れています。
KNN 対 K 平均法: 混同しないでください。 KNNはアルゴリズムです 監督された 分類/回帰用 (ラベルを使用)。 K-Means はアルゴリズムです 監視されていない クラスタリング (ラベルは使用しません)。彼らが共有している唯一のものは、文字「K」です。
各アルゴリズムをいつ使用するか
KNN: 中小規模のデータセットの分類問題と、 機能とターゲットはローカルで非線形です。 K 平均法: クラスターによるセグメンテーション用 球形でバランスが取れています。 DBSCAN: クラスターの形状が不規則な場合、外れ値が存在します。 有意であるか、クラスターの数が不明です。 階層的: 理解する必要があるとき グループ化階層とデータセットは大きすぎません。
重要なポイント
- KNN は K 最近傍に基づいて分類します。単純ですが、大規模なデータセットでは時間がかかります。
- K の選択は相互検証によって行われます。K が低すぎると過剰適合が発生し、高すぎると過小適合が発生します。
- K-Means は重心を持つ K 個のクラスターに分割します。既知の K が必要で、球状クラスターで動作します
- DBSCAN は密度に基づいて任意の形状のクラスターを検出し、外れ値を特定します
- シルエット スコアは、クラスタリングの品質を評価するために最も使用される指標です
- 特徴のスケーリングはすべての距離ベースのアルゴリズムに不可欠です







