Closed ixxmu closed 2 years ago
与其他开源机器学习库相比,PyCaret 库只需几行代码即可执行复杂的机器学习任务,方便我们高效地执行迭代实验,更快地得出结论。PyCaret 有点类似于 R 里的 Caret 包,但要更为简单。
一般情况下,如果不使用 PyCaret,从数据预处理、执行特征工程,建模到调参,我们构建一个机器学习模型需要至少 100 行代码,而这些步骤在 PyCaret 中只需不到 10 行,同时这些命令都非常直观易记,例如:
# 预设流程参数
setup()
# 比较不同算法
compare_models()
# 建立模型
create_model()
# 调参
tune_model()
# 模型可视化
plot_model()
# 用模型预测
predict_model()
# 保存/载入模型
save_model()
load_model()
从本质上来看,PyCaret 是一个 Python 库,封装了多个机器学习库和框架,如 sci-kit-learn、XGBoost、Microsoft LightGBM、spaCy 等等。包括 6 个模块,支持有监督和无监督模型的训练和部署,分别是分类、回归、聚类、异常检测、自然语言处理和关联规则挖掘。每个模块封装特定的机器学习算法和不同模块均可以使用的函数。用户可以根据实验类型,将模块导入环境中。
•GitHub 地址:https://github.com/pycaret/pycaret•官网:https://www.pycaret.org•教程:https://www.pycaret.org/tutorial
为了避免与其他包的冲突,这里强烈建议使用 conda 创建虚拟环境。
# 创建 conda 环境
conda create --name pycaret python=3.8
# 激活 conda 环境
conda activate pycaret
# 安装完整版 pycaret
pip install pycaret[full]
# 将 conda 环境载入 jupyter notebook
python -m ipykernel install --user --name pycaret --display-name "pycaret-2.3.5"
以下模型支持使用 GPU 进行模型训练和超参数选择:
•XGBoost•CatBoost•LightGBM(需额外安装 GPU 版本:https://lightgbm.readthedocs.io/en/latest/GPU-Tutorial.html)•Logistic Regression, Ridge Classifier, Random Forest, K Neighbors Classifier, K Neighbors Regressor, Support Vector Machine, Linear Regression, Ridge Regression, Lasso Regression (需 cuML >= 0.15 https://github.com/rapidsai/cuml)
PyCaret 的分类模块 (pycaret.classification
) 是一个有监督的机器学习模块,用于二分类和多分类问题。支持超过 18 种算法以及 14 种图形以分析模型性能。无论是基本的超参数调优,还是像模型集成这种高阶玩法,都可用此模块实现。
我们将使用来自 UCI 的 Default of Credit Card Clients Dataset 数据集。该数据集包含自 2005 年 4 月至 2005 年 9 月台湾信用卡客户的违约付款、人口统计因素、信用数据、付款历史和帐单等信息,包括 24,000 个样本和 25 个特征。每列的描述信息如下:
•ID:每个客户端的ID•LIMIT_BAL:以新台币计的信用额度•SEX:性别(1=男性,2=女性)•EDUCATION:(1=研究生,2=大学,3=高中,4=其他,5=未知,6=未知)•MARRIAGE:婚姻状况(1=已婚,2=单身,3=其他)•AGE:年龄•PAY_0 到 PAY_6:n 个月前的还款状态(PAY_0 = 上个月 .. PAY_6 = 6 个月前)(标签:-1=按时付款,1=延迟付款一个月,2=延迟付款两个月,. .. 8=付款延迟八个月,9=付款延迟九个月及以上)•BILL_AMT1 到 BILL_AMT6:n 个月前的账单金额(BILL_AMT1 = 上个月 .. BILL_AMT6 = 6 个月前)•PAY_AMT1 到 PAY_AMT6:n 个月前的付款金额(BILL_AMT1 = 上个月 .. BILL_AMT6 = 6 个月前)•默认值:默认付款(1=是,0=否)此为目标列
使用 PyCaret 的数据存储库自带的 get_data()
函数加载数据:
from pycaret.datasets import get_data
dataset = get_data('credit')
# 检查数据维度
dataset.shape
为了在独立验证集中演示 predict_model()
函数,我们将从原始数据集中拆分出 1200 条记录,这些数据将不用于建模。
data = dataset.sample(frac=0.95, random_state=786)
data_unseen = dataset.drop(data.index)
data.reset_index(inplace=True, drop=True)
data_unseen.reset_index(inplace=True, drop=True)
print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))
Data for Modeling: (22800, 24)
Unseen Data For Predictions: (1200, 24)
在执行 PyCaret 其他步骤之前,我们必须执行setup()
函数,这一步这将初始化 PyCaret 中的环境参数并创建数据预处理流程。这里需要两个必填的参数:一个 pandas 数据框和目标列的名称。
执行 setup()
时,PyCaret 将根据某些属性自动推断所有特征的数据类型,是连续性变量还是分类变量。一般情况下都不会出太大问题,当推断的有出入时,我们可以用 numeric_features
和 categorical_features
参数覆盖 PyCaret 的推断数据类型。如果所有的数据类型都被正确识别,可以直接按 Enter 键继续或键入 quit 结束实验。
from pycaret.classification import *
exp_clf101 = setup(data = data, target = 'default', session_id=123)
...
成功执行 setup()
后,会输出一个表格,其中的大多数信息与执行 setup()
时构建的预处理流程相关。需要额外注意的一些重要信息包括:
•session_id :随机数种子,方便后续的结果复现。•Target Type :二分类或多分类。目标类型会自动检测并显示。•Label Encoded :当目标变量是字符串类型(即“是”或“否”)而不是 1 或 0 时,它会自动将标签编码为 1 和 0 并显示映射(0:否,1:是)。在这个实验中,不需要进行标签编码,因为目标变量本身就是数字。•Original Data :显示数据集的原始形状。示例中的 (22800, 24) 表示有 22,800 个样本和 24 个特征,包含目标列。•Missing Values :当原始数据中存在缺失值时,这将显示为 True。本示例无缺失值。•Numeric Features :推断为数字的特征数量。本示例中的 24 个特征中有 14 个被推断为数字特征。•Categorical Features :推断为分类特征的数量。本示例中的 24 个特征中有 9 个被推断为分类特征。•Transformed Train Set :显示转换后的训练集形状。经过预处理,我们将训练集从 (22800, 24) 转换为 (15959, 91),并且由于存在分类编码,特征数量从 24 个增加到 91 个。•Transformed Test Set :显示转换后的测试集形状。经过预处理,测试集中将包含 6841 个样本。此拆分基于默认值 70/30,可以使用 setup()
中的 train_size
参数更改。
建议大家阅读 PyCaret 文档以了解这些步骤在 PyCaret 中具体是如何自动处理的,例如缺失值插补、分类变量编码等等,同时了解其他可选参数。
下一步我们将把所有能用的模型都跑一遍(使用默认超参数),看看哪些模型更适用于我们的数据集,这里输出的表格内容包括不同模型的(10 折交叉验证)平均 Accuracy, AUC, Recall, Precision, F1, Kappa, MCC 以及对应的训练时间。
best_model = compare_models()
用这简单的一行代码我们就已经完成用交叉验证训练和评估超过 15 种算法。输出的表格默认使用“Accuracy”从高到低进行排序,我们也可以修改参数以基于其他参数进行排序, 例如 compare_models(sort = 'Recall')
将按 Recall 进行排序。如果要将 fold
从默认的 10 更改为其他值,则可以使用 fold
参数。例如 compare_models(fold = 5)
将在 5 折交叉验证的基础上比较所有模型,减少训练时间。
print(best_model)
RidgeClassifier(alpha=1.0, class_weight=None, copy_X=True, fit_intercept=True,
max_iter=None, normalize=False, random_state=123, solver='auto',
tol=0.001)
默认情况下,compare_models
仅返回性能最佳的模型,我们可使用 n_select
参数返回前 N 个模型的列表。
PyCaret 的模型库中有 18 个分类器可用。
models()
下面,我们将以随机森林模型为例进行演示(这里仅作示例,随机森林并非最佳模型)。
rf = create_model('rf')
可使用 print
输出模型参数:
print(rf)
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
criterion='gini', max_depth=None, max_features='auto',
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=100,
n_jobs=-1, oob_score=False, random_state=123, verbose=0,
warm_start=False)
这里显示的模型平均分数与 compare_models()
中打印的分数相一致。这是因为在 compare_models()
表格中输出的指标是所有 CV folds 的平均得分。与 compare_models()
类似,如果要将 fold 从默认值 10 更改为不同的值,则可以使用 fold
参数。例如:create_model('dt', fold = 5)
将使用 5 折 CV 创建决策树分类器。
当我们用 create_model()
函数创建模型时,算法只是调用默认的超参数来训练模型。所以为了进一步优化模型,我们将使用 tune_model()
函数进行超参数调优。此函数使用随机网格搜索在预设的搜索空间上自动调整模型的超参数,我们也可用 custom_grid
参数自定义网格。
tuned_rf = tune_model(rf)
默认情况下,tune_model
将基于 Accuracy
进行优化,这里同样可以使用 optimize
参数进行更改。例如: tune_model(dt, optimize = 'AUC')
将基于 AUC 排序。这里出于示例,我们仅用默认的 Accuracy
进行演示,但需要注意的是,尤其当数据集不平衡时(例如我们正在使用的这个数据集),Accuracy
并不是一个比较好的指标,关于此话题可以阅读这一篇文章[1] 以进一步了解。
在最终确定最佳的机器学习模型时,这些评判指标并不应该是我们唯一需要考虑的标准,其他要考虑的因素也包括训练时间、交叉验证的标准差等等。
plot_model()
函数可用于分析模型不同方面的性能,例如 AUC、混淆矩阵、决策边界等。PyCaret 支持 15 种图的绘制。
plot_model(tuned_rf, plot = 'auc')
plot_model(tuned_rf, plot = 'pr')
plot_model(tuned_rf, plot='feature')
plot_model(tuned_rf, plot = 'confusion_matrix')
分析模型性能的另一种方法是使用 evaluate_model()
函数,该函数显示给定模型的所有可用图的交互界面。
evaluate_model(tuned_rf)
在最终确定模型之前,我们还需要通过测试集来进一步评估模型性能。下面,我们将使用存储于 tune_rf
变量中的最终模型,基于(30% 的样本)测试集进行预测并评估指标,以查看它们是否与交叉验证的结果存在显著差异。
predict_model(tuned_rf)
可以看到在测试集中随机森林模型的 accuracy 为 0.8116,十折交叉验证结果为 0.8203,这里的结果比较接近,如果测试集中的结果和交叉验证的结果之间存在很大差异,则这说明我们的模型可能存在过拟合。下一步,我们将继续完善模型并基于独立验证集进行测试(我们在开始时就分割出的 5% 数据)。
这是建模的最后一步,完善最终模型,finalize_model()
函数将模型拟合到完整的数据集上,包括测试集中的样本。
final_rf = finalize_model(tuned_rf)
#Final Random Forest model parameters for deployment
print(final_rf)
RandomForestClassifier(bootstrap=False, ccp_alpha=0.0, class_weight={},
criterion='entropy', max_depth=5, max_features=1.0,
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0002, min_impurity_split=None,
min_samples_leaf=5, min_samples_split=10,
min_weight_fraction_leaf=0.0, n_estimators=150,
n_jobs=-1, oob_score=False, random_state=123, verbose=0,
warm_start=False)
最后我们将使用 predict_model()
函数基于独立验证集进行预测。
unseen_predictions = predict_model(final_rf, data=data_unseen)
unseen_predictions.head()
输出的矩阵包括了 Label
和 Score
两列,其中 Label
是预测值,Score
是预测的概率。
我们可基于这个矩阵进一步判断模型性能,这里需要用到 pycaret.utils
模块:
from pycaret.utils import check_metric
check_metric(unseen_predictions['default'], unseen_predictions['Label'], metric = 'Accuracy')
0.8167
现在我们已经完成了机器学习建模,最后一步我们将使用 save_model()
保存这个模型。
save_model(final_rf,'Final RF Model 11Nov2020')
Transformation Pipeline and Model Succesfully Saved
(Pipeline(memory=None,
steps=[('dtypes',
DataTypes_Auto_infer(categorical_features=[],
display_types=True, features_todrop=[],
id_columns=[],
ml_usecase='classification',
numerical_features=[], target='default',
time_features=[])),
('imputer',
Simple_Imputer(categorical_strategy='not_available',
fill_value_categorical=None,
fill_value_numerical=None,
numeric_stra...
RandomForestClassifier(bootstrap=False, ccp_alpha=0.0,
class_weight={}, criterion='entropy',
max_depth=5, max_features=1.0,
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0002,
min_impurity_split=None,
min_samples_leaf=5,
min_samples_split=10,
min_weight_fraction_leaf=0.0,
n_estimators=150, n_jobs=-1,
oob_score=False, random_state=123,
verbose=0, warm_start=False)]],
verbose=False), 'Final RF Model 11Nov2020.pkl')
小技巧:保存模型时最好在文件名中使用日期,方便版本控制。
使用 load_model()
函数可以载入模型。
saved_final_rf = load_model('Final RF Model 11Nov2020')
Transformation Pipeline and Model Successfully Loaded
加载模型后,我们同样可以使用 predict_model()
进行预测。
new_prediction = predict_model(saved_final_rf, data=data_unseen)
new_prediction.head()
from pycaret.utils import check_metric
check_metric(new_prediction['default'], new_prediction['Label'], metric = 'Accuracy')
0.8167
本教程几乎涵盖了整个机器学习建模过程,从数据获取、预处理、训练模型、超参数选择、模型预测到存储和载入模型。从此可以看出 PyCaret 的简单易用,除了上面例子中这样简单的建模之外,PyCaret 还支持更为高级的操作,例如集成模型。我个人更推荐已经有一定机器学习基础的同学使用,因为目前官方的文档和教程并不是特别完善,还需结合 sklearn 以及其他依赖库文档使用。
[1]
阅读这一篇文章: https://medium.com/@MohammedS/performance-metrics-for-classification-problems-in-machine-learning-part-i-b085d432082b
https://mp.weixin.qq.com/s/TxFMDROzS0Z33j6XxP4JjQ