Day11 补昨天没做完的内容+常见调参方法

@浙大疏锦行

小碎碎念:果然,三分钟热度的崽会忍不住开始拖延,不过不能明日复明日,明日何其多了啊啊啊啊啊啊啊啊啊。今天一定得补上!!!

okok,正式开始补昨天的内容和学今天的内容

一、机器学习的建模和评估(昨天的)

数据划分

# 数据集的划分
from sklearn.model_selection import train_test_split
# 准备标签和特征
X = data_encoded.drop(TARGET_COLUMN, axis=1)
y = data_encoded[TARGET_COLUMN]
# 划分数据集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=42,stratify=y)
# 测试集占比为20%,固定随机种子,确保结果可以复现,stratify=y确保划分后目标变量比例一致
print(f"训练集形状: {X_train.shape}, 测试集形状: {X_test.shape}")  # 打印训练集和测试集的形状
训练集形状: (242, 25), 测试集形状: (61, 25)

模型的训练与评估

机器学习是典型的三行代码:(都是封装死的,调用就好)

  1. 模型实例化
  2. 代入训练集进行模型训练
  3. 代入测试集进行模型预测

混淆矩阵是由测试集的预测值和测试集的真实值进行对比得到的(针对二分类问题)

混淆矩阵是希望对角线越大越好,预测的越准确

基于混淆矩阵的固定阈值的评估指标

  1. 准确率:预测准确的比例
  2. 精确率(关注是否有误报):模型预测为正例的样本中,实际为正例的比例
  3. 召回率(关注是否有漏报的情况):所有实际为正例的样本中,被模型正确预测为正例的比例
  4. F1值,F1分数,2*精确率*召回率/(精确率+召回率)
  5. AUC指标(对抗不平衡数据的影响):ROC曲线下的面积,取值范围为 0~1 ,是衡量二分类模型区分能力的量化指标。越接近1,性能越好
  6. ROC曲线:以 假阳性率(FPR) 为横轴, 真阳性率(TPR) 为纵轴绘制的曲线,反映二分类模型在不同阈值下的性能权衡。

    核心参数 :

    -真阳性率(TPR) :患病样本中被正确预测的比例 TPR = TP / (TP + FN) (医学上称为 敏感度/召回率 )
    -假阳性率(FPR) :健康样本中被错误预测的比例 FPR = FP / (FP + TN)
    绘制逻辑 :通过调整分类阈值(如0.1→0.9),计算不同阈值下的TPR和FPR,连接各点形成曲线。 理想情况 :曲线靠近左上角(高TPR+低FPR),表示模型能准确区分患病与健康样本。

# 模型训练与评估
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 #随机森林分类器
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") # 忽略所有警告信息

model_metrics = []

# SVM
svm_model = SVC(random_state=42)
svm_model.fit(X_train, y_train)
svm_pred = svm_model.predict(X_test)

print("\nSVM 分类报告:")
print(classification_report(y_test, svm_pred))  # 打印分类报告
print("SVM 混淆矩阵:")
print(confusion_matrix(y_test, svm_pred))  # 打印混淆矩阵

# 计算 SVM 评估指标,这些指标默认计算正类的性能
svm_accuracy = accuracy_score(y_test, svm_pred)
svm_precision = precision_score(y_test, svm_pred)
svm_recall = recall_score(y_test, svm_pred)
svm_f1 = f1_score(y_test, svm_pred)
print("SVM 模型评估指标:")
print(f"准确率: {svm_accuracy:.4f}")
print(f"精确率: {svm_precision:.4f}")
print(f"召回率: {svm_recall:.4f}")
print(f"F1 值: {svm_f1:.4f}")

model_metrics.append({
    '模型名称': 'SVM',
    '准确率': round(svm_accuracy, 4),
    '精确率': round(svm_precision, 4),
    '召回率': round(svm_recall, 4),
    'F1分数': round(svm_f1, 4)
})

# KNN
knn_model = KNeighborsClassifier()
knn_model.fit(X_train, y_train)
knn_pred = knn_model.predict(X_test)

