引入分类模型库
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
from pycaret.classification import *
数据集拆分
dataset = pd.read_csv(r"D:\Work\PycharmProjects\jupyter\pycaret\diabetes.csv")
data = dataset.sample(frac=0.75, random_state=42)
data_unseen = dataset.drop(data.index)
data.reset_index(inplace=True, drop=True)
data_unseen.reset_index(inplace=True, drop=True)
代码的核心目的是将数据集拆分为训练集和测试集(留出集),并对索引进行重置整理
第1行:data = dataset.sample(frac=0.75, random_state=42)
这行代码从 dataset 中随机抽取 75% 的样本 ,作为训练数据(通常命名为 data)。
-
frac=0.75:抽取 75% 的行 -
random_state=42:设置随机种子,保证每次运行代码时抽取的结果都一样(可复现)
第2行:data_unseen = dataset.drop(data.index)
这行代码从原始 dataset 中删除 data 中已有的行 ,剩下的就是没有被抽中的那 25% ,赋值给 data_unseen。
-
data.index是data的索引号(即被抽中样本在原数据集中的位置) -
drop(data.index)删除这些索引对应的行 -
剩下的 25% 数据就作为测试集/留出集,用于模型最终评估
第3行:data.reset_index(inplace=True, drop=True)
重置 data 的索引,让索引变成 0, 1, 2, 3, ... 的连续整数。
-
inplace=True:直接在原 DataFrame 上修改,不返回新对象 -
drop=True:丢弃旧的索引列,不将其保存为新的数据列
为什么要这样做? 因为 data 是从 dataset 中抽取的样本,它的索引是原数据集中的位置编号(比如 5, 12, 33, ...),不是从 0 开始的连续编号。重置索引可以让后续操作(如遍历、拼接)更方便。
第4行:data_unseen.reset_index(inplace=True, drop=True)
对 data_unseen 做同样的索引重置操作,原因同上。
env_setup = setup(data=data, target='Class variable', session_id=42)
setup() 是 PyCaret 的"启动器"------它接收你的数据,配置预处理管道,划分训练/测试集,建立交叉验证策略,为后续的所有建模工作做好准备。
后台操作
flowchart TD
A[开始: setup()] --> B[接收 data 和 target]
B --> C[自动检测特征类型<br>数值/类别/日期/文本]
C --> D[分离特征 X 和目标 y]
D --> E[划分训练集和测试集<br>默认 70%/30%]
E --> F[配置 10 折交叉验证<br>StratifiedKFold]
F --> G[建立预处理管道<br>缺失值填充/编码/标准化等]
G --> H[存储所有配置到环境中]
H --> I[返回配置信息汇总表]
I --> J[准备好接收模型训练命令]
返回值分析
Description Value
0 Session id 42
1 Target Class variable
2 Target type Binary
3 Original data shape (576, 9)
4 Transformed data shape (576, 9)
5 Transformed train set shape (403, 9)
6 Transformed test set shape (173, 9)
7 Numeric features 8
8 Preprocess True
9 Imputation type simple
10 Numeric imputation mean
11 Categorical imputation mode
12 Fold Generator StratifiedKFold
13 Fold Number 10
14 CPU Jobs -1
15 Use GPU False
16 Log Experiment False
17 Experiment Name clf-default-name
18 USI a95b
📊 整体概览
| 序号 | 描述 | 值 | 含义 |
|---|---|---|---|
| 0 | Session id | 42 | 会话ID,你设置的 session_id=42 作为随机种子,确保结果可复现 |
| 1 | Target | Class variable | 目标变量(标签列),你要预测的字段名 |
| 2 | Target type | Binary | 目标变量是二分类问题(比如 0/1,是/否) |
| 3 | Original data shape | (576, 9) | 原始数据:576行 × 9列(8个特征 + 1个目标变量) |
| 4 | Transformed data shape | (576, 9) | 经过预处理后的数据形状不变(因为目前没有做变换) |
| 5 | Transformed train set shape | (403, 9) | 训练集:403行(占 576 的 70%) |
| 6 | Transformed test set shape | (173, 9) | 测试集:173行(占 576 的 30%) |
| 7 | Numeric features | 8 | 数值型特征有 8 个(目标变量不算在内) |
⚙️ 预处理配置
| 序号 | 描述 | 值 | 含义 |
|---|---|---|---|
| 8 | Preprocess | True | 启用了自动预处理(PyCaret 默认帮你做缺失值填充、编码等) |
| 9 | Imputation type | simple | 缺失值填充方式为"简单填充" |
| 10 | Numeric imputation | mean | 数值型特征的缺失值用均值填充 |
| 11 | Categorical imputation | mode | 类别型特征的缺失值用众数填充 |
🔄 交叉验证配置
| 序号 | 描述 | 值 | 含义 |
|---|---|---|---|
| 12 | Fold Generator | StratifiedKFold | 使用分层K折交叉验证(保持类别比例) |
| 13 | Fold Number | 10 | 10折交叉验证 |
| 14 | CPU Jobs | -1 | 使用所有可用的 CPU 核心(-1 表示全部) |
| 15 | Use GPU | False | 未使用 GPU 加速 |
📝 实验记录
| 序号 | 描述 | 值 | 含义 |
|---|---|---|---|
| 16 | Log Experiment | False | 不自动记录实验日志 |
| 17 | Experiment Name | clf-default-name | 实验默认名称(clf = classification) |
| 18 | USI | a95b | 唯一的会话标识符(Unique Session ID),用于追踪此次实验 |
🔍 关键发现
-
数据拆分比例 :你之前用
sample(frac=0.75)抽取了 75%(576行)作为训练集,但 PyCaret 的setup()又自动按 70%/30% 拆分了训练集内部的数据:-
训练集:403 行(576 × 70%)
-
验证集/测试集:173 行(576 × 30%)
也就是说,
data本身就是你从原始数据中取的 75%,现在 PyCaret 又把它拆成了 70%/30%,用于训练过程中的验证。 -
-
你的数据应该是二分类问题 :目标变量
Class variable只有两个取值。 -
预处理已自动启用 :
Preprocess=True意味着 PyCaret 会自动处理缺失值、编码类别变量等。best_model = compare_models()这行代码
best_model = compare_models()是 PyCaret 中最核心、最强大的功能之一。它的作用是自动训练和评估多个机器学习模型,并返回性能最好的那一个best_models = compare_models( include=['rf', 'dt', 'xgboost', 'lightgbm'], turbo=False, sort='AUC', n_select=3 )tuned_model = tune_model(best_model, search_library="scikit-learn", search_algorithm="random")
tune_model() 通过随机搜索算法,在指定的参数空间中寻找使模型表现最好的超参数组合,并返回调优后的模型。
📊 参数详解
1️⃣ best_model
-
含义:要调优的模型对象
-
说明 :这是你之前通过
compare_models()获得的最佳模型(在你的例子中是 Ridge Classifier) -
注意 :这里传入的是模型对象,不是模型名称字符串
2️⃣ search_library="scikit-learn"
-
含义 :指定使用哪个库的搜索算法
-
参数值:
-
"scikit-learn"(默认):使用 sklearn 的RandomizedSearchCV或GridSearchCV -
"optuna":使用 Optuna 库(更高效的贝叶斯优化),需先pip install optuna -
"scikit-optimize":使用 skopt 库,需先pip install scikit-optimize
-
-
你的情况:使用 scikit-learn 的随机搜索
3️⃣ search_algorithm="random"
-
含义:指定搜索策略/算法
-
参数值 (当
search_library="scikit-learn"时):-
"random":随机搜索(RandomizedSearchCV),在参数空间中随机采样组合 -
"grid":网格搜索(GridSearchCV),穷举所有参数组合(更精确但更慢)
-
后台操作
flowchart TD
A[开始: tune_model] --> B[读取 best_model 的参数空间]
B --> C[定义要搜索的超参数范围]
C --> D[使用 scikit-learn 的 RandomizedSearchCV]
D --> E[在训练集上执行 10 折交叉验证]
E --> F[随机采样 N 组参数组合<br>默认 10 组]
F --> G[对每组参数计算交叉验证平均得分]
G --> H[找到得分最高的参数组合]
H --> I[用最佳参数重新训练模型]
I --> J[返回调优后的模型对象]
J --> K[打印调优结果汇总]
具体步骤:
-
确定搜索空间:PyCaret 为每个模型预定义了要调优的超参数范围
- 例如 Ridge Classifier 会调优:
alpha、solver、tol等
- 例如 Ridge Classifier 会调优:
-
随机采样 :在参数空间中随机抽取 10 组(默认
n_iter=10)参数组合 -
交叉验证评估:对每组参数,在训练集上执行 10 折交叉验证
-
选择最佳:找到使验证得分最高的参数组合
-
重新训练 :用找到的最佳参数在整个训练集上重新训练模型
-
返回调优模型:返回调优后的模型对象
更多参数示例
# 增加随机搜索的迭代次数(更充分但更慢)
tuned_model = tune_model(
best_model,
search_library="scikit-learn",
search_algorithm="random",
n_iter=30, # 随机采样 30 组,默认 10
optimize='AUC', # 按 AUC 优化,默认 Accuracy
fold=5, # 使用 5 折交叉验证,默认 10
choose_better=True # 自动比较调优前后,保留更好的
)
best_auc_model = automl(optimize="AUC")
automl() 函数自动运行模型选择、超参数调优、特征工程等过程,返回在指定优化指标(这里是 AUC)上表现最优的最终模型。
unseen_predictions = predict_model(tuned_model, data=data_unseen)
使用调优后的模型(tuned_model)对留出集(data_unseen)进行预测,返回包含原始数据和预测结果的 DataFrame。
save_model(tuned_model, "Final_Model")
load_saved_model = load_model("Final_Model")
保存模型和加载模型
简单完整流程
# 1. 初始化
env_setup = setup(data=data, target='Class variable', session_id=42)
# 2. 模型选择和调优
best_model = compare_models()
tuned_model = tune_model(best_model, search_library="scikit-learn", search_algorithm="random")
# 3. 预测前查看模型信息
print(tuned_model)
# 4. 在留出集上预测
unseen_predictions = predict_model(tuned_model, data=data_unseen)
# 5. 分析预测结果
print("\n=== 预测结果概览 ===")
print(unseen_predictions[['Class variable', 'prediction_label', 'prediction_score']].head())
# 6. 计算最终指标
from sklearn.metrics import roc_auc_score, accuracy_score, f1_score
auc = roc_auc_score(
unseen_predictions['Class variable'],
unseen_predictions['prediction_score']
)
acc = accuracy_score(
unseen_predictions['Class variable'],
unseen_predictions['prediction_label']
)
f1 = f1_score(
unseen_predictions['Class variable'],
unseen_predictions['prediction_label']
)
print(f"\n=== 最终评估结果 ===")
print(f"准确率: {acc:.4f}")
print(f"AUC: {auc:.4f}")
print(f"F1分数: {f1:.4f}")
# 7. 对比交叉验证结果
print(f"\n交叉验证 AUC: 0.7924")
print(f"留出集 AUC: {auc:.4f}")
if auc < 0.7924 - 0.05:
print("⚠️ 警告:可能存在过拟合!")
else:
print("✅ 模型泛化良好!")