4. 监督学习算法快速原型
在MATLAB机器学习工程中,快速原型阶段的核心目标不是追求最高精度,而是用最短路径验证“数据是否可分、特征是否有效、模型是否值得继续投入”。分类学习器App(Classification Learner)与fitcensemble、fitcsvm等函数,分别对应交互式探索与脚本化复现两条路径,二者配合可以显著缩短从数据到可用模型的周期。
一、分类学习器App:交互式快速筛选
分类学习器App适合在特征工程尚未完全定型时使用。启动方式为在命令行输入classificationLearner,或在“App”选项卡中点击“Classification Learner”。导入数据时,App会自动识别表变量类型,并要求指定响应变量(标签)与预测变量(特征)。对于本节示例,假设有一个fisheriris数据集,包含150个样本、4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)和3个类别(setosa、versicolor、virginica)。
在App中,选择“交叉验证”并设置折数(如5折),然后可同时勾选多种模型进行训练:决策树、K近邻、支持向量机、集成方法等。App会以列表形式给出每种模型的验证准确率,并允许点击任一模型查看其混淆矩阵。这一阶段的判断依据是:若多个模型准确率接近且均高于基线(如多数类占比),说明特征具有可分性;若所有模型都接近基线,则应回到特征工程而非继续调参。
二、脚本化训练:fitcsvm与fitcensemble
当需要复现、调参或嵌入工程流程时,应使用函数式接口。以二分类SVM为例,fitcsvm的基本调用形式为:
load fisheriris
X = meas(1:100,:); % 取前两类,共100个样本
Y = species(1:100);
Mdl = fitcsvm(X, Y, ...
'KernelFunction', 'rbf', ...
'BoxConstraint', 1, ...
'Standardize', true);
CVMdl = crossval(Mdl, 'KFold', 5);
loss = kfoldLoss(CVMdl);
其中KernelFunction选择核函数,BoxConstraint控制惩罚强度,Standardize对特征标准化。训练后可用predict获得预测标签,用confusionmat计算混淆矩阵。对于多分类问题,fitcsvm默认采用“一对多”策略,也可通过fitcecoc使用纠错输出码。
集成方法fitcensemble则通过组合多个弱学习器提升泛化能力。常用调用为:
Mdl = fitcensemble(X, Y, ...
'Method', 'AdaBoostM2', ...
'NumLearningCycles', 100, ...
'Learners', 'tree');
其中Method可选'AdaBoostM2'、'Bag'、'RUSBoost'等,NumLearningCycles为学习器数量,Learners指定基学习器类型。集成模型通常比单模型更稳健,但训练时间更长,且可解释性下降。
三、准确率与混淆矩阵:从数字到判断
准确率(Accuracy)是最直观的指标,定义为正确预测样本数除以总样本数。但在类别不平衡时,准确率可能产生误导。例如,若90%样本属于A类,模型全部预测为A,准确率仍达90%,但B类完全漏判。因此必须结合混淆矩阵分析。
混淆矩阵的行表示真实类别,列表示预测类别。以三分类为例,矩阵对角线为正确分类数,非对角线为误分类数。由此可计算:
- 召回率(Recall):某类真实样本中被正确预测的比例,反映“漏判”程度;
- 精确率(Precision):某类预测结果中真实属于该类的比例,反映“误报”程度;
- F1分数:精确率与召回率的调和平均,适合不平衡数据。
在MATLAB中,confusionchart可直接绘制带颜色映射的混淆矩阵,并显示每类的召回率与精确率。例如:
YPred = predict(Mdl, X);
figure;
cm = confusionchart(Y, YPred);
cm.Title = 'SVM分类混淆矩阵';
cm.RowSummary = 'row-normalized';
cm.ColumnSummary = 'column-normalized';
观察混淆矩阵时,应重点关注:对角线是否显著高于非对角线;是否存在某一类被系统性误判为另一类;误判是否集中在特征空间重叠区域。若某两类互相误判严重,说明现有特征不足以区分它们,需要引入新特征或非线性变换。
四、从原型到可复现:导出与封装
分类学习器App支持将训练好的模型导出到工作区,或生成等效的MATLAB函数。导出后,可用saveLearnerForCoder保存模型,用loadLearnerForCoder加载,便于部署。对于fitcensemble和fitcsvm,建议将训练脚本封装为函数,输入为特征矩阵和标签向量,输出为模型对象和评估指标,便于批量实验。
一个实用的原型脚本结构如下:
function [mdl, acc, cm] = trainAndEval(X, Y, method)
% method: 'svm' 或 'ensemble'
if strcmp(method, 'svm')
mdl = fitcsvm(X, Y, 'KernelFunction', 'rbf', ...
'Standardize', true, 'BoxConstraint', 1);
else
mdl = fitcensemble(X, Y, 'Method', 'AdaBoostM2', ...
'NumLearningCycles', 100, 'Learners', 'tree');
end
cvmdl = crossval(mdl, 'KFold', 5);
acc = 1 - kfoldLoss(cvmdl);
YPred = predict(mdl, X);
cm = confusionmat(Y, YPred);
end
该脚本返回交叉验证准确率与训练集混淆矩阵。注意:训练集混淆矩阵仅用于诊断模型是否过拟合,最终评估应以交叉验证或独立测试集为准。
五、参数选择与快速调参建议
对于fitcsvm,关键参数包括BoxConstraint(越大越严格,易过拟合)、KernelScale(RBF核宽度,越小越平滑)和Standardize(建议开启)。可用fitcsvm的自动优化选项'OptimizeHyperparameters'进行贝叶斯优化,但原型阶段建议先手动尝试2~3组参数。
对于fitcensemble,NumLearningCycles通常设为50~200,LearnRate(AdaBoost)设为0.1~1,MaxNumSplits控制基树深度。若数据类别不平衡,优先使用'RUSBoost'方法,它通过欠采样平衡类别。
快速原型的判断标准可以归纳为:交叉验证准确率是否显著高于多数类基线;混淆矩阵对角线是否占主导;误判是否集中在可解释的类别对之间。若满足前两条,即可进入下一阶段;若不满足,应优先检查特征质量与类别可分性,而非盲目增加模型复杂度。