print("\nKNN 分类报告:")
print(classification_report(y_test, knn_pred))
print("KNN 混淆矩阵:")
print(confusion_matrix(y_test, knn_pred))

knn_accuracy = accuracy_score(y_test, knn_pred)
knn_precision = precision_score(y_test, knn_pred)
knn_recall = recall_score(y_test, knn_pred)
knn_f1 = f1_score(y_test, knn_pred)
print("KNN 模型评估指标:")
print(f"准确率: {knn_accuracy:.4f}")
print(f"精确率: {knn_precision:.4f}")
print(f"召回率: {knn_recall:.4f}")
print(f"F1 值: {knn_f1:.4f}")

model_metrics.append({
    '模型名称': 'KNN',
    '准确率': round(knn_accuracy, 4),
    '精确率': round(knn_precision, 4),
    '召回率': round(knn_recall, 4),
    'F1分数': round(knn_f1, 4)
})
# 逻辑回归
logreg_model = LogisticRegression(random_state=42)
logreg_model.fit(X_train, y_train)
logreg_pred = logreg_model.predict(X_test)

print("\n逻辑回归 分类报告:")
print(classification_report(y_test, logreg_pred))
print("逻辑回归 混淆矩阵:")
print(confusion_matrix(y_test, logreg_pred))

logreg_accuracy = accuracy_score(y_test, logreg_pred)
logreg_precision = precision_score(y_test, logreg_pred)
logreg_recall = recall_score(y_test, logreg_pred)
logreg_f1 = f1_score(y_test, logreg_pred)
print("逻辑回归 模型评估指标:")
print(f"准确率: {logreg_accuracy:.4f}")
print(f"精确率: {logreg_precision:.4f}")
print(f"召回率: {logreg_recall:.4f}")
print(f"F1 值: {logreg_f1:.4f}")

model_metrics.append({
    '模型名称': '逻辑回归',
    '准确率': round(logreg_accuracy, 4),
    '精确率': round(logreg_precision, 4),
    '召回率': round(logreg_recall, 4),
    'F1分数': round(logreg_f1, 4)
})

# 朴素贝叶斯
nb_model = GaussianNB()
nb_model.fit(X_train, y_train)
nb_pred = nb_model.predict(X_test)

print("\n朴素贝叶斯 分类报告:")
print(classification_report(y_test, nb_pred))
print("朴素贝叶斯 混淆矩阵:")
print(confusion_matrix(y_test, nb_pred))

nb_accuracy = accuracy_score(y_test, nb_pred)
nb_precision = precision_score(y_test, nb_pred)
nb_recall = recall_score(y_test, nb_pred)
nb_f1 = f1_score(y_test, nb_pred)
print("朴素贝叶斯 模型评估指标:")
print(f"准确率: {nb_accuracy:.4f}")
print(f"精确率: {nb_precision:.4f}")
print(f"召回率: {nb_recall:.4f}")
print(f"F1 值: {nb_f1:.4f}")

model_metrics.append({
    '模型名称': '朴素贝叶斯',
    '准确率': round(nb_accuracy, 4),
    '精确率': round(nb_precision, 4),
    '召回率': round(nb_recall, 4),
    'F1分数': round(nb_f1, 4)
})


# 随机森林
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train)
rf_pred = rf_model.predict(X_test)

