当前位置: 首页 > news >正文

day11 python超参数调整

  • 模型组成:模型 = 算法 + 实例化设置的外参(超参数)+ 训练得到的内参
  • 调参评估:调参通常需要进行两次评估。若不使用交叉验证,需手动划分验证集和测试集;但许多调参方法自带交叉验证功能,实际中可省略该步骤
  • 超参数学习:每个模型都有对应超参数且各具意义。若仅为追求精度或完成科研,可直接使用调参工具,无需深入研究每个超参数原理

一、数据预处理

首先执行数据预处理代码,为后续模型训练做准备:

import pandas as pd    # 用于数据处理和分析,支持表格数据操作
import numpy as np     # 用于高效的数值计算,提供数组操作功能
import matplotlib.pyplot as plt    # 用于绘制各类图表
import seaborn as sns   # 基于matplotlib的高级绘图库,生成美观的统计图形# 设置中文字体,解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False    # 确保负号正常显示
data = pd.read_csv('data.csv')    # 读取数据# 筛选字符串类型变量
discrete_features = data.select_dtypes(include=['object']).columns.tolist()# Home Ownership 标签编码
home_ownership_mapping = {'Own Home': 1,'Rent': 2,'Have Mortgage': 3,'Home Mortgage': 4
}
data['Home Ownership'] = data['Home Ownership'].map(home_ownership_mapping)# Years in current job 标签编码
years_in_job_mapping = {'< 1 year': 1,'1 year': 2,'2 years': 3,'3 years': 4,'4 years': 5,'5 years': 6,'6 years': 7,'7 years': 8,'8 years': 9,'9 years': 10,'10+ years': 11
}
data['Years in current job'] = data['Years in current job'].map(years_in_job_mapping)# Purpose 独热编码,并将bool类型转换为数值
data = pd.get_dummies(data, columns=['Purpose'])
data2 = pd.read_csv("data.csv") # 重新读取原始数据,用于列名对比
list_final = [] # 新建空列表,存储独热编码后新增的特征名
for i in data.columns:if i not in data2.columns:list_final.append(i) # 保存独热编码后的特征名
for i in list_final:data[i] = data[i].astype(int) # 将独热编码后的特征转换为整数类型# Term 0 - 1 映射
term_mapping = {'Short Term': 0,'Long Term': 1
}
data['Term'] = data['Term'].map(term_mapping)
data.rename(columns={'Term': 'Long Term'}, inplace=True) # 重命名列# 筛选连续型特征列名
continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist()# 用中位数填充连续型特征的缺失值
for feature in continuous_features:     mode_value = data[feature].mode()[0]            # 获取该列的众数data[feature].fillna(mode_value, inplace=True)  # 用众数填充缺失值,直接修改原数据

二、数据集划分

2.1 两次划分数据集(演示)

由于调参需两次评估,这里演示如何两次划分数据集(因相关函数一次只能划分一次):

from sklearn.model_selection import train_test_split
X = data.drop(['Credit Default'], axis=1)  # 提取特征,按列删除指定列
y = data['Credit Default']  # 提取标签# 第一次划分:80%训练集,20%临时集
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.2, random_state=42)# 第二次划分:临时集再分为50%验证集和50%测试集
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)print("Data shapes:")
print("X_train:", X_train.shape)
print("y_train:", y_train.shape)
print("X_val:", X_val.shape)
print("y_val:", y_val.shape)
print("X_test:", X_test.shape)
print("y_test:", y_test.shape)

运行结果

Data shapes:
X_train: (6000, 31)
y_train: (6000,)
X_val: (750, 31)
y_val: (750,)
X_test: (750, 31)
y_test: (750,)

2.2 一次划分数据集(实际使用)

考虑到多数调参函数自带交叉验证,实际中常进行一次划分(8:2 划分训练集和测试集):

from sklearn.model_selection import train_test_split
X = data.drop(['Credit Default'], axis=1)  # 提取特征
y = data['Credit Default'] # 提取标签# 80%训练集,20%测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

三、超参数调整方法概述

常见的超参数调整方法包括随机搜索、网格搜索和贝叶斯优化。在正式调参前,先构建基线模型(使用默认参数的 RandomForestClassifier),作为性能对比基准。

3.1 网格搜索 (GridSearchCV)

  • 原理:定义参数网格(param_grid),穷举所有参数组合进行评估
  • 缺点:计算成本高,参数组合随参数数量呈指数级增长,通常需缩小搜索范围或结合预筛选

3.2 随机搜索 (RandomizedSearchCV)

  • 原理:定义参数分布,在指定次数内随机采样评估
  • 优势:在高维参数空间中效率更高,较少迭代次数即可找到较优参数

