KNN算法詳解及Scikit-learn API使用指南

一、KNN算法介紹

K最近鄰(K-Nearest Neighbor, KNN)算法是機器學習中最簡單、最直觀的分類算法之一。它既可以用于分類問題,也可以用于回歸問題。KNN是一種基于實例的學習(instance-based learning)或懶惰學習(lazy learning)算法,因為它不會從訓練數據中學習一個明確的模型,而是直接使用訓練數據本身進行預測。

1.1 KNN算法原理

KNN算法的核心思想可以概括為:"物以類聚,人以群分"。對于一個待分類的樣本,算法會在訓練集中找到與之最相似的K個樣本(即"最近鄰"),然后根據這K個樣本的類別來決定待分類樣本的類別。

具體步驟如下:

  1. 計算待分類樣本與訓練集中每個樣本的距離(通常使用歐氏距離)

  2. 選取距離最近的K個訓練樣本

  3. 統計這K個樣本中每個類別出現的頻率

  4. 將頻率最高的類別作為待分類樣本的預測類別

1.2 KNN算法的特點

優點:

  • 簡單直觀,易于理解和實現

  • 無需訓練過程,新數據可以直接加入訓練集

  • 對數據分布沒有假設,適用于各種形狀的數據分布

缺點:

  • 計算復雜度高,預測時需要計算與所有訓練樣本的距離

  • 對高維數據效果不佳(維度災難)

  • 對不平衡數據敏感

  • 需要選擇合適的K值和距離度量方式

二、Scikit-learn中的KNN實現

Scikit-learn提供了KNeighborsClassifier和KNeighborsRegressor兩個類分別用于KNN分類和回歸。下面我們重點介紹KNeighborsClassifier。

2.1 KNeighborsClassifier API詳解

class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,          # K值,默認5weights='uniform',      # 權重函數algorithm='auto',       # 計算最近鄰的算法leaf_size=30,           # KD樹或球樹的葉子節點大小p=2,                    # 距離度量參數(1:曼哈頓距離,2:歐氏距離)metric='minkowski',     # 距離度量類型metric_params=None,     # 距離度量的額外參數n_jobs=None             # 并行計算數
)
主要參數說明:
  1. n_neighbors (int, default=5)

    • K值,即考慮的最近鄰的數量

    • 較小的K值會使模型對噪聲更敏感,較大的K值會使決策邊界更平滑

    • 通常通過交叉驗證來選擇最佳K值

  2. weights ({'uniform', 'distance'} or callable, default='uniform')

    • 'uniform': 所有鄰居的權重相同

    • 'distance': 權重與距離成反比,距離越近的鄰居影響越大

    • 也可以自定義權重函數

  3. algorithm ({'auto', 'ball_tree', 'kd_tree', 'brute'}, default='auto')

    • 計算最近鄰的算法:

      • 'brute': 暴力搜索,計算所有樣本的距離

      • 'kd_tree': KD樹,適用于低維數據

      • 'ball_tree': 球樹,適用于高維數據

      • 'auto': 自動選擇最合適的算法

  4. leaf_size (int, default=30)

    • KD樹或球樹的葉子節點大小

    • 影響樹的構建和查詢速度

  5. p (int, default=2)

    • 距離度量的參數:

      • p=1: 曼哈頓距離

      • p=2: 歐氏距離

    • 僅當metric='minkowski'時有效

  6. metric (str or callable, default='minkowski')

    • 距離度量類型,可以是:

      • 'euclidean': 歐氏距離

      • 'manhattan': 曼哈頓距離

      • 'chebyshev': 切比雪夫距離

      • 'minkowski': 閔可夫斯基距離

      • 或自定義距離函數

  7. n_jobs (int, default=None)

    • 并行計算數

    • -1表示使用所有處理器

2.2 常用方法

  • fit(X, y): 擬合模型,只需要存儲訓練數據

  • predict(X): 預測X的類別

  • predict_proba(X): 返回X屬于各類別的概率

  • kneighbors([X, n_neighbors, return_distance]): 查找點的K近鄰

  • score(X, y): 返回給定測試數據和標簽的平均準確率

三、KNN分類實戰示例