print("\n随机森林 分类报告:")
print(classification_report(y_test, rf_pred))
print("随机森林 混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))

rf_accuracy = accuracy_score(y_test, rf_pred)
rf_precision = precision_score(y_test, rf_pred)
rf_recall = recall_score(y_test, rf_pred)
rf_f1 = f1_score(y_test, rf_pred)
print("随机森林 模型评估指标:")
print(f"准确率: {rf_accuracy:.4f}")
print(f"精确率: {rf_precision:.4f}")
print(f"召回率: {rf_recall:.4f}")
print(f"F1 值: {rf_f1:.4f}")

model_metrics.append({
    '模型名称': '随机森林',
    '准确率': round(rf_accuracy, 4),
    '精确率': round(rf_precision, 4),
    '召回率': round(rf_recall, 4),
    'F1分数': round(rf_f1, 4)
})

# XGBoost
xgb_model = xgb.XGBClassifier(random_state=42)
xgb_model.fit(X_train, y_train)
xgb_pred = xgb_model.predict(X_test)

print("\nXGBoost 分类报告:")
print(classification_report(y_test, xgb_pred))
print("XGBoost 混淆矩阵:")
print(confusion_matrix(y_test, xgb_pred))

xgb_accuracy = accuracy_score(y_test, xgb_pred)
xgb_precision = precision_score(y_test, xgb_pred)
xgb_recall = recall_score(y_test, xgb_pred)
xgb_f1 = f1_score(y_test, xgb_pred)
print("XGBoost 模型评估指标:")
print(f"准确率: {xgb_accuracy:.4f}")
print(f"精确率: {xgb_precision:.4f}")
print(f"召回率: {xgb_recall:.4f}")
print(f"F1 值: {xgb_f1:.4f}")

model_metrics.append({
    '模型名称': 'XGBoost',
    '准确率': round(xgb_accuracy, 4),
    '精确率': round(xgb_precision, 4),
    '召回率': round(xgb_recall, 4),
    'F1分数': round(xgb_f1, 4)
})


# LightGBM
lgb_model = lgb.LGBMClassifier(random_state=42)
lgb_model.fit(X_train, y_train)
lgb_pred = lgb_model.predict(X_test)

print("\nLightGBM 分类报告:")
print(classification_report(y_test, lgb_pred))
print("LightGBM 混淆矩阵:")
print(confusion_matrix(y_test, lgb_pred))

lgb_accuracy = accuracy_score(y_test, lgb_pred)
lgb_precision = precision_score(y_test, lgb_pred)
lgb_recall = recall_score(y_test, lgb_pred)
lgb_f1 = f1_score(y_test, lgb_pred)
print("LightGBM 模型评估指标:")
print(f"准确率: {lgb_accuracy:.4f}")
print(f"精确率: {lgb_precision:.4f}")
print(f"召回率: {lgb_recall:.4f}")
print(f"F1 值: {lgb_f1:.4f}")

model_metrics.append({
    '模型名称': 'LightGBM',
    '准确率': round(lgb_accuracy, 4),
    '精确率': round(lgb_precision, 4),
    '召回率': round(lgb_recall, 4),
    'F1分数': round(lgb_f1, 4)
})

就是一个纯套公式,然后把每个模型都训练一遍,通过指标来判断用哪个模型最好

SVM 分类报告:
              precision    recall  f1-score   support

           0       0.81      0.79      0.80        28
           1       0.82      0.85      0.84        33

    accuracy                           0.82        61
   macro avg       0.82      0.82      0.82        61
weighted avg       0.82      0.82      0.82        61

SVM 混淆矩阵:
[[22  6]
 [ 5 28]]
SVM 模型评估指标:
准确率: 0.8197
精确率: 0.8235
召回率: 0.8485
F1 值: 0.8358

KNN 分类报告:
              precision    recall  f1-score   support

           0       0.67      0.57      0.62        28
           1       0.68      0.76      0.71        33

    accuracy                           0.67        61
   macro avg       0.67      0.66      0.66        61
weighted avg       0.67      0.67      0.67        61

KNN 混淆矩阵:
[[16 12]
 [ 8 25]]
KNN 模型评估指标:
准确率: 0.6721
精确率: 0.6757
召回率: 0.7576
F1 值: 0.7143

逻辑回归 分类报告:
              precision    recall  f1-score   support

           0       0.88      0.82      0.85        28
           1       0.86      0.91      0.88        33

    accuracy                           0.87        61
   macro avg       0.87      0.87      0.87        61
weighted avg       0.87      0.87      0.87        61

逻辑回归 混淆矩阵:
[[23  5]
 [ 3 30]]
逻辑回归 模型评估指标:
准确率: 0.8689
精确率: 0.8571
召回率: 0.9091
F1 值: 0.8824

朴素贝叶斯 分类报告:
              precision    recall  f1-score   support

           0       0.88      0.75      0.81        28
           1       0.81      0.91      0.86        33

    accuracy                           0.84        61
   macro avg       0.84      0.83      0.83        61
weighted avg       0.84      0.84      0.83        61

朴素贝叶斯 混淆矩阵:
[[21  7]
 [ 3 30]]
朴素贝叶斯 模型评估指标:
准确率: 0.8361
精确率: 0.8108
召回率: 0.9091
F1 值: 0.8571

随机森林 分类报告:
              precision    recall  f1-score   support

           0       0.83      0.68      0.75        28
           1       0.76      0.88      0.82        33

    accuracy                           0.79        61
   macro avg       0.79      0.78      0.78        61
weighted avg       0.79      0.79      0.78        61

随机森林 混淆矩阵:
[[19  9]
 [ 4 29]]
随机森林 模型评估指标:
准确率: 0.7869
精确率: 0.7632
召回率: 0.8788
F1 值: 0.8169

XGBoost 分类报告:
              precision    recall  f1-score   support

           0       0.71      0.54      0.61        28
           1       0.68      0.82      0.74        33

    accuracy                           0.69        61
   macro avg       0.69      0.68      0.68        61
weighted avg       0.69      0.69      0.68        61

XGBoost 混淆矩阵:
[[15 13]
 [ 6 27]]
XGBoost 模型评估指标:
准确率: 0.6885
精确率: 0.6750
召回率: 0.8182
F1 值: 0.7397
[LightGBM] [Info] Number of positive: 132, number of negative: 110
[LightGBM] [Info] Auto-choosing row-wise multi-threading, the overhead of testing was 0.000088 seconds.
You can set `force_row_wise=true` to remove the overhead.
And if memory is not enough, you can set `force_col_wise=true`.
[LightGBM] [Info] Total Bins 447
[LightGBM] [Info] Number of data points in the train set: 242, number of used features: 20
[LightGBM] [Info] [binary:BoostFromScore]: pavg=0.545455 -> initscore=0.182322
[LightGBM] [Info] Start training from score 0.182322
[LightGBM] [Warning] No further splits with positive gain, best gain: -inf
#这边出现了很多警告,可能是因为数据集太少,不适合lgbm的原因,或者是默认参数不合适的原因

LightGBM 分类报告:
              precision    recall  f1-score   support

           0       0.76      0.68      0.72        28
           1       0.75      0.82      0.78        33

    accuracy                           0.75        61
   macro avg       0.76      0.75      0.75        61
weighted avg       0.75      0.75      0.75        61

LightGBM 混淆矩阵:
[[19  9]
 [ 6 27]]
LightGBM 模型评估指标:
准确率: 0.7541
精确率: 0.7500
召回率: 0.8182
F1 值: 0.7826

所有模型评估指标汇总表:
+----+------------+----------+----------+----------+----------+
|    |  模型名称  |   准确率 |   精确率 |   召回率 |   F1分数 |
+====+============+==========+==========+==========+==========+
|  0 |    SVM     |   0.8197 |   0.8235 |   0.8485 |   0.8358 |
+----+------------+----------+----------+----------+----------+
|  1 |    KNN     |   0.6721 |   0.6757 |   0.7576 |   0.7143 |
+----+------------+----------+----------+----------+----------+
|  2 |  逻辑回归  |   0.8689 |   0.8571 |   0.9091 |   0.8824 |
+----+------------+----------+----------+----------+----------+
|  3 | 朴素贝叶斯 |   0.8361 |   0.8108 |   0.9091 |   0.8571 |
+----+------------+----------+----------+----------+----------+
|  4 |  随机森林  |   0.7869 |   0.7632 |   0.8788 |   0.8169 |
+----+------------+----------+----------+----------+----------+
|  5 |  XGBoost   |   0.6885 |   0.6750 |   0.8182 |   0.7397 |
+----+------------+----------+----------+----------+----------+
|  6 |  LightGBM  |   0.7541 |   0.7500 |   0.8182 |   0.7826 |
+----+------------+----------+----------+----------+----------+

可以发现,SVM,逻辑回归,和朴素贝叶斯的表现都不错,逻辑回归表现最佳。但后续也可以考虑用这三个模型进行一个模型上的改进

!!!然后开始今天的学习,进行一个常见调参方式的了解与认识

知识点回顾

  1. 网格搜索(资源要求较高):核心原理是穷举指定参数空间的所有组合,暴力搜索最优解 适用场景 :参数数量少(<5个)、搜索空间小的模型调优。
  2. 随机搜索(简单介绍,非重点 实战中很少用到,可以不了解):在参数空间随机采样组合,效率高于网格搜索 实战价值:仅适用于参数间无交互的简单模型
  3. 贝叶斯优化(更经常使用,对资源要求没有那么高)(2种实现逻辑,以及如何避开必须用交叉验证的问题):  

     需要定义参数的搜索空间,与随机搜索类似,当搜索空间非常大时,它通常比网格搜索和随机搜索更有效。

    核心优势: 它不是随机选择下一个点,而是根据先前评估的结果建立一个概率模型(通常是高斯过程),预测哪些参数组合可能产生更好的结果,并据此选择下一个评估点。这使得它在寻找最优解方面通常比随机搜索更高效(用更少的迭代次数达到相似或更好的性能),特别是当模型训练(单次评估)非常耗时的时候。

  4. time库的计时模块,方便后人查看代码运行时长

划分数据集,需要划分两次。

通常,我们需要训练集来训练模型,验证集来调整超参数,测试集来评估最终性能。如果只划分一次,可能无法得到独立的验证集,导致模型在测试集上的表现过于乐观,因为超参数调整可能已经利用了测试集的信息,造成数据泄露。

然后,两次划分的好处在于保持了数据集的独立性。训练集用于模型学习,验证集用于超参数优化,测试集则模拟真实环境下的评估。这样可以更准确地估计模型在未见过的数据上的泛化能力。如果只划分一次,比如直接分成三部分,可能无法保证各集合的随机性和独立性,尤其是当数据分布不均匀时。

另外,“考2次”可能是指模型需要经过训练和验证两个阶段,验证集的存在可以帮助在不接触测试集的情况下调整模型,避免过拟合测试集


# 数据集的划分
from sklearn.model_selection import train_test_split
# 准备标签和特征
X = data_encoded.drop(TARGET_COLUMN, axis=1)
y = data_encoded[TARGET_COLUMN]
# 划分数据集
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.2, random_state=42)  # 80%训练集,20%临时集
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)  # 50%验证集,50%测试集
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: (242, 25)
y_train: (242,)
X_val: (30, 25)
y_val: (30,)
X_test: (31, 25)
y_test: (31,)

