機器學習模型調優實戰指南

文章目錄

  • 模型選擇與調優:從理論到實戰
    • 1. 引言
    • 2. 模型評估:為選擇提供依據
      • 2.1 偏差-方差權衡
      • 2.2 數據集劃分與分層抽樣
      • 2.3 交叉驗證(Cross-Validation)
      • 2.4 信息準則(AIC / BIC)
    • 3. 超參數調優:讓模型更好
      • 3.1 網格搜索 (Grid Search)
      • 3.2 隨機搜索 (Randomized Search)
      • 3.3 貝葉斯優化 (Bayesian Optimization)
    • 4. 模型選擇:如何最終定奪
      • 4.1 集成學習的思路
      • 4.2 評估指標(詳細公式)
        • 分類任務:
        • 回歸任務:
    • 5. 實戰案例:以 KNN 和隨機森林為例
    • 6. 總結與建議

模型選擇與調優:從理論到實戰

1. 引言

在機器學習中,模型選擇與調優是決定模型性能的關鍵步驟。一個好的算法如果參數配置不當,可能表現不如一個簡單模型;而錯誤的評估方法也可能導致“看似很準”,實則泛化能力極差。本文將從模型評估超參數調優模型比較三個維度展開,并結合公式、代碼和圖示給出系統性理解。


2. 模型評估:為選擇提供依據

2.1 偏差-方差權衡

模型預測誤差可分解為:
E[(y?f^(x))2]=Bias2+Variance+σ2\mathbb{E}[(y-\hat{f}(x))^2] = \text{Bias}^2 + \text{Variance} + \sigma^2 E[(y?f^?(x))2]=Bias2+Variance+σ2

  • Bias(偏差):模型假設與真實分布的差異。
  • Variance(方差):模型對訓練數據波動的敏感性。
  • σ2\sigma^2:不可約誤差。

圖示通常表現為:模型復雜度增加 → 偏差下降、方差上升。最佳點是兩者平衡的位置。

bc1ba08ac606fbc862436f903688e246_720

什么是偏差(Bias)? 什么是方差(Variance)?
其實可以套到生活中"準" 跟"確" 這兩個概念,如果用高中軍訓課打靶的經驗來說,那就是:
如果說你打靶打得很精"準",意味你子彈射中的地方離靶心很近,即Low Bias;
如果說你打靶打得很精"確",意味你在發射數槍之后這幾槍彼此之間在靶上的距離很近,即Low Variance。
接著下面用一張圖來說明,應該就一目了然了!

b28b8719957f468d32ef8eda579ec006


2.2 數據集劃分與分層抽樣

保留交叉驗證Hold-Out(留出法)是最簡單的評估方式:將數據分為訓練集和測試集。但對于類別不平衡問題,普通劃分可能導致訓練或測試集中類別分布偏移。此時應使用 train_test_split 的分層參數:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42
)
  • stratify=y:確保分割后各數據集的類別比例與原始數據一致,減少評估偏差。

2.3 交叉驗證(Cross-Validation)

不同交叉驗證方法的對比:

  1. K-Fold

    • K 折交叉驗證將數據集分割為 K 個互斥的子集(折疊,fold),每次用 K-1 個子集作為訓練集,剩下的 1 個子集作為驗證集,重復 K 次,最終得到 K 個模型的評估結果(如準確率、MSE 等),取平均值作為模型的最終性能指標。

    • 實現:

      from sklearn.model_selection import KFold
      
    • 公式:
      CV?Error=1K∑i=1KEi\text{CV Error} = \frac{1}{K} \sum_{i=1}^K E_i CV?Error=K1?i=1K?Ei?

    • 適用于數據量較大、類別分布均衡的情況。

  2. Stratified K-Fold

    • Stratified K-Fold(分層 K 折交叉驗證) 是 K 折交叉驗證的一種改進版本,專門用于分類問題,其核心特點是在劃分數據集時保持每個折中類別比例與原始數據集一致,避免因隨機劃分導致的類別分布失衡,從而更穩健地評估模型性能。

    • 實現:

      from sklearn.model_selection import StratifiedKFold
      
  3. Leave-One-Out (LOO)

    • 每次只留一個樣本作為驗證,其余樣本作為訓練。
    • 優點:幾乎無偏估計。
    • 缺點:計算量大、方差高。
  4. Hold-Out

    • 單次劃分,計算效率高,但結果波動較大。

K 折交叉驗證的作用不是“提高泛化性”,而是更穩定、無偏地估計泛化誤差。調參過程中,它幫助選擇在新數據上表現最好的模型。

代碼示例:

