自动机器学习pycaret 处理分类简单用法

引入分类模型库

复制代码
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.indexdata 的索引号(即被抽中样本在原数据集中的位置)

  • 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),用于追踪此次实验

🔍 关键发现

  1. 数据拆分比例 :你之前用 sample(frac=0.75) 抽取了 75%(576行)作为训练集,但 PyCaret 的 setup() 又自动按 70%/30% 拆分了训练集内部的数据:

    • 训练集:403 行(576 × 70%)

    • 验证集/测试集:173 行(576 × 30%)

    也就是说,data 本身就是你从原始数据中取的 75%,现在 PyCaret 又把它拆成了 70%/30%,用于训练过程中的验证。

  2. 你的数据应该是二分类问题 :目标变量 Class variable 只有两个取值。

  3. 预处理已自动启用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 的 RandomizedSearchCVGridSearchCV

    • "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[打印调优结果汇总]

具体步骤:

  1. 确定搜索空间:PyCaret 为每个模型预定义了要调优的超参数范围

    • 例如 Ridge Classifier 会调优:alphasolvertol
  2. 随机采样 :在参数空间中随机抽取 10 组(默认 n_iter=10)参数组合

  3. 交叉验证评估:对每组参数,在训练集上执行 10 折交叉验证

  4. 选择最佳:找到使验证得分最高的参数组合

  5. 重新训练 :用找到的最佳参数在整个训练集上重新训练模型

  6. 返回调优模型:返回调优后的模型对象

更多参数示例

复制代码
# 增加随机搜索的迭代次数(更充分但更慢)
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("✅ 模型泛化良好!")