当前代码选择一次划分,本质是 用交叉验证的"隐式验证集"替代了手动划分的"显式验证集" ,在保证模型评估严谨性的同时简化了代码流程。这是工程实践中的常见权衡

所以还是采用一次划分的方法,8:2

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 

针对随机森林模型,进行的举例


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") # 忽略所有警告信息

# --- 1. 默认参数的随机森林 ---
# 评估基准模型,这里确实不需要验证集
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
import time # 这里介绍一个新的库,time库,主要用于时间相关的操作,因为调参需要很长时间,记录下会帮助后人知道大概的时长
start_time = time.time() # 记录开始时间
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))

# --- 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_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))

print("\n--- 2. 贝叶斯优化随机森林 (训练集 -> 测试集) ---")


from skopt import BayesSearchCV
from skopt.space import Integer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix


# 定义要搜索的参数空间
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折交叉验证,这个参数是必须的,不能设置为1,否则就是在训练集上做预测了
    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))
--- 1. 默认参数随机森林 (训练集 -> 测试集) ---
训练与预测耗时: 0.1243 秒

默认随机森林 在测试集上的分类报告:
              precision    recall  f1-score   support

           0       0.79      0.90      0.84        29
           1       0.89      0.78      0.83        32

    accuracy                           0.84        61
   macro avg       0.84      0.84      0.84        61