from sklearn.datasets import load_wine
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
import numpy as np# 1. 加載數據
X, y = load_wine(return_X_y=True)# 2. 標準化數據
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)# 3. 創建KFold對象
kfold = KFold(n_splits=5, shuffle=True, random_state=42)# 4. 進行交叉驗證
scores = []
for train_idx, test_idx in kfold.split(X_scaled):X_train, X_test = X_scaled[train_idx], X_scaled[test_idx]y_train, y_test = y[train_idx], y[test_idx]# 訓練模型knn = KNeighborsClassifier(n_neighbors=5)knn.fit(X_train, y_train)# 預測并計算準確率y_pred = knn.predict(X_test)score = accuracy_score(y_test, y_pred)scores.append(score)# 5. 輸出結果
print("每折的準確率:", scores)
print("平均準確率:", np.mean(scores))
print("標準差:", np.std(scores))

輸出結果如下:

每折的準確率: [0.9444444444444444, 0.9444444444444444, 0.9722222222222222, 0.9142857142857143, 0.9714285714285714]
平均準確率: 0.9493650793650794
標準差: 0.02139268011280184

2.4 信息準則(AIC / BIC)

對于概率模型,可使用信息準則進行模型選擇:

  • AIC(Akaike Information Criterion)
    AIC=2k?2ln?(L)\text{AIC} = 2k - 2\ln(L) AIC=2k?2ln(L)

    • kkk:模型參數數量
    • LLL:似然函數最大值
    • 目標:懲罰參數數量,鼓勵較好擬合。
  • BIC(Bayesian Information Criterion)
    BIC=kln?(n)?2ln?(L)\text{BIC} = k\ln(n) - 2\ln(L) BIC=kln(n)?2ln(L)

    • nnn:樣本數量
    • 與 AIC 區別:BIC 對模型復雜度懲罰更強,更傾向選擇簡單模型。

功能總結

  • AIC 偏好泛化能力強的模型。
  • BIC 偏好更簡單、更保守的模型。
  • 二者都基于最大似然估計,適用于概率模型(如回歸、時間序列)。

3. 超參數調優:讓模型更好

3.1 網格搜索 (Grid Search)

窮舉所有組合,計算成本高但適合小搜索空間:

from sklearn.model_selection import GridSearchCV
param_grid = {'n_neighbors': [3,5,7], 'weights': ['uniform','distance']}
grid = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5)
grid.fit(X_train, y_train)
print(grid.best_params_, grid.best_score_)

weights='uniform'(默認值):等權重

  • 含義:所有 K 個鄰居的投票權重相同,預測結果由 “多數鄰居的類別” 決定(簡單多數投票)。

weights='distance':距離加權

  • 含義:鄰居的權重與其到待預測樣本的距離成反比 ——距離越近的鄰居,權重越大,對預測結果的影響越強。

3.2 隨機搜索 (Randomized Search)

隨機采樣部分參數組合:
P(找到最優解)=1?(1?p)nP(\text{找到最優解}) = 1 - (1-p)^n P(找到最優解)=1?(1?p)n
(其中ppp 為采樣一次命中最優區域的概率,nnn 為采樣次數。)

3.3 貝葉斯優化 (Bayesian Optimization)

利用高斯過程或樹模型擬合“超參數 → 評分”的函數,通過采集函數(如期望改進 EI)智能選擇下一步采樣位置。


4. 模型選擇:如何最終定奪

4.1 集成學習的思路

  • Bagging:降低方差(隨機森林)。
  • Boosting:降低偏差(XGBoost)。
  • Stacking:綜合多模型優勢。

4.2 評估指標(詳細公式)

分類任務:
  • 準確率
    Accuracy=TP+TNTP+FP+TN+FN\text{Accuracy} = \frac{TP+TN}{TP+FP+TN+FN} Accuracy=TP+FP+TN+FNTP+TN?

  • 精確率(Precision)
    Precision=TPTP+FP\text{Precision} = \frac{TP}{TP+FP} Precision=TP+FPTP?

  • 召回率(Recall)
    Recall=TPTP+FN\text{Recall} = \frac{TP}{TP+FN} Recall=TP+FNTP?

  • F1 分數
    F1=2?Precision?RecallPrecision+RecallF1 = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} F1=2?Precision+RecallPrecision?Recall?

  • AUC(ROC 曲線下面積):衡量分類器對正負樣本排序能力。

    這個鏈接有個在線實驗可以幫助理解:
    Google實驗案例
    image-20250806191204763