3.1 基礎示例:鳶尾花分類

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix# 加載數據集
iris = load_iris()
X = iris.data  # 特征 (150, 4)
y = iris.target  # 標簽 (150,)# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 創建KNN分類器
knn = KNeighborsClassifier(n_neighbors=5,      # 使用5個最近鄰weights='uniform',   # 均勻權重algorithm='auto',    # 自動選擇算法p=2                  # 歐氏距離
)# 訓練模型(實際上只是存儲數據)
knn.fit(X_train, y_train)# 預測測試集
y_pred = knn.predict(X_test)# 評估模型
print("分類報告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
print("\n混淆矩陣:")
print(confusion_matrix(y_test, y_pred))

3.2 進階示例:手寫數字識別?

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import matplotlib.pyplot as plt
import numpy as np# 加載手寫數字數據集
digits = load_digits()
X = digits.data  # (1797, 64)
y = digits.target  # (1797,)# 可視化一些樣本
fig, axes = plt.subplots(2, 5, figsize=(10, 5))
for i, ax in enumerate(axes.flat):ax.imshow(X[i].reshape(8, 8), cmap='gray')ax.set_title(f"Label: {y[i]}")ax.axis('off')
plt.show()# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 創建管道:先標準化數據,再應用KNN
pipe = Pipeline([('scaler', StandardScaler()),  # 標準化特征('knn', KNeighborsClassifier())  # KNN分類器
])# 設置參數網格進行網格搜索
param_grid = {'knn__n_neighbors': [3, 5, 7, 9],  # 不同的K值'knn__weights': ['uniform', 'distance'],  # 兩種權重方式'knn__p': [1, 2]  # 曼哈頓距離和歐氏距離
}# 創建網格搜索對象
grid = GridSearchCV(pipe, param_grid, cv=5,  # 5折交叉驗證scoring='accuracy',  # 評估指標n_jobs=-1  # 使用所有CPU核心
)# 執行網格搜索
grid.fit(X_train, y_train)# 輸出最佳參數和得分
print(f"最佳參數: {grid.best_params_}")
print(f"最佳交叉驗證準確率: {grid.best_score_:.4f}")# 在測試集上評估最佳模型
best_model = grid.best_estimator_
test_score = best_model.score(X_test, y_test)
print(f"測試集準確率: {test_score:.4f}")# 可視化一些預測結果
sample_indices = np.random.choice(len(X_test), 10, replace=False)
sample_images = X_test[sample_indices]
sample_labels = y_test[sample_indices]
predicted_labels = best_model.predict(sample_images)plt.figure(figsize=(12, 3))
for i, (image, true_label, pred_label) in enumerate(zip(sample_images, sample_labels, predicted_labels)):plt.subplot(1, 10, i+1)plt.imshow(image.reshape(8, 8), cmap='gray')plt.title(f"True: {true_label}\nPred: {pred_label}", fontsize=8)plt.axis('off')
plt.tight_layout()
plt.show()

3.3 自定義距離度量示例?

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import make_classification
import numpy as np# 自定義距離函數:余弦相似度
def cosine_distance(x, y):return 1 - np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y))# 創建模擬數據
X, y = make_classification(n_samples=1000, n_features=20, n_classes=3, random_state=42
)# 使用自定義距離度量的KNN
knn_custom = KNeighborsClassifier(n_neighbors=5,metric=cosine_distance,  # 使用自定義距離algorithm='brute'         # 自定義距離需要暴力搜索
)# 使用標準KNN作為對比
knn_standard = KNeighborsClassifier(n_neighbors=5)# 劃分訓練集和測試集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 訓練并評估兩個模型
knn_custom.fit(X_train, y_train)
knn_standard.fit(X_train, y_train)print(f"自定義距離KNN準確率: {knn_custom.score(X_test, y_test):.4f}")
print(f"標準KNN準確率: {knn_standard.score(X_test, y_test):.4f}")

四、KNN回歸實戰示例

總結:一句話區分核心差異

  • 分類:回答 “這是什么” 的問題,輸出離散類別(如 “是垃圾郵件”);
  • 回歸:回答 “這有多少” 的問題,輸出連續數值(如 “房價 300 萬”)。

雖然本文主要介紹分類問題,但KNN也可以用于回歸。下面是一個簡單的回歸示例:

from sklearn.neighbors import KNeighborsRegressor
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt# 創建回歸數據集
X, y = make_regression(n_samples=200, n_features=1, noise=10, random_state=42
)# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 創建KNN回歸器
knn_reg = KNeighborsRegressor(n_neighbors=5,weights='distance',  # 距離加權p=1                  # 曼哈頓距離
)# 訓練模型
knn_reg.fit(X_train, y_train)# 預測
y_pred = knn_reg.predict(X_test)# 評估
mse = mean_squared_error(y_test, y_pred)
print(f"均方誤差(MSE): {mse:.2f}")# 可視化結果
plt.scatter(X_test, y_test, color='blue', label='Actual')
plt.scatter(X_test, y_pred, color='red', label='Predicted')
plt.title('KNN Regression')
plt.xlabel('Feature')
plt.ylabel('Target')
plt.legend()
plt.show()

五、KNN調優技巧

5.1 K值選擇

K值的選擇對KNN性能有很大影響:

  • K值太小:模型對噪聲敏感,容易過擬合

  • K值太大:模型過于簡單,可能欠擬合

常用方法:

  1. 使用交叉驗證選擇最佳K值

  2. 經驗法則:K通常取3-10之間的奇數(避免平票)