weighted avg       0.84      0.84      0.84        61

默认随机森林 在测试集上的混淆矩阵:
[[26  3]
 [ 7 25]]

--- 2. 网格搜索优化随机森林 (训练集 -> 测试集) ---
网格搜索耗时: 16.7035 秒
最佳参数:  {'max_depth': None, 'min_samples_leaf': 1, 'min_samples_split': 5, 'n_estimators': 200}

网格搜索优化后的随机森林 在测试集上的分类报告:
              precision    recall  f1-score   support

           0       0.81      0.90      0.85        29
           1       0.90      0.81      0.85        32

    accuracy                           0.85        61
   macro avg       0.85      0.85      0.85        61
weighted avg       0.86      0.85      0.85        61

网格搜索优化后的随机森林 在测试集上的混淆矩阵:
[[26  3]
 [ 6 26]]

--- 2. 贝叶斯优化随机森林 (训练集 -> 测试集) ---
贝叶斯优化耗时: 14.9996 秒
最佳参数:  OrderedDict([('max_depth', 24), ('min_samples_leaf', 1), ('min_samples_split', 2), ('n_estimators', 200)])

贝叶斯优化后的随机森林 在测试集上的分类报告:
              precision    recall  f1-score   support

           0       0.81      0.90      0.85        29
           1       0.90      0.81      0.85        32

    accuracy                           0.85        61
   macro avg       0.85      0.85      0.85        61