回歸任務:
  • 均方誤差 (MSE)
    MSE=1n∑i=1n(yi?y^i)2\text{MSE} = \frac{1}{n}\sum_{i=1}^n (y_i-\hat{y}_i)^2 MSE=n1?i=1n?(yi??y^?i?)2

  • 平均絕對誤差 (MAE)
    MAE=1n∑i=1n∣yi?y^i∣\text{MAE} = \frac{1}{n}\sum_{i=1}^n |y_i-\hat{y}_i| MAE=n1?i=1n?yi??y^?i?

  • 決定系數 (R2)
    R2=1?∑(yi?y^i)2∑(yi?yˉ)2R^2 = 1 - \frac{\sum (y_i-\hat{y}_i)^2}{\sum (y_i-\bar{y})^2} R2=1?(yi??yˉ?)2(yi??y^?i?)2?


5. 實戰案例:以 KNN 和隨機森林為例

  1. 劃分數據集并進行標準化

  2. 使用 Stratified K-Fold 進行評估

  3. 分別通過 Grid Search 和 Random Search 調參

  4. 對比最佳模型性能(表格+曲線)

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from sklearn.datasets import make_classification
    from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV, RandomizedSearchCV
    from sklearn.preprocessing import StandardScaler
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.pipeline import Pipeline
    from scipy.stats import randint# 1. 加載數據
    data = make_classification(n_samples=1000, n_features=20, n_informative=10, n_redundant=5,n_classes=3, n_clusters_per_class=1, random_state=42
    )
    X, y = data
    print(f"數據集特征數: {X.shape[1]}, 樣本數: {X.shape[0]}, 類別數: {len(np.unique(y))}")# 2. 分層劃分訓練集和測試集(保持類別比例)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42
    )# 3. 定義分層K折交叉驗證(適合分類問題)
    cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)# 4. KNN - 網格搜索(KNN需要標準化)
    knn_pipe = Pipeline([('scaler', StandardScaler()),  # KNN對特征尺度敏感,必須標準化('knn', KNeighborsClassifier())
    ])
    param_knn = {'knn__n_neighbors': [3, 5, 7, 9],  # 增加參數范圍'knn__weights': ['uniform', 'distance']
    }
    grid_knn = GridSearchCV(estimator=knn_pipe,param_grid=param_knn,cv=cv,scoring='accuracy',n_jobs=-1,  # 使用所有可用CPUverbose=1  # 顯示調參過程
    )
    grid_knn.fit(X_train, y_train)# 5. 隨機森林 - 隨機搜索(隨機森林不需要標準化)
    rf_pipe = Pipeline([# 移除StandardScaler,隨機森林對特征尺度不敏感('rf', RandomForestClassifier(random_state=42))
    ])
    param_rf = {'rf__n_estimators': randint(50, 200),  # 增加參數范圍'rf__max_depth': randint(3, 15),'rf__min_samples_split': randint(2, 10),'rf__min_samples_leaf': randint(1, 5)  # 增加葉子節點參數
    }
    random_rf = RandomizedSearchCV(estimator=rf_pipe,param_distributions=param_rf,n_iter=20,  # 增加搜索迭代次數cv=cv,scoring='accuracy',n_jobs=-1,random_state=42,verbose=1
    )
    random_rf.fit(X_train, y_train)# 6. 性能對比表格
    results = pd.DataFrame({'模型': ['KNN(網格搜索)', '隨機森林(隨機搜索)'],'最佳參數': [grid_knn.best_params_, random_rf.best_params_],'交叉驗證準確率': [f"{grid_knn.best_score_:.4f}", f"{random_rf.best_score_:.4f}"],'測試集準確率': [f"{grid_knn.score(X_test, y_test):.4f}", f"{random_rf.score(X_test, y_test):.4f}"]
    })
    print("\n模型性能對比:")
    print(results)# 7. 可視化 - KNN超參數(n_neighbors)與準確率關系
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 顯示中文
    plt.rcParams['axes.unicode_minus'] = False    # 顯示負號
    plt.figure(figsize=(10, 6))# 提取網格搜索結果
    mean_scores = grid_knn.cv_results_['mean_test_score']
    params = grid_knn.cv_results_['params']# 按權重分組繪制
    for weight in ['uniform', 'distance']:# 篩選當前權重的結果scores = [mean_scores[i] for i, p in enumerate(params) if p['knn__weights'] == weight]n_neighbors = [p['knn__n_neighbors'] for i, p in enumerate(params) if p['knn__weights'] == weight]plt.plot(n_neighbors, scores, marker='o', label=f'權重={weight}')plt.xlabel('近鄰數量(n_neighbors)')
    plt.ylabel('交叉驗證準確率')
    plt.title('KNN不同近鄰數量與權重的性能對比')
    plt.legend()
    plt.grid(alpha=0.3)
    plt.tight_layout()
    plt.show()# 8. 輸出最佳模型在測試集上的表現
    print("\nKNN最佳模型測試集準確率:", grid_knn.score(X_test, y_test))
    print("隨機森林最佳模型測試集準確率:", random_rf.score(X_test, y_test))
    數據集特征數: 20, 樣本數: 1000, 類別數: 3
    Fitting 5 folds for each of 8 candidates, totalling 40 fits
    Fitting 5 folds for each of 20 candidates, totalling 100 fits模型性能對比:模型                                               最佳參數 交叉驗證準確率  \
    0   KNN(網格搜索)  {'knn__n_neighbors': 7, 'knn__weights': 'dista...  0.9262   
    1  隨機森林(隨機搜索)  {'rf__max_depth': 9, 'rf__min_samples_leaf': 1...  0.9287   測試集準確率  
    0  0.9450  
    1  0.9200
    

    image-20250806192309446


6. 總結與建議

  • 分層抽樣在類別不平衡下必不可少。
  • K 折交叉驗證是為了更穩定地估計泛化誤差,而非直接“提高泛化性”。
  • AIC/BIC更適用于概率模型;交叉驗證適合通用機器學習場景。
  • 實戰中可結合隨機搜索 + 貝葉斯優化以降低計算成本。
  • 評估指標需根據業務目標選取,而非盲目追求單一指標。

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

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

相關文章

【教程】Unity CI/CD流程

測試機:紅帽 Linux8 源碼倉庫:Gitee - MrRiver/Unity Example ? 系統環境準備 1)yum 源 sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo sudo sed -i s/\$releasever/8/g /etc/yum.repos…

文獻閱讀 | Briefings in Bioinformatics | Hiplot:全面且易于使用的生物醫學可視化分析平臺

文獻介紹文獻題目: Hiplot:一個綜合且易于使用的 Web 服務,用于增強出版物準備的生物醫學數據可視化 研究團隊: Openbiox/Hiplot 社區 發表時間: 2022-07-05 發表期刊: Briefings in Bioinformatics 影響因…

【數字圖像處理系列筆記】Ch04:灰度變換與空間域圖像增強(2)

目錄 一、空域濾波基礎 一、空域濾波的基本概念 二、空域濾波的數學原理 三、空域濾波器的分類與典型示例 (一)線性濾波器(Linear Filter) (二)非線性濾波器(Non-linear Filter&#xff0…

AI浪潮下,FPGA如何實現自我重塑與行業變革

引言:AI 與 FPGA,新時代的碰撞 2025 年,人工智能技術迎來爆發式增長,大模型、生成式 AI 和多模態技術持續突破,人形機器人量產元年正式開啟,自動駕駛商業化進程加速,工業數字化轉型全面鋪開(1)…

系統集成項目管理工程師【第十一章 規劃過程組】定義范圍、創建WBS、規劃進度管理和定義活動篇

系統集成項目管理工程師【第十一章 規劃過程組】定義范圍、創建WBS、規劃進度管理和定義活動篇 一、定義范圍:給項目畫好"邊界線" 定義范圍是明確項目和產品"做什么、不做什么"的過程,直接影響后續所有工作的方向。 1. 核心概念與作…

Spring Boot 參數校驗全指南

Spring Boot 參數校驗全指南 在 Web 開發中,參數校驗是保障接口安全性和數據合法性的關鍵環節。手動編寫校驗邏輯不僅繁瑣,還容易遺漏邊界情況。Spring Boot 整合了 validation 工具,提供了一套簡潔高效的參數校驗方案,可快速實現…

常用技術資料鏈接

1.team技術 https://zhuanlan.zhihu.com/p/11389323664 https://blog.csdn.net/Lucky_Lu0/article/details/121697151 2.bond切換主備 https://www.xgss.net/3306.html 3.ssh詳解: https://cloud.tencent.com/developer/news/105165 https://blog.huochengrm.c…

【Spring Cloud】-- 注冊中心

文章目錄1. 什么是注冊中心2. CPA理論1. 什么是注冊中心 注冊中心有三種角色: 服務提供者(Server) :提供接口給其他微服務的程序。服務消費者(Client):調用其他微服務提供的接口。**服務注冊中…

go-zero 詳解

go-zero 詳解 go-zero 是一個基于 Go 語言的微服務框架,由字節跳動團隊開發并開源,旨在幫助開發者快速構建高可用、高性能的微服務架構。它集成了豐富的組件,簡化了微服務開發中的常見問題(如服務注冊發現、配置管理、限流熔斷等&…

接口自動化框架封裝之統一請求封裝及通過文件實現接口關聯

接口自動化測試框架封裝目的:簡化自動化框架的落地,提高投入和產出比,只要一個人封裝好框架,另外的測試通過寫yaml測試用例即可實現接口自動化1.統一請求的封裝去除多余重復的代碼可跨py文件實現通過一個session來自動關聯有cookie的接口設置統一公共參數,統一文件處理,統一異常…

Vue 最佳實踐:如何利用唯一 key 值保證 el-table 動態渲染的穩定性

📋 問題描述 在Vue 2.0 ElementUI項目的偏置條件管理頁面中,每次切換到"內規拉偏"菜單時,表格樣式會發生崩潰,導致表格布局異常、列寬錯亂、固定列顯示不正確等問題。 🔍 問題分析 通過深入分析代碼&#x…

popen開啟進程,寫入數據

通過管道&#xff08;popen&#xff09;啟動 SDIWAN_WEB 進程并寫入 JSON 數據的過程可以分為以下步驟&#xff0c;結合代碼示例和關鍵注意事項進行說明&#xff1a;1. 核心代碼示例 #include <stdio.h> #include <json-c/json.h>int main() {// 1. 創建 JSON 對象…

計算機視覺的四項基本任務辨析

計算機視覺是使計算機能理解采集設備采集的圖像視頻的一門學科&#xff0c;目的是讓計算機實現人的視覺功能——對客觀世界的三維場景的感知、識別和理解。換句話說&#xff0c;要讓計算機具備通過二維圖像認識三維環境的能力。 目錄 三個階段 視覺層級 基本任務 技術難點…

iostat 系統IO監控命令學習

一、iostat 命令描述 “iostat”命令用于監測系統輸入/輸出設備的負載情況&#xff0c;其通過觀察設備處于活躍狀態的時間與平均傳輸速率之間的關系來實現這一目的。該命令會生成報告&#xff0c;這些報告可用于調整系統配置&#xff0c;以更好地平衡物理磁盤之間的輸入/輸出負…

jenkins使用ssh方式連接gitee 公鑰、私鑰配置、指紋

前言 Gitee 提供了基于 SSH 協議的 Git 服務&#xff0c;jenkins可使用ssh方式連接gitee&#xff0c;拉取代碼、提交tag等&#xff1b;使用ssh 連接&#xff0c;相比用戶名密碼方式&#xff0c;可省去因密碼變更而引起的jenkins關聯修改。 gitee生成、添加 SSH 公鑰 生成SSH…

如何在Android設備上刪除多個聯系人(3種方法)

如果您想清理安卓手機&#xff0c;或者只是想刪除舊的、不需要的聯系人&#xff0c;或者刪除多個聯系人&#xff0c;有三種有效的方法可供選擇。無論您是想手動刪除安卓手機上的聯系人&#xff0c;還是使用專用工具&#xff0c;都可以按照以下步驟操作。方法1&#xff1a;如何通…

Angular進階之十三:Angular全新控制流:革命性的模板語法升級

隨著Angular v17的發布&#xff0c;框架帶來了革命性的控制流語法&#xff0c;徹底改變了我們編寫模板的方式。這些改進不僅僅是語法糖——它們提升了性能、開發體驗和代碼可維護性。 為什么我們需要新的控制流&#xff1f; 在之前的Angular版本中&#xff0c;我們使用結構指令…

【Redis】string字符串

目錄 一.常見命令 1.1.SET 1.2.GET 1.3.MGET 1.4.MSET 1.5.SETNX 二.計數命令 2.1.INCR 2.2.INCRBY 2.3.DECR 2.4.DECYBY 2.5.INCRBYFLOAT 三 . 其他命令 3.1.APPEND 3.2.GETRANGE 3.3.SETRANGE 3.4.STRLEN 四. 字符串類型內部編碼 五. 典型使用場…

Nginx 學習

通過網盤分享的文件&#xff1a;Nginx 鏈接: https://pan.baidu.com/s/1dCc7FoND90H_x7rvRUXJqg 提取碼: yyds 通過網盤分享的文件&#xff1a;Tomcat 鏈接: https://pan.baidu.com/s/1nj_5j_66gS_YHUAX1C25jg 提取碼: yyds Nginx安裝、啟動 安裝依賴庫 #安裝C編譯器 yum insta…

Java、Android及計算機基礎面試題總結

1. String、StringBuffer、StringBuilder區別特性StringStringBufferStringBuilder可變性不可變可變可變線程安全是是(synchronized)否性能低(頻繁操作時)中等高場景字符串常量多線程字符串操作單線程字符串操作2. 接口和抽象類的區別特性接口(Interface)抽象類(Abstract Class…