? 今日目標
- 理解 KNN 的原理與“以鄰為近”的思想
- 掌握 K 值選擇與模型效果的關系
- 學會使用
sklearn
訓練 KNN 模型 - 實現 KNN 分類 + 模型評估 + 超參數調優
📘 一、KNN 算法原理
KNN(K-Nearest Neighbors)核心思想:
給定一個待預測樣本,找到訓練集中“距離它最近”的 K 個樣本,用這些樣本的類別進行多數投票預測。
特點 | 描述 |
---|---|
模型類型 | 懶惰學習(無顯式訓練過程) |
距離度量 | 歐幾里得距離(默認)或自定義 |
參數調優 | K 值、距離函數、權重方式 |
適用場景 | 數據量不大,維度不高,需快速建模時 |
🧪 二、KNN 分類流程(代碼實踐)
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score# 生成數據
X = [[1], [2], [3], [10], [11], [12]]
y = [0, 0, 0, 1, 1, 1]# 訓練測試劃分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33)# 建模
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)# 預測
y_pred = model.predict(X_test)
print("準確率:", accuracy_score(y_test, y_pred))
🧠 三、K 值選擇對模型的影響
K 值 | 模型表現 |
---|---|
K 太小 | 模型過擬合,受噪聲影響大 |
K 太大 | 模型過于平滑,泛化能力下降 |
一般建議 | 使用奇數,避免投票平局;通過交叉驗證選擇最佳 K |
🔧 四、模型調參建議(使用 GridSearchCV)
from sklearn.model_selection import GridSearchCVparam_grid = {'n_neighbors': list(range(1, 11))}
grid_search = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5)
grid_search.fit(X_train, y_train)print("最優K值:", grid_search.best_params_)
print("最佳準確率:", grid_search.best_score_)
🧾 今日總結
技能 | 工具 |
---|---|
快速建模 | KNeighborsClassifier |
評估效果 | accuracy_score() |
參數調優 | GridSearchCV() |
可視化分類邊界 | 使用 matplotlib 或 seaborn |
🧪 建議練習腳本
-
使用 sklearn 中的 KNN 模型實現學生是否及格分類
-
嘗試多種 K 值進行訓練,并繪制準確率變化圖
-
使用 GridSearchCV 找出最優 K
-
可視化分類邊界(二維特征時)
# KNN 分類實戰演示:學生是否及格預測from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report import matplotlib.pyplot as plt import pandas as pd import numpy as npplt.rcParams['font.family'] = 'Arial Unicode MS' # Mac 用戶可用 plt.rcParams['axes.unicode_minus'] = False # 1. 模擬學生成績數據(兩個特征:成績 + 性別) np.random.seed(42) size = 100 scores = np.random.randint(40, 100, size) genders = np.random.choice([0, 1], size=size) # 0=女, 1=男 pass_label = (scores >= 60).astype(int)X = np.column_stack(((scores - scores.mean()) / scores.std(), genders)) # 標準化+性別 y = pass_label# 2. 拆分訓練集與測試集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 3. 不同 K 值準確率比較 acc_list = [] k_values = range(1, 16)for k in k_values:model = KNeighborsClassifier(n_neighbors=k)model.fit(X_train, y_train)y_pred = model.predict(X_test)acc = accuracy_score(y_test, y_pred)acc_list.append(acc)# 4. 可視化不同 K 值的準確率 plt.plot(k_values, acc_list, marker='o', linestyle='--') plt.title("不同 K 值下的準確率") plt.xlabel("K 值") plt.ylabel("準確率") plt.xticks(k_values) plt.grid(True) plt.tight_layout() plt.show()# 5. 使用 GridSearchCV 找最佳 K param_grid = {'n_neighbors': list(range(1, 16))} grid_search = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5) grid_search.fit(X_train, y_train)print("? 最佳 K 值:", grid_search.best_params_) print("📋 最佳交叉驗證準確率:", grid_search.best_score_)# 6. 在測試集上評估 best_model = grid_search.best_estimator_ y_pred = best_model.predict(X_test)print("\\n=== 最終模型評估(測試集) ===") print("準確率:", accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred))
運行輸出:
? 最佳 K 值: {'n_neighbors': 1} 📋 最佳交叉驗證準確率: 0.9875 \n=== 最終模型評估(測試集) === 準確率: 0.95precision recall f1-score support0 0.88 1.00 0.93 71 1.00 0.92 0.96 13accuracy 0.95 20macro avg 0.94 0.96 0.95 20 weighted avg 0.96 0.95 0.95 20