weighted avg       0.86      0.85      0.85        61

贝叶斯优化后的随机森林 在测试集上的混淆矩阵:
[[26  3]
 [ 6 26]]

贝叶斯优化和网格优化的结果一样,但是贝叶斯优化的耗时更少,效率更高

对前面效果最好的逻辑回归模型进行一下调参。在调参过程中发现出现难以收敛的问题,需要在数据预处理部分增添删除高共线性的特征

# 新增:共线性处理(医学数据关键步骤)
correlation_threshold = 0.8 
corr_matrix = data_encoded[continue_feature].corr().abs() 
upper = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool)) 
to_drop = [column for column in upper.columns if any(upper[column] > correlation_threshold)] 

if to_drop: 
    data_encoded = data_encoded.drop(to_drop, axis=1) 
    print(f'移除高共线性特征: {to_drop}') 
    # 更新特征列表 
    continue_feature = [f for f in continue_feature if f not in to_drop]
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from skopt import BayesSearchCV
from skopt.space import Real, Categorical
import time
import warnings
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score,roc_auc_score# 用于评估分类器性能的指标
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
warnings.filterwarnings("ignore")

# --- 1. 默认参数逻辑回归(基准模型)---
print("--- 1. 默认参数逻辑回归 (训练集 -> 测试集) ---")
start_time = time.time()
# 初始化模型:默认无正则化(C=1.0)、l2正则化、liblinear优化器
base_model = LogisticRegression(random_state=42)
# 在训练集上拟合模型
base_model.fit(X_train, y_train)
# 在测试集上预测
base_pred = base_model.predict(X_test)
end_time = time.time()

print(f"训练预测耗时: {end_time - start_time:.4f} 秒")
print("默认参数逻辑回归分类报告:")
print(classification_report(y_test, base_pred))
print("默认参数逻辑回归混淆矩阵:")
print(confusion_matrix(y_test, base_pred))

# --- 2. 网格搜索优化逻辑回归 --- 
print("\n--- 2. 网格搜索优化逻辑回归 ---")
# 2.1 定义参数网格
param_grid = {
    # 正则化强度倒数:值越小正则化越强,医学数据常用对数尺度搜索
    'C': [0.01, 0.1, 1, 10],
    # 正则化类型:l1(Lasso)产生稀疏解,l2(Ridge)保留更多特征
    'penalty': ['l2'],
    # 优化器:根据正则化类型选择兼容的求解器
    'solver': ['liblinear', 'saga'],
    # 最大迭代次数:确保收敛,医学数据特征多时需增加
    'max_iter': [1500, 2000]
}

