DAY11
超参数调整专题
知识点回顾
- 网格搜索
- 随机搜索(简单介绍,非重点 实战中很少用到,可以不了解)
- 贝叶斯优化(2种实现逻辑,以及如何避开必须用交叉验证的问题)
- time库的计时模块,方便后人查看代码运行时长
今日作业:
对于信贷数据的其他模型,如LightGBM和KNN 尝试用下贝叶斯优化和网格搜索
#回顾一下
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
dt = pd.read_csv('heart.csv')
dt.info()
dt.head()
dt.isnull().sum()
def manual_normalize(dt):
min_val = dt.min()
max_val = dt.max()
normalized_dt = (dt - min_val) / (max_val - min_val)
return normalized_dt
dt['age'] = manual_normalize(dt['age'])
dt['trestbps'] = manual_normalize(dt['trestbps'])
dt['chol'] = manual_normalize(dt['chol'])
dt['thalach'] = manual_normalize(dt['thalach'])
dt['oldpeak'] = manual_normalize(dt['oldpeak'])
dt.head()
from sklearn.model_selection import train_test_split
x = dt.drop(['target'],axis=1)
y = dt['target']
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=42)
print(f"训练集形状: {x_train.shape}, 测试集形状: {x_test.shape}")
from sklearn.svm import SVC #支持向量机分类器
import warnings #用于忽略警告信息
warnings.filterwarnings("ignore")
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, precision_score, recall_score, f1_score
smodel = SVC(random_state=42)
smodel.fit(x_train,y_train)
smodel_pred = smodel.predict(x_test)
print("\nSVM 分类报告:")
print(classification_report(y_test, smodel_pred))
print("SVM 混淆矩阵:")
print(confusion_matrix(y_test, smodel_pred))
print("SVM 准确率:", accuracy_score(y_test, smodel_pred))
print("SVM 精确率:", precision_score(y_test, smodel_pred))
print("SVM 召回率:", recall_score(y_test, smodel_pred))
print("SVM F1 分数:", f1_score(y_test, smodel_pred))
# new数据预处理
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
dt = pd.read_csv('data.csv')
dt.info()
dt.head()
discrete_features = dt.select_dtypes(include=['object']).columns.tolist()
print("离散型特征列:", discrete_features)
continuous_features = dt.select_dtypes(include=['int64', 'float64']).columns.tolist()
print("连续型特征列:", continuous_features)
for features in discrete_features:
mode_value = dt[features].mode()[0]
dt[features].fillna(mode_value,inplace=True)
print(f'列:{features}用众数{mode_value}填充缺失值')
for features in continuous_features:
median_value = dt[features].median()
dt[features].fillna(median_value,inplace=True)
print(f'列:{features}用中位数{median_value}填充缺失值')
dt.info()
dt.head()
# Home Ownership 标签编码
home_ownership_mapping = {
'Own Home': 1,
'Rent': 2,
'Have Mortgage': 3,
'Home Mortgage': 4
}
dt['Home Ownership'] = dt['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
}
dt['Years in current job'] = dt['Years in current job'].map(years_in_job_mapping)
dt['Purpose'].value_counts()
# Purpose 独热编码,记得需要将bool类型转换为数值
dt = pd.get_dummies(dt, columns=['Purpose'])
dt2 = pd.read_csv("data.csv") # 重新读取数据,用来做列名对比
purpose_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in dt.columns:
if i not in dt2.columns:
purpose_final.append(i) # 这里打印出来的就是独热编码后的特征名
for i in purpose_final:
dt[i] = dt[i].astype(int) # 这里的i就是独热编码后的特征名
# Term 0 - 1 映射
term_mapping = {
'Short Term': 0,
'Long Term': 1
}
dt['Term'] = dt['Term'].map(term_mapping)
dt.rename(columns={'Term': 'Long Term'}, inplace=True) # 重命名列
def manual_normalize(dt):
min_val = dt.min()
max_val = dt.max()
normalized_dt = (dt - min_val) / (max_val - min_val)
return normalized_dt
for features in continuous_features:
dt[features] = manual_normalize(dt[features])
dt.head()
dt.info()
#删除id列
dt = dt.drop(['Id'],axis=1)
dt.head()
dt.info()
#划分训练集和测试集
from sklearn.model_selection import train_test_split
x = dt.drop(['Credit Default'],axis=1)
y = dt['Credit Default']
x_train,x_temp,y_train,y_temp = train_test_split(x,y,test_size=0.2,random_state=42)
x_test,x_val,y_test,y_val = train_test_split(x_temp,y_temp,test_size=0.5,random_state=42)
print("dt 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)
from sklearn.model_selection import train_test_split
x = dt.drop(['Credit Default'], axis=1) # 特征,axis=1表示按列删除
y = dt['Credit Default'] # 标签
# 按照8:2划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42) # 80%训练集,20%测试集
print("dt shapes:")
print("x_train:", x_train.shape)
print("y_train:", y_train.shape)
print("x_test:", x_test.shape)
print("y_test:", y_test.shape)
from sklearn.svm import SVC #支持向量机分类器
from sklearn.neighbors import KNeighborsClassifier #K近邻分类器
from sklearn.linear_model import LogisticRegression #逻辑回归分类器
import xgboost as xgb #XGBoost分类器
import lightgbm as lgb #LightGBM分类器
from sklearn.ensemble import RandomForestClassifier #LGB分类器
from catboost import CatBoostClassifier #CatBoost分类器
from sklearn.tree import DecisionTreeClassifier #决策树分类器
from sklearn.naive_bayes import GaussianNB #高斯朴素贝叶斯分类器
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") # 忽略所有警告信息
import time
print("--- 1. 默认参数LGB (训练集 -> 测试集) ---")
start_time = time.time()
lgb_model = lgb.LGBMClassifier(random_state=42) # 初始化LGB分类器
lgb_model.fit(x_train, y_train) # 训练模型
lgb_pred = lgb_model.predict(x_test) # 预测测试集
end_time = time.time()
print(f"训练时间:{ end_time - start_time:.4f}秒")
print("\nLGB 分类报告:")
print(classification_report(y_test, lgb_pred))
print("LGB 混淆矩阵:")
print(confusion_matrix(y_test, lgb_pred))
print("LGB F1 分数:", f1_score(y_test, lgb_pred))
print("\n--- 2. 网格搜索优化LGB (训练集 -> 测试集) ---")
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=lgb.LGBMClassifier(random_state=42), # LGB分类器
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_params_属性返回最佳参数组合
# 使用最佳参数的模型进行预测
best_model = grid_search.best_estimator_ # 获取最佳模型
best_pred = best_model.predict(x_test) # 在测试集上进行预测
print("\n网格搜索优化后的LGB 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("网格搜索优化后的LGB 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))
print("网格搜索优化后的LGB 在测试集上的 F1 分数:", f1_score(y_test, best_pred))
print("\n--- 3. 贝叶斯优化LGB (训练集 -> 测试集) ---")
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
# 定义目标函数,这里使用交叉验证来评估模型性能
def lgb_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_lgb = {
'n_estimators': (50, 200),
'max_depth': (10, 30),
'min_samples_split': (2, 10),
'min_samples_leaf': (1, 4)
}
# 创建贝叶斯优化对象,设置 verbose=2 显示详细迭代信息
optimizer_lgb = BayesianOptimization(
f=lgb_eval, # 目标函数
pbounds=pbounds_lgb, # 参数空间
random_state=42, # 随机种子
verbose=2 # 显示详细迭代信息
)
start_time = time.time()
# 开始贝叶斯优化
optimizer_lgb.maximize(
init_points=5, # 初始随机采样点数
n_iter=32 # 迭代次数
)
end_time = time.time()
print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", optimizer_lgb.max['params'])
# 使用最佳参数的模型进行预测
best_params = optimizer_lgb.max['params']
best_model = lgb.LGBMClassifier(
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贝叶斯优化后的LGB 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("贝叶斯优化后的LGB 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))
print("贝叶斯优化后的LGB 在测试集上的 F1 分数:", f1_score(y_test, best_pred))
print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")