3.3 贝叶斯优化 (BayesSearchCV from skopt)

  • 原理:基于历史评估结果构建概率模型(如高斯过程),预测最优参数组合
  • 优势:尤其适用于模型训练耗时场景,能用更少迭代次数达到更好性能

选择建议:计算资源充足选网格搜索;资源有限选贝叶斯优化;随机搜索应用相对较少。

四、模型训练与调参实战

4.1 默认参数的随机森林(基线模型)

import time 
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
start_time = time.time() # 记录开始时间from sklearn.ensemble import RandomForestClassifier # 导入随机森林分类器
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 评估指标
from sklearn.metrics import classification_report, confusion_matrix # 生成分类报告和混淆矩阵
import warnings # 用于忽略警告信息
warnings.filterwarnings("ignore") # 忽略所有警告rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train) # 在训练集上训练
rf_pred = rf_model.predict(X_test) # 在测试集上预测end_time = time.time() # 记录结束时间
print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))

运行结果

--- 1. 默认参数随机森林 (训练集 -> 测试集) ---
训练与预测耗时: 0.9972 秒默认随机森林 在测试集上的分类报告:precision    recall  f1-score   support0       0.77      0.97      0.86      10591       0.79      0.30      0.43       441accuracy                           0.77      1500macro avg       0.78      0.63      0.64      1500
weighted avg       0.77      0.77      0.73      1500默认随机森林 在测试集上的混淆矩阵:
[[1023   36][ 309  132]]

4.2 网格搜索优化随机森林

print("\n--- 2. 网格搜索优化随机森林 (训练集 -> 测试集) ---")
from sklearn.model_selection import GridSearchCV# 定义参数搜索网格
param_grid = {'n_estimators': [50, 100, 200],'max_depth': [None, 10, 20, 30],'min_samples_split': [2, 5, 10],'min_samples_leaf': [1, 2, 4]
}# 创建网格搜索对象
grid_search = GridSearchCV(estimator=RandomForestClassifier(random_state=42), # 随机森林分类器param_grid=param_grid, # 参数网格cv=5, # 5折交叉验证n_jobs=-1, # 使用所有可用CPU核心并行计算scoring='accuracy' # 以准确率为评分标准
)start_time = time.time()
grid_search.fit(X_train, y_train) # 在训练集上执行网格搜索
end_time = time.time()print(f"网格搜索耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", grid_search.best_params_) # 获取最佳参数组合# 使用最佳参数模型进行预测
best_model = grid_search.best_estimator_ # 获取最佳模型
best_pred = best_model.predict(X_test) # 在测试集上预测print("\n网格搜索优化后的随机森林 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("网格搜索优化后的随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))

运行结果

--- 2. 网格搜索优化随机森林 (训练集 -> 测试集) ---
网格搜索耗时: 56.7938 秒
最佳参数:  {'max_depth': 20, 'min_samples_leaf': 1, 'min_samples_split': 2, 'n_estimators': 200}网格搜索优化后的随机森林 在测试集上的分类报告:precision    recall  f1-score   support0       0.76      0.97      0.86      10591       0.80      0.28      0.42       441accuracy                           0.77      1500macro avg       0.78      0.63      0.64      1500
weighted avg       0.77      0.77      0.73      1500网格搜索优化后的随机森林 在测试集上的混淆矩阵:
[[1028   31][ 317  124]]

4.3 贝叶斯优化随机森林

print("\n--- 3. 贝叶斯优化随机森林 (训练集 -> 测试集) ---")
from skopt import BayesSearchCV
from skopt.space import Integer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
import time# 定义参数搜索空间
search_space = {'n_estimators': Integer(50, 200),'max_depth': Integer(10, 30),'min_samples_split': Integer(2, 10),'min_samples_leaf': Integer(1, 4)
}# 创建贝叶斯优化搜索对象
bayes_search = BayesSearchCV(estimator=RandomForestClassifier(random_state=42),search_spaces=search_space,n_iter=32,  # 迭代次数cv=5, # 5折交叉验证n_jobs=-1,scoring='accuracy'
)start_time = time.time()
bayes_search.fit(X_train, y_train) # 在训练集上执行贝叶斯优化
end_time = time.time()print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", bayes_search.best_params_)# 使用最佳参数模型进行预测
best_model = bayes_search.best_estimator_
best_pred = best_model.predict(X_test)print("\n贝叶斯优化后的随机森林 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("贝叶斯优化后的随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))

运行结果