# 2.2 创建网格搜索对象
# estimator: 基础模型
# param_grid: 待搜索参数空间
# cv: 交叉验证折数(5折=训练80%+验证20%)
# n_jobs: 并行计算核心数(-1=全部)
# scoring: 优化目标(医学数据常用roc_auc)
grid_search = GridSearchCV(
    estimator=LogisticRegression(random_state=42),
    param_grid=param_grid,
    cv=5,
    n_jobs=-1,
    scoring='roc_auc',
    verbose=1  # 输出搜索过程
)

# 2.3 执行网格搜索
start_time = time.time()
grid_search.fit(X_train, y_train)  # 内部自动进行交叉验证
end_time = time.time()

# 2.4 输出结果
print(f"网格搜索耗时: {end_time - start_time:.4f} 秒")
print(f"最佳参数组合: {grid_search.best_params_}")
print(f"交叉验证最佳AUC: {grid_search.best_score_:.4f}")

# 2.5 最佳模型评估
grid_model = grid_search.best_estimator_
grid_pred = grid_model.predict(X_test)
print("\n网格搜索优化后分类报告:")
print(classification_report(y_test, grid_pred))

# --- 3. 贝叶斯优化逻辑回归 --- 
print("\n--- 3. 贝叶斯优化逻辑回归 ---")
# 3.1 定义参数空间(支持连续/离散分布)
search_space = {
    # 连续参数:使用Real定义范围和分布
    'C': Real(0.01, 2.0, 'log-uniform'),  # 对数均匀分布搜索
    # 离散参数:使用Categorical定义候选值
    'penalty': Categorical(['l2']),
    'solver': Categorical(['liblinear', 'saga']),
    'max_iter': Categorical([100, 500, 1000])
}

# 3.2 创建贝叶斯搜索对象
# search_spaces: 参数空间定义
# n_iter: 采样迭代次数(医学数据建议30-50次)
# cv: 交叉验证折数
# scoring: 优化目标
# random_state: 随机种子确保可复现
bayes_search = BayesSearchCV(
    estimator=LogisticRegression(random_state=42),
    search_spaces=search_space,
    n_iter=30,
    cv=5,
    n_jobs=-1,
    scoring='roc_auc',
    random_state=42,
    verbose=1
)

# 3.3 执行贝叶斯优化
start_time = time.time()
bayes_search.fit(X_train, y_train)
end_time = time.time()

# 3.4 输出结果
print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print(f"最佳参数组合: {bayes_search.best_params_}")
print(f"交叉验证最佳AUC: {bayes_search.best_score_:.4f}")

# 3.5 最佳模型评估
bayes_model = bayes_search.best_estimator_
bayes_pred = bayes_model.predict(X_test)
print("\n贝叶斯优化后分类报告:")
print(classification_report(y_test, bayes_pred))

# --- 4. 调参前后性能对比 --- 
print("\n--- 调参方法对比 --- ")
print(f"默认模型测试集AUC: {roc_auc_score(y_test, base_model.predict_proba(X_test)[:,1]):.4f}")
print(f"网格搜索模型测试集AUC: {roc_auc_score(y_test, grid_model.predict_proba(X_test)[:,1]):.4f}")
print(f"贝叶斯优化模型测试集AUC: {roc_auc_score(y_test, bayes_model.predict_proba(X_test)[:,1]):.4f}")
--- 调参方法对比 ---
默认模型测试集AUC: 0.9246
网格搜索模型测试集AUC: 0.9375
贝叶斯优化模型测试集AUC: 0.9364

网格搜索耗时10秒,贝叶斯优化耗时38秒

还是有警告出现,这个后续再琢磨琢磨捏,不过大致掌握整个过程了。一些知识点有点忘了,奖励自己明天去看几遍视频。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值