说实话,我以前特别迷信算法。拿一个电商复购预测的项目说吧,当时我把用户浏览、加购、收藏、甚至停留时长全做成特征,再叠加上一整套xgboost调参,离线AUC跑到了0.93。看着群里老板竖起的大拇指,我觉得自己已经站在了数据挖矿的珠峰上。结果上线一周,预测准确率跟抛硬币差不多——准确率只有51.3%。后来复盘差点扇自己耳光:训练数据来自“双11”前后那段时间,用户行为全是促销刺激下的应激反应,而我拿这套规则去预测平时的工作日,当然会崩。
那次教训让我养成了一个习惯:先跟业务方聊数据生成过程,再谈建模。去年在做一个反欺诈模型,算法部门的人坚持用深度学习替换掉原来的规则引擎,说AUC还能涨两个点。我跑了一下,发现训练集里只有那些已经被识别的欺诈记录,漏网的欺诈在系统里全部被标记成了“正常”。模型越努力,越是在把历史漏洞当正常行为来学。也就是说,从源头就烂掉的标签,换什么模型都是在给错误答案做精细拟合。当时我把采样方式从按账户随机改成按时间窗口划分,再调整了三个字段的归一化逻辑,模型在冷启动场景下的召回率反而提高了14个百分点。这件事给我的冲击是:数据挖掘里最关键的“算法”,其实是你对数据从哪来、被谁改过、为什么缺失的理解。
对比一下传统统计和数据挖掘工程师的思维方式很有意思。早年做普查的统计师会盯着抽样框,纠结样本能不能代表总体;现在很多数据挖掘从业者盯着损失函数,恨不得把学习率调到小数点后四位。前者太慢,后者太飘。我见过一个团队花了两个月把模型线上定位的误差从50米压到45米,却没人注意到某个定位字段在夜间到凌晨会突然漂移到隔壁城市,因为值班工程师修服务器时把时区改错了。挖掘心态让你发现“啊,夜间用户有瞬移行为”,工程心态才促使你去查看数据字典里的时区字段。一个真正稳的数据挖掘项目,往往是这两股劲拧在一起,而不是谁替代谁。
现在我给自己定了三条傻乎乎的规矩。第一,任何变量在上模型之前,必须写一段五分钟能讲清楚它是怎么生成的,讲不清就不准用,哪怕它当时能提升0.01的AUC。第二,训练集和验证集要按自然时间切,并且至少保留一个让业务方惊讶的“违背直觉”的单独切片去测试,比如节假日后第一个工作日。第三,每次提交测试结果,我都要在后面附一段“数据不可靠区”的说明,比如哪些新注册设备的标签可信度低,哪些渠道的订单存在虚假交易嫌疑。这做法让我在几个项目里躲过了暗坑,其中一次是某支付系统的逾期预测,如果不看春节前后的数据分布,整个模型会把农民工返乡误判成高风险。说到底,数据挖掘不是从石头里榨出油,而是先把石头里包裹的化石和普通泥块分开——分错一块,后面全白搭。