--- 3. 贝叶斯优化随机森林 (训练集 -> 测试集) ---
贝叶斯优化耗时: 43.6849 秒
最佳参数:  OrderedDict([('max_depth', 21), ('min_samples_leaf', 3), ('min_samples_split', 4), ('n_estimators', 85)])贝叶斯优化后的随机森林 在测试集上的分类报告:precision    recall  f1-score   support0       0.76      0.97      0.85      10591       0.78      0.27      0.40       441accuracy                           0.76      1500macro avg       0.77      0.62      0.63      1500
weighted avg       0.77      0.76      0.72      1500贝叶斯优化后的随机森林 在测试集上的混淆矩阵:
[[1026   33][ 321  120]]

4.4 另一种贝叶斯优化实现(拓展)

此方法可自定义目标函数、灵活控制交叉验证,通过 verbose 参数输出中间过程:

print("\n--- 3. 贝叶斯优化随机森林 (训练集 -> 测试集) ---")
from bayes_opt import BayesianOptimization
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from sklearn.metrics import classification_report, confusion_matrix
import time
import numpy as np# 假设 X_train, y_train, X_test, y_test 已定义# 定义目标函数,使用交叉验证评估模型性能
def rf_eval(n_estimators, max_depth, min_samples_split, min_samples_leaf):n_estimators = int(n_estimators)max_depth = int(max_depth)min_samples_split = int(min_samples_split)min_samples_leaf = int(min_samples_leaf)model = RandomForestClassifier(n_estimators=n_estimators,max_depth=max_depth,min_samples_split=min_samples_split,min_samples_leaf=min_samples_leaf,random_state=42)scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')return np.mean(scores)# 定义参数搜索空间
pbounds_rf = {'n_estimators': (50, 200),'max_depth': (10, 30),'min_samples_split': (2, 10),'min_samples_leaf': (1, 4)
}# 创建贝叶斯优化对象,设置verbose=2显示详细迭代信息
optimizer_rf = BayesianOptimization(f=rf_eval,  # 目标函数pbounds=pbounds_rf,  # 参数空间random_state=42,  # 随机种子verbose=2  # 显示详细迭代信息
)start_time = time.time()
# 开始贝叶斯优化
optimizer_rf.maximize(init_points=5,  # 初始随机采样点数n_iter=32  # 迭代次数
)
end_time = time.time()print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", optimizer_rf.max['params'])# 使用最佳参数的模型进行预测
best_params = optimizer_rf.max['params']
best_model = RandomForestClassifier(n_estimators=int(best_params['n_estimators']),max_depth=int(best_params['max_depth']),min_samples_split=int(best_params['min_samples_split']),min_samples_leaf=int(best_params['min_samples_leaf']),random_state=42
)
best_model.fit(X_train, y_train)
best_pred = best_model.predict(X_test)print("\n贝叶斯优化后的随机森林 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("贝叶斯优化后的随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))

通过实践掌握了随机森林模型超参数调整方法,网格搜索虽能找到较优解但计算耗时久,随机搜索效率高但稳定性不足,贝叶斯优化结合历史数据预测最优参数组合,在效率与效果间取得平衡,同时也意识到数据预处理和数据集划分对模型性能的重要影响。

@浙大疏锦行

相关文章:

  • 32单片机——串口
  • C++初阶-string类1
  • Hadoop虚拟机中配置hosts
  • 微信小程序 XSS 防护知识整理
  • 上海车展,世界模型 + VLA,城区智驾进入下半场
  • 同时启动俩个tomcat压缩版
  • spring--事务详解
  • react-10样式模块化(./index.module.css, <div className={welcome.title}>Welcome</div>)
  • 神经网络用于地震数据时空均匀插值的方法与开源资料
  • 六、UI自动化测试06--PO设计模式
  • micro-app前端微服务原理解析
  • 论文笔记(八十二)Transformers without Normalization
  • linux系统加固
  • 逻辑回归之参数选择:从理论到实践
  • GNU gettext 快速上手
  • 两向量平行公式、向量与平面平行公式、两平面平行公式;两向量垂直公式、向量与平面垂直公式、两平面垂直公式
  • 基于 HT 构建 2D 智慧仓储可视化系统的技术解析
  • IP 地址和 MAC 地址是如何转换的
  • mac下载homebrew 安装和使用git
  • 3.2goweb框架GORM
  • 美国第一季度经济环比萎缩0.3%
  • 武汉楼市新政:二孩、三孩家庭购买新房可分别享受6万元、12万元购房补贴
  • 央行4月开展12000亿元买断式逆回购操作
  • “上博号”彩绘大飞机今日启航:万米高空传播中国古代文化
  • 西班牙葡萄牙电力基本恢复
  • 对谈|李钧鹏、周忆粟:安德鲁·阿伯特过程社会学的魅力