5.2 數據預處理

KNN對數據尺度敏感,通常需要:

  • 標準化:將特征縮放到均值為0,方差為1

  • 歸一化:將特征縮放到[0,1]范圍

5.3 維度災難

高維空間中,所有點都趨向于遠離彼此,導致距離度量失效。解決方法:

  • 特征選擇:選擇最相關的特征

  • 降維:使用PCA等方法降低維度

5.4 距離度量選擇

不同距離度量適用于不同場景:

  • 歐氏距離:適用于連續變量

  • 曼哈頓距離:適用于高維數據或稀疏數據

  • 余弦相似度:適用于文本數據

六、總結

KNN是一種簡單但強大的機器學習算法,特別適合小規模數據集和低維問題。通過Scikit-learn的KNeighborsClassifier,我們可以方便地實現KNN算法,并通過調整各種參數來優化模型性能。

關鍵點回顧:

  1. KNN是一種懶惰學習算法,沒有顯式的訓練過程

  2. K值和距離度量的選擇對模型性能至關重要

  3. 數據預處理(特別是標準化)對KNN非常重要

  4. 高維數據中KNN可能表現不佳,需要考慮降維

希望本教程能幫助你理解和應用KNN算法。在實際應用中,記得結合交叉驗證和網格搜索來找到最佳參數組合。

?

?

?

?

?

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/89424.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/89424.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/89424.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【PMP】項目管理入門:從基礎到環境的體系化拆解

不少技術管理者都有過這樣的困惑: 明明按流程做了項目管理,結果還是延期、超預算?需求變更多到炸,到底是客戶無理還是自己沒管好?跨部門協作像“推皮球”,資源總不到位? 其實,項目失…

【Web前端】簡易輪播圖顯示(源代碼+解析+知識點)

