尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

多分类模型上线后精准率暴跌,我重新推导混淆矩阵才发现“宏平均”坑了我

多分类模型上线后精准率暴跌,我重新推导混淆矩阵才发现“宏平均”坑了我 多分类模型上线后精准率暴跌,我重新推导混淆矩阵才发现“宏平均”坑了我去年年底,我主导的一个客户意图分类模型正式上线,9个类别,样本量从300到8000不等,训练集准确率0.91,测试集0.89,所有人都觉得稳了。第二天业务方直接拉群质问:“为什么第三类的精准率只有0.38?你们到底怎么评估的?”我点开混淆矩阵,看着类别3那一列高亮的红色--大量被误分成了4和7,而我在评估时只看了整体准确率,从没算过每个类别的精确率和召回率。当晚我就决定,把混淆矩阵、ROC、PR 曲线这些评估指标从头补课。同事扔给我一门 AWS 的深度学习课程,说里面专门有一节讲多分类评估,还带着动手实验分析不平衡数据,学了就能看懂为什么宏平均和微平均会打架。我原本觉得自己写了两年 PyTorch 不用学基础,结果这门深度学习课程用几节课就把我打回原形--原来评估体系选错,能把一个看起来 0.9 的模型搞到 0.4。如果你也遇到过“训练集高、上线崩”的诡异场面,这门深度学习课程正好能告诉你问题出在哪一环。业务打脸:一个准确率 0.91 的模型,怎么精准率就掉到 0.38上线前我们用的就是 sklearn 的classification_report,看了加权平均 F1 有 0.88,觉得 OK。但业务方要求每个类别的召回率不低于 0.7,特别强调类别3(高价值投诉类)不能漏。我重新跑报告才发现:from sklearn.metrics import classification_report print(classification_report(y_true, y_pred, target_namesclass_names))输出里类别3的 precision 0.38,recall 0.41,f1-score 0.39--惨不忍睹。翻出混淆矩阵一看,类别3的样本只有 300 条,模型压根没学会区分,大量分给了样本量 8000 的类别4。更坑的是,我之前的机器学习基础全靠看博客拼凑,不知道宏平均(macro average)会给小类同等权重,而整体准确率、微平均(micro average)都偏向大类,这才导致评估虚高。很多工程师做分类任务直接用model.score()就完事,但一旦类别不平衡,这种偷懒会直接让少数类的表现被淹没。后来我补机器学习基础时,课程里用信用卡欺诈的例子一步步展示了这点--少量欺诈样本如果只看整体准确率,模型完全可以全判为正常,准确率照样 99%。这门机器学习基础课不只是教公式,它用真实场景告诉你为什么指标要分场景选,学完就不会再被“看起来挺好”的评估表骗了。我花了一周重新推导混淆矩阵,却卡在“平均”两个字上为了搞清问题,我关掉 sklearn,自己用 numpy 从混淆矩阵重算指标。先写二分类的 precision、recall、F1,都顺:import numpy as np def precision_recall_f1(cm): tn, fp, fn, tp cm[0,0], cm[0,1], cm[1,0], cm[1,1] prec tp / (tp fp 1e-12) rec tp / (tp fn 1e-12) f1 2 * prec * rec / (prec rec 1e-12) return prec, rec, f1扩展到多分类时,我以为 macro 就是先算每个类别的 F1 再取平均,micro 就是先把所有 TP、FP、FN 求和再算。写出来也没报错:def macro_micro_f1(cm): n cm.shape[0] tp np.diag(cm) fp cm.sum(axis0) - tp fn cm.sum(axis1) - tp precision_per tp / (tp fp 1e-12) recall_per tp / (tp fn 1e-12) macro_f1 np.mean(2 * precision_per * recall_per / (precision_per recall_per 1e-12)) micro_prec tp.sum() / (tp.sum() fp.sum()) micro_rec tp.sum() / (tp.sum() fn.sum()) micro_f1 2 * micro_prec * micro_rec / (micro_prec micro_rec 1e-12) return macro_f1, micro_f1但算出来我的模型 macro F1 只有 0.42,micro F1 却有 0.87。我查了十几篇博客,有说 macro 对不平衡更敏感,有说应该用 weighted,但没一个人讲清楚什么时候该用哪种、为什么 sklearn 默认用 weighted 但 API 文档又推荐 macro。我陷入了更深的困惑。这时候我才意识到,机器学习基础不是背几个公式就能通的,需要成体系地学推导和适用场景。AWS 的机器学习基础课把混淆矩阵、ROC 曲线从概率推到多分类,再用交互实验让你切换平均方式观察指标变化,这是看零散博客永远得不到的。机器学习基础这门课特别适合我这样半路出家、只会调包但说不出所以然的工程师,学完之后你至少能跟面试官把“为什么用宏平均”这件事掰扯明白。跟着深度学习课程做的三次实验,让我彻底搞懂宏微平均我报了 AWS 的深度学习课程,不是因为要学新网络,而是听说里面有一章叫“模型评估与调优”,专门处理多分类评估。课程给了三个 Jupyter Notebook 实验,一个一个跑下来,当初的困惑全解开了。第一个实验:给定一个 3 类的混淆矩阵,让你手算 macro、micro 和 weighted F1,并画出每个类别的 P-R 散点图。亲手算一遍,我才真正体会到 macro 是“每个类别平等投票”,micro 是“每个样本平等投票”,weighted 是按样本数加权。第二个实验:固定类别3样本数从 50 逐渐增到 2000,其他两类各 5000,记录三种平均的变化曲线。这个对比冲击极大--当类别3样本只有 50 时,macro 低到 0.2,而 micro 还有 0.8,因为大量样本来自另外两类。业务方关心的恰恰是那个 0.2 的类别,所以必须用 macro 作为主指标。这门深度学习课程给我的最大收获不是公式本身,而是“选择评估指标本身就是模型设计的一部分”这个观念。很多工程师先搭网络再想指标,其实应该反过来。第三个实验最狠:给你一套业务描述(“召回率对类别2和3不能低于0.8,类别5允许牺牲一些精确率”),让你自定义一个综合 loss 函数,结合不同类别的 cost。我用 PyTorch 写了加权交叉熵,并在验证循环里监控自己写的评估器。课程提供的AWS深度学习实验环境里已配好数据,不需要自己搭机器,跟着做就能把评估方案落进生产管道。学完这一章,我才真正从“看 sklearn 报告”进化到“设计评估体系”。不夸张地说,之前那种上线前只瞥一眼准确率的日子彻底结束了。学完课程,我把评估代码从 sklearn 包装改成了自定义计算回到项目,我重新设计了一套评估 pipeline。先用混淆矩阵计算每个类别的精确率、召回率,然后根据业务需求选择 macro 作为主评估,再单独输出类别3和7的 F1 供业务方审阅。代码也从之前的 demo 级变成了生产级:class MultiClassEvaluator: def __init__(self, cm): self.cm cm def per_class_metrics(self): tp np.diag(self.cm) fp self.cm.sum(axis0) - tp fn self.cm.sum(axis1) - tp eps 1e-12 prec tp / (tp fp eps) rec tp / (tp fn eps) f1 2 * prec * rec / (prec rec eps) return prec, rec, f1 def report(self, averagemacro): prec, rec, f1 self.per_class_metrics() if average macro: return np.mean(prec), np.mean(rec), np.mean(f1) elif average weighted: support self.cm.sum(axis1) w_prec np.average(prec, weightssupport) w_rec np.average(rec, weightssupport) w_f1 2 * w_prec * w_rec / (w_prec w_rec 1e-12) return w_prec, w_rec, w_f1 # ...配合数据预处理采样策略,线上模型替换后,类别3的召回率从 0.41 提到 0.76,精确率也从 0.38 涨到 0.68。业务方终于不再拉群质问,我才算缓过劲来。后来团队内部做了个深度学习入门分享,我把这套评估思路讲了一遍。同事问:“这些东西不就是 macro 和 weighted 的区别吗,你之前怎么不会?”我老老实实说,因为以前只看了网上零散的 Python 片段,从没系统学过深度学习基础,连 ROC 曲线在多分类怎么画都不知道。AWS 的深度学习课程把这些知识点串成了体系,才让我从“调参侠”变成能讲清为什么的人。给补基础的工程师几条血泪建议把混淆矩阵按类别拆开看:不要满足于整体准确率,尤其类别不平衡时,每类的 precision/recall 才是你的命门。我在AWS深度学习课后养成了一个习惯,每次训练完先打印每类指标,再决定是否调采样策略。宏平均和微平均没有绝对优劣,关键看业务:金融风控要宁愿误杀不放过(高召回),内容推荐可能更看重精确率。机器学习基础课里有一张表格对比了常见场景下的指标选择,值得你点进去对照自己的业务。自己手写一遍评估代码,别只调 sklearn:像我前面那样用 numpy 实现 macro/micro,能帮你发现权重假设和极端边界(比如除零保护)。这门深度学习课程的动手实验就强制你徒手写,写完基本就不会忘了。多分类 ROC 也要看,别只盯着 PR 曲线:虽然类别不平衡时 PR 更敏感,但多个 one-vs-rest 的 ROC 能帮你观察类间混淆情况。在补机器学习基础时,我才搞懂宏平均 ROC 和微平均 ROC 的差别。评估方案要在开发前就和业务对齐:别等上线被打脸才想起看指标。我现在接新任务第一件事就是确认业务更关心哪几个类、容忍多少漏判。这套方法,正是从AWS深度学习课的实验里搬过来的。如果觉得基础薄弱,直接去学一门成体系的课:零散看博客三年,不如系统跟一门深度学习课程三个月。它教的不只是指标,更是如何把模型评估做成工程上的闭环。
返回列表