.net企業(yè)網(wǎng)站網(wǎng)站建站價格
一、前言:為何要學交叉驗證與網(wǎng)格搜索?
大家好!在機器學習的道路上,我們經(jīng)常面臨一個難題:模型調(diào)參。比如在 KNN 算法中,選擇多少個鄰居(n_neighbors)直接影響預測效果。
? 蠻力猜測:就像在廚房隨便“加鹽加辣椒”,不僅費時費力,還可能把菜搞砸。
? 交叉驗證 + 網(wǎng)格搜索:更像是讓你請來一位“大廚”,提前試好所有配方,幫你挑選出最完美的“調(diào)料搭配”。
交叉驗證與網(wǎng)格搜索的組合,能讓你在眾多超參數(shù)組合中自動挑選出最佳方案,從而讓模型預測達到“哇塞,這也太準了吧!”的境界。
二、概念掃盲:交叉驗證 & 網(wǎng)格搜索
1. 交叉驗證(Cross-Validation)
核心思路:
? 分組品嘗:將整個數(shù)據(jù)集平均分成若干份(比如分成 5 份,即“5折交叉驗證”)。
? 輪流擔任評委:每次選取其中一份作為“驗證集”(就像讓這部分數(shù)據(jù)來“評委打分”),剩下的作為“訓練集”來訓練模型。
? 集體評定:重復多次,每一份都輪流擔任驗證集,然后把所有“評分”取平均,作為模型在數(shù)據(jù)集上的最終表現(xiàn)。
好處:
? 每個樣本都有機會既當“選手”又當“評委”,使得評估結果更穩(wěn)定、可靠。
? 避免單一劃分帶來的偶然性,確保你調(diào)出來的參數(shù)在不同數(shù)據(jù)切分下都表現(xiàn)良好。
2. 網(wǎng)格搜索(Grid Search)
核心思路:
? 列出所有可能:將你想嘗試的超參數(shù)組合“羅列成一個表格(網(wǎng)格)”。
? 自動試菜:每種組合都進行一次完整的模型訓練和評估,記錄下它們的表現(xiàn)。
? 選出最佳配方:最后找出在交叉驗證中表現(xiàn)最好的超參數(shù)組合。
好處:
? 自動化、系統(tǒng)化地尋找最佳參數(shù)組合,避免你手動“胡亂猜測”。
? 和交叉驗證結合后,每個參數(shù)組合都經(jīng)過了多次評估,結果更穩(wěn)健。
3. 網(wǎng)格搜索 + 交叉驗證
這兩者結合就像“煉丹”高手的秘訣:
? 交叉驗證解決了“數(shù)據(jù)切分”的問題,讓評估更準確;
? 網(wǎng)格搜索解決了“超參數(shù)組合”問題,幫你遍歷所有可能性。
合體后,你就能輕松找到最優(yōu)超參數(shù),讓模型發(fā)揮出最佳性能!
三、案例一:鳶尾花數(shù)據(jù)集 + KNN + 交叉驗證網(wǎng)格搜索
3.1 數(shù)據(jù)集介紹
? 數(shù)據(jù)來源:scikit-learn 內(nèi)置的 load_iris
? 特征:萼片長度、萼片寬度、花瓣長度、花瓣寬度
? 目標:根據(jù)花的外部特征預測其所屬的鳶尾花種類
3.2 代碼示例
下面代碼展示如何在鳶尾花數(shù)據(jù)集上使用 KNN 算法,并通過 GridSearchCV(交叉驗證+網(wǎng)格搜索)自動調(diào)優(yōu) n_neighbors 參數(shù):
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_scoredef iris_knn_cv():"""使用KNN算法在鳶尾花數(shù)據(jù)集上進行分類,并通過網(wǎng)格搜索+交叉驗證尋找最優(yōu)超參數(shù)。"""# 1. 加載數(shù)據(jù)iris = load_iris()X = iris.data # 特征矩陣,包含四個特征y = iris.target # 標簽,分別代表三種鳶尾花# 2. 劃分訓練集和測試集# test_size=0.2 表示 20% 的數(shù)據(jù)用于測試,保證測試結果具有代表性# random_state=22 固定隨機數(shù)種子,確保每次運行劃分一致X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=22)# 3. 數(shù)據(jù)標準化# 標準化可使各特征均值為0、方差為1,消除量綱影響(對于基于距離的KNN非常重要)scaler = StandardScaler()X_train_scaled = scaler.fit_transform(X_train)X_test_scaled = scaler.transform(X_test)# 4. 構建KNN模型及參數(shù)調(diào)優(yōu)knn = KNeighborsClassifier() # 初始化KNN模型# 4.1 設置網(wǎng)格搜索參數(shù)范圍:嘗試不同的鄰居數(shù)param_grid = {'n_neighbors': [1, 3, 5, 7, 9]}# 4.2 進行網(wǎng)格搜索 + 交叉驗證(5折交叉驗證)grid_search = GridSearchCV(estimator=knn, # 待調(diào)參的模型param_grid=param_grid, # 超參數(shù)候選列表cv=5, # 5折交叉驗證:將訓練集分為5個子集,每次用1個子集驗證,其余4個訓練scoring='accuracy', # 以準確率作為評估指標n_jobs=-1 # 使用所有CPU核心并行計算)grid_search.fit(X_train_scaled, y_train) # 自動遍歷各參數(shù)組合并評估# 4.3 輸出網(wǎng)格搜索結果print("最佳交叉驗證分數(shù):", grid_search.best_score_)print("最優(yōu)超參數(shù)組合:", grid_search.best_params_)print("最優(yōu)模型:", grid_search.best_estimator_)# 5. 模型評估:用測試集評估最優(yōu)模型的泛化能力best_model = grid_search.best_estimator_y_pred = best_model.predict(X_test_scaled)acc = accuracy_score(y_test, y_pred)print("在測試集上的準確率:{:.2f}%".format(acc * 100))# 6. 可視化(選做):可進一步繪制混淆矩陣或?qū)W習曲線# 直接調(diào)用函數(shù)進行測試
if __name__ == "__main__":iris_knn_cv()
輸出:?
3.3 結果解讀
? 最佳交叉驗證分數(shù):表示在5折交叉驗證過程中,所有參數(shù)組合中平均準確率最高的值。
? 最優(yōu)超參數(shù)組合:顯示在候選參數(shù) [1, 3, 5, 7, 9] 中哪個 n_neighbors 的效果最好。
? 測試集準確率:驗證模型在未見數(shù)據(jù)上的表現(xiàn),反映其泛化能力。
通過這個案例,你可以看到交叉驗證網(wǎng)格搜索如何自動幫你“挑菜”選料,讓 KNN 模型在鳶尾花分類任務上達到最佳表現(xiàn)。
四、案例二:手寫數(shù)字數(shù)據(jù)集 + KNN + 交叉驗證網(wǎng)格搜索
4.1 數(shù)據(jù)集介紹
? 數(shù)據(jù)來源:scikit-learn 內(nèi)置的 load_digits
? 特征:每張 8×8 像素的手寫數(shù)字圖像被拉伸成64維特征向量
? 目標:識別圖片中數(shù)字所屬類別(0~9)
4.2 代碼示例
下面代碼展示如何在手寫數(shù)字數(shù)據(jù)集上使用 KNN 算法,并通過交叉驗證網(wǎng)格搜索調(diào)優(yōu)參數(shù):
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits # 導入手寫數(shù)字數(shù)據(jù)集(內(nèi)置于 scikit-learn)
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler # 導入數(shù)據(jù)標準化工具
from sklearn.neighbors import KNeighborsClassifier # 導入KNN分類器
from sklearn.metrics import accuracy_score, confusion_matrix
import seaborn as sns # 導入 seaborn,用于繪制更美觀的圖表def digits_knn_cv():"""使用KNN算法在手寫數(shù)字數(shù)據(jù)集上進行分類,并通過網(wǎng)格搜索+交叉驗證尋找最優(yōu)超參數(shù)。"""# 1. 加載數(shù)據(jù)digits = load_digits() # 從scikit-learn加載內(nèi)置手寫數(shù)字數(shù)據(jù)集X = digits.data # 特征數(shù)據(jù),形狀為 (1797, 64),每一行對應一張圖片的64個像素值y = digits.target # 目標標簽,共10個類別(數(shù)字 0 到 9)# 2. 數(shù)據(jù)可視化:展示前5張圖片及其標簽# 創(chuàng)建一個1行5列的子圖區(qū)域,圖像尺寸為10x2英寸fig, axes = plt.subplots(1, 5, figsize=(10, 2))for i in range(5):# 顯示第 i 張圖片,使用灰度圖(cmap='gray')axes[i].imshow(digits.images[i], cmap='gray')# 設置每個子圖的標題,顯示該圖片對應的標簽axes[i].set_title("Label: {}".format(digits.target[i]))# 關閉坐標軸顯示(避免坐標信息干擾視覺效果)axes[i].axis('off')plt.suptitle("手寫數(shù)字數(shù)據(jù)集示例") # 為整個圖表添加一個總標題plt.show() # 顯示圖表# 3. 數(shù)據(jù)劃分 + 標準化# 將數(shù)據(jù)劃分為訓練集和測試集,其中測試集占20%,random_state保證每次劃分一致X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 初始化標準化工具,將特征數(shù)據(jù)轉換為均值為0、方差為1的標準正態(tài)分布scaler = StandardScaler()# 僅在訓練集上擬合標準化參數(shù),并轉換訓練集數(shù)據(jù)X_train_scaled = scaler.fit_transform(X_train)# 使用相同的轉換參數(shù)轉換測試集數(shù)據(jù)(避免數(shù)據(jù)泄露)X_test_scaled = scaler.transform(X_test)# 4. 構建KNN模型及網(wǎng)格搜索調(diào)參knn = KNeighborsClassifier() # 初始化KNN分類器,暫未指定 n_neighbors 參數(shù)# 定義一個字典,列出希望嘗試的超參數(shù)組合# 這里我們測試不同鄰居數(shù)的效果:[1, 3, 5, 7, 9]param_grid = {'n_neighbors': [1, 3, 5, 7, 9]}# 初始化網(wǎng)格搜索對象,結合交叉驗證grid_search = GridSearchCV(estimator=knn, # 需要調(diào)參的KNN模型param_grid=param_grid, # 超參數(shù)候選組合cv=5, # 5折交叉驗證,將訓練數(shù)據(jù)分成5份,每次用4份訓練,1份驗證scoring='accuracy', # 使用準確率作為模型評估指標n_jobs=-1 # 并行計算,使用所有可用的CPU核心加速計算)# 在標準化后的訓練集上進行網(wǎng)格搜索,自動嘗試所有參數(shù)組合,并進行交叉驗證grid_search.fit(X_train_scaled, y_train)# 5. 輸出網(wǎng)格搜索調(diào)參結果# 打印在交叉驗證中獲得的最佳平均準確率print("手寫數(shù)字 - 最佳交叉驗證分數(shù):", grid_search.best_score_)# 打印獲得最佳結果時所使用的超參數(shù)組合,例如 {'n_neighbors': 3}print("手寫數(shù)字 - 最優(yōu)超參數(shù)組合:", grid_search.best_params_)# 打印最佳模型對象,該模型已使用最優(yōu)參數(shù)重新訓練best_model = grid_search.best_estimator_# 6. 模型評估:用測試集評估模型效果# 使用最優(yōu)模型對測試集進行預測y_pred = best_model.predict(X_test_scaled)# 計算測試集上的準確率acc = accuracy_score(y_test, y_pred)print("手寫數(shù)字 - 測試集準確率:{:.2f}%".format(acc * 100))# 7. 可視化混淆矩陣(直觀展示各數(shù)字分類效果)# 混淆矩陣能夠顯示真實標簽與預測標簽之間的對應關系cm = confusion_matrix(y_test, y_pred)plt.figure(figsize=(6, 5))# 使用 seaborn 的 heatmap 繪制混淆矩陣,annot=True 表示在每個單元格中顯示數(shù)字sns.heatmap(cm, annot=True, cmap='Blues', fmt='d')plt.title("手寫數(shù)字 - 混淆矩陣")plt.xlabel("預測值")plt.ylabel("真實值")plt.show()# 直接調(diào)用函數(shù)進行測試
if __name__ == "__main__":digits_knn_cv()
輸出:
4.3 結果解讀
? 最優(yōu) n_neighbors:通過交叉驗證,我們找到了在候選參數(shù)中使模型表現(xiàn)最佳的鄰居數(shù)量。
? 測試集準確率:在手寫數(shù)字識別任務上,通常準確率能達到90%以上,證明 KNN 在小數(shù)據(jù)集上也能表現(xiàn)不錯。
? 混淆矩陣:直觀展示哪些數(shù)字容易混淆(例如數(shù)字“3”和“5”),便于進一步分析和改進。
混淆矩陣圖的含義與作用
1. 橫縱坐標的含義
? 行(縱軸)代表真實標簽(真實的數(shù)字 0~9)。
? 列(橫軸)代表模型預測的標簽(預測的數(shù)字 0~9)。
2. 數(shù)值和顏色深淺
? 單元格 (i, j) 內(nèi)的數(shù)值表示:真實類別為 i 的樣本中,有多少被預測為 j。
? 越靠近對角線(i = j)代表預測正確的數(shù)量;
? 離對角線越遠,說明模型將真實類別 i 的樣本錯誤地預測成類別 j。
? 熱力圖中顏色越深表示數(shù)量越多,淺色則表示數(shù)量少。
3. 作用
? 評估模型分類效果:如果對角線上的數(shù)值高且遠離對角線的數(shù)值低,說明模型分類準確度高;反之,說明某些類別容易被混淆。
? 發(fā)現(xiàn)易混淆的類別:通過觀察非對角線位置是否有較大的數(shù)值,可以知道哪些數(shù)字最容易被誤判。例如,模型可能經(jīng)常把“3”預測成“5”,這能提示我們在后續(xù)改進中加強這兩個類別的區(qū)分。
? 比單純的準確率更全面:準確率只能告訴你模型整體正確率,而混淆矩陣能告訴你哪類錯誤最多,便于更有針對性地提升模型性能。
五、總結 & 彩蛋
1. 交叉驗證的價值
? 有效避免過擬合,通過多次分組驗證,使得模型評估更穩(wěn)健。
2. 網(wǎng)格搜索的強大
? 自動遍歷所有超參數(shù)組合,省去手動調(diào)參的煩惱,快速鎖定“最佳拍檔”。
3. KNN 的局限
? 雖然簡單易用,但在大規(guī)模、高維數(shù)據(jù)中計算量較大,且對異常值較敏感。
4. 后續(xù)進階
? 可以嘗試隨機搜索(RandomizedSearchCV)或貝葉斯優(yōu)化,甚至轉向更復雜的模型如 CNN 進行數(shù)字識別。
結語
如果你覺得本篇文章對你有所幫助,請記得點贊、收藏、轉發(fā)和評論哦!你的支持是我繼續(xù)創(chuàng)作的最大動力。讓我們一起在機器學習的道路上不斷探索、不斷進步,早日成為調(diào)參界的“神仙”!
祝學習愉快,煉丹順利~