一、簡易輪播圖源代碼 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>簡易輪播圖顯示</title><style type"text/css">*{margin: 0 auto;padding: 0;/* 全局重置邊距 */}p{text-align: center;fon…

電機試驗平臺的用途及實驗范圍

電機試驗平臺是一種專門設計用來對各種類型的電機進行測試和分析的設備。在現代工業中&#xff0c;電機作為驅動力的重要組成部分&#xff0c;在各個領域發揮著至關重要的作用。而為了確保電機的性能、效率和可靠性達到最佳水平&#xff0c;需要進行各種試驗和測試。電機試驗平…

自主/智能的本質內涵及其相互關系

論文地址&#xff1a;無人機的自主與智能控制 - 中國知網 (cnki.net) 自主/智能的本質內涵及其相互關系準則是無人機設計的基本原則。從一般意義上講。自主與智能是兩個不同范疇的概念。自主表達的是行為方式&#xff0c;由自身決策完成某行為則稱之為“自主”。“智能”…

nignx+Tomcat+NFS負載均衡加共享儲存服務腳本

本次使有4臺主機&#xff0c;系統均為centos7&#xff0c;1臺nignx&#xff0c;2臺tomcat&#xff0c;1臺nfs 第一臺配置nignx腳本 #!/bin/bash #xiexianghu 2025.6.24 #nignx配置腳本&#xff0c;centos7#關閉防火墻和SElinux systemctl stop firewalld && system…

zabbix監控Centos 服務器

1.2&#xff1a;本地安裝 先使用wget下載RPM安裝包 然后解壓安裝 >>wget https://repo.zabbix.com/zabbix/6.4/rhel/8/x86_64/zabbix-agent2-6.4.21-release1.el8.x86_64.rpm ##### CENTOS 8 使用這一條>>rpm -ivh zabbix-agent2-6.4.21-release1.el8.x86_64.r…

中科米堆三維掃描儀3D掃描壓力閥抄數設計

三維掃描技術正以數字化手段重塑傳統制造流程。以壓力閥這類精密流體控制元件為例&#xff0c;其內部流道結構的幾何精度直接影響設備運行穩定性與使用壽命。 在傳統設計模式下&#xff0c;壓力閥的逆向工程需經歷手工測繪、二維圖紙繪制、三維建模轉換等多個環節。技術人員需…

Python pytz 時區使用舉例

Python pytz 時區使用舉例 ? 一、Python代碼實現&#xff1a;時區轉換與時間比較 import pytz from datetime import datetime# 1. 獲取當前UTC時間 utc_now datetime.now(pytz.utc)# 2. 轉換為目標時區&#xff08;示例&#xff1a;上海和紐約&#xff09; shanghai_tz py…

vue中ref()和reactive()區別

好的&#xff0c;這是 Vue 3 中 ref() 和 reactive() 這兩個核心響應式 API 之間區別的詳細解釋。 簡單來說&#xff0c;它們是創建響應式數據的兩種方式&#xff0c;主要區別在于處理的數據類型和訪問數據的方式。 核心區別速查表 特性ref()reactive()適用類型? 任何類型 …

目標檢測數據集——交通信號燈紅綠燈檢測數據集

在智能交通系統迅速發展的背景下&#xff0c;準確且實時地識別交通信號燈的狀態對于提升道路安全和優化交通流量管理至關重要。 無論是自動駕駛汽車還是輔助駕駛技術&#xff0c;可靠地檢測并理解交通信號燈的指示——特別是紅燈與綠燈的區別——是確保交通安全、避免交通事故…

哪款即時通訊服務穩定性靠譜?18家對比

本文將深入對比18家 IM 服務商&#xff1a;1.網易云信; 2. 有度即時通; 3. 環信; 4. 小天互連; 5. 企達即時通訊; 6. 敏信即時通訊; 7. 360織語; 8. 容聯云通訊; 9. 云之訊 UCPaaS等。 在如今的數字化時代&#xff0c;即時通訊&#xff08;IM&#xff09;軟件已經成為企業日常運…

【Android】Flow學習及使用

目錄 前言基礎基本用法概念與核心特點Android中使用與LiveData對比熱流StateFlow、SharedFlow 搜索輸入流實現實時搜索 前言 ? Flow是kotlin協程庫中的一個重要組成部分&#xff0c;它可以按順序發送多個值&#xff0c;用于對異步數據流進行處理。所謂異步數據流就是連續的異…

idea常做的配置改動和常用插件

IDEA 使用 最強教程&#xff0c;不多不雜。基于idea旗艦版 2019.2.3左右的版本&#xff0c;大多數是windows的&#xff0c;少數是mac版的 一、必改配置 1、ctrl滾輪 調整字體大小 全局立即生效&#xff1a;settings -> Editor -> General -> Change font size with …

3. 物理信息神經網絡(PINNs)和偏微分方程(PDE),用物理定律約束神經網絡

導言&#xff1a;超越時間&#xff0c;擁抱空間 在前兩篇章中&#xff0c;我們已經走過了漫長而深刻的旅程。我們學會了用常微分方程&#xff08;ODE&#xff09;來描述事物如何隨時間演化&#xff0c;從一個初始狀態出發&#xff0c;描繪出一條獨一無二的生命軌跡。我們還學會…

Flutter基礎(基礎概念和方法)

概念比喻StatefulWidget會變魔術的電視機State電視機的小腦袋&#xff08;記信息&#xff09;build 方法電視機變身顯示新畫面setState按遙控器按鈕改變狀態Scaffold電視機的外殼 StatefulWidget&#xff1a;創建一個按鈕組件。State&#xff1a;保存點贊數&#xff08;比如 i…

K8s——Pod(1)

目錄 基本概念 ?一、Pod 的原理? ?二、Pod 的特性? ?三、Pod 的意義? 狀態碼詳解 ?一、Pod 核心狀態詳解? ?二、其他關鍵狀態標識? ?三、狀態碼運維要點? 探針 ?一、探針的核心原理? ?二、三大探針的特性與作用? ?參數詳解? ?三、探針的核心意義…

MySQL 存儲過程面試基礎知識總結

文章目錄 MySQL 存儲過程面試基礎知識總結一、存儲過程基礎&#xff08;一&#xff09;概述1.優點2.缺點 &#xff08;二&#xff09;創建與調用1.創建存儲過程2.調用存儲過程3.查看存儲過程4.修改存儲過程5.存儲過程權限管理 &#xff08;三&#xff09;參數1.輸入參數2.輸出參…

NLP文本數據增強

文章目錄 文本數據增強同義詞替換示例Python代碼示例 隨機插入示例Python代碼示例 隨機刪除示例Python代碼示例 回譯&#xff08;Back Translation&#xff09;示例Python代碼示例 文本生成模型應用方式示例Python代碼示例 總結 文本數據增強 數據增強通過對原始數據進行變換、…

(LeetCode 每日一題) 594. 最長和諧子序列 (哈希表)

題目&#xff1a;594. 最長和諧子序列 思路&#xff1a;哈希表&#xff0c;時間復雜度0(n)。 用哈希表mp來記錄每個元素值出現的次數&#xff0c;然后枚舉所有值x&#xff0c;看其x1是否存在&#xff0c;存在的話就可以維護最長的子序列長度mx。 C版本&#xff1a; class Sol…

FreePDF:讓看英文文獻像喝水一樣簡單

前言 第一次看英文文獻&#xff0c;遇到不少看不懂的英文單詞&#xff0c;一個個查非常費勁。 后來&#xff0c;學會了使用劃詞翻譯&#xff0c;整段整段翻譯查看&#xff0c;極大提升看文獻效率。 最近&#xff0c;想到了一種更快的看文獻的方式&#xff0c;那就是把英文PD…