十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

《模型不玄学》第12章 分类模型、 GBDT与神经网络

《模型不玄学》第12章 分类模型、 GBDT与神经网络 小白一句话监督模型在这套体系里就干一件事拿一个用户评分日及之前的特征算出一个数字——他未来 7 天有多大概率还会回来领。这件事在机器学习里叫二分类算出来的那个数字就是概率。监督模型在这一章的位置第2章讲过本项目有两个模型行为分类第9–11章无监督管他是什么风格活跃度预测本章起有监督管他会不会回来。第6章把样本长什么样定下来了一行 (uid, 评分日) 快照左边是特征、右边是标签active_7d未来 7 天是否至少再来 1 次。第7章把左边那 10 维特征讲清楚了。第8章把特征只能看左边、标签只能看右边这条线焊死。到了本章左边的特征和右边的标签都齐了该让模型学从特征到标签的映射了。我们用示例数据生成的训练表来做这件事162 行样本其中 134 行未来 7 天回来了label128 行没回来label0。这 134:28 的不均衡不是偶然——大部分常来的用户确实还会再来真正凉了的是少数。这个不均衡后面第14章样本权重和第19章评估指标都要专门对付先记一笔。二分类但模型给的是概率标签active_7d本身是 0 或 1。但直接让模型硬猜 0/1 太浪费——我们更想要一个连续的概率0.9 表示九成会回来0.1 表示基本凉了。原因很实际概率比 0/1 好用。后面可以把它乘 100 当成 0–100 分的活跃度第16章校准后会细讲也可以按概率高低给运营排个队而不是直接二分。所以这一章的任务是学一个函数f(特征) → 0~1 之间的概率。决策树模型其实在问一连串是否要理解后面那个模型先得懂它最基础的零件——决策树。它的工作方式特别像人做判断不断问这个条件成立吗顺着答案往下走走到叶子节点给个结论。用示例训练表训一棵只许问 3 层问题的浅树它自己学出的规则长这样读图从根节点开始满足节点条件走「是」分支、否则走「否」分支落到叶子节点即得到预测类别——绿色「会回来」class 1、红色「不会回来」class 0。你会发现它第一句话就问特征期总领取次数 ≤ 3.5 吗——这不是人写死的是树从数据里自己挑的最能分开回不回的那个问题。沿着这棵树走一个用户最终落到某个叶子叶子给出的就是这批人里有多大比例回来了那就是他的预测概率雏形。树靠不纯度挑问题树不是瞎猜先问哪个。它心里有一把尺子叫不纯度基尼不纯度衡量这一堆人里标签有多乱如果一堆人全回来了全 1或者全凉了全 0不纯度是 0最干净如果一半回一半没回最乱不纯度最高。树的做法是——对每个特征、每个可能的切分点都试一刀挑那一刀能让切完之后两边的不纯度加权和降得最多的。拿根节点试算一下162 行134 回 / 28 凉基准率 0.827根节点不纯度 0.2859。第一刀f_total_claims ≤ 3.5左支 46 行25 回不纯度 0.4962、右支 116 行109 回不纯度 0.1134加权不纯度 0.2221不纯度下降 0.0638。对照一刀按行号奇偶乱分和特征无关加权不纯度 0.2847只降 0.0012几乎没分干净。差距就在下降多少——树自动选下降最多的那刀所以第一句话问的是领取次数不是某个没用的特征。这套试所有可能、选降最多的就是决策树的学习也是为什么它第一刀和 GBDT 认为最重要的特征一致都是总领取次数。叶子的值为什么是概率每个叶子聚了一群人。树不硬说这群都会回来 / 都不会回来而是报这群人里实际回来的比例。比如某叶子拢了 100 人、80 人未来 7 天回来了就输出 0.8——意思是这拨人八成会回来而不是铁板钉钉。这个比例是训练数据里数出来的经验概率是后面概率预测的雏形第16章会讲它还得校准。深度简单规则 vs 死记硬背这棵浅树只许问 3 层。为什么不让它一直问下去因为树越深能把每个叶子分到只剩一种标签——等于把训练表背下来了。背下来的规则对新用户反而失灵过拟合训练时它认得 U0009换个人就不灵了。深度就是个旋钮浅一点是看得见的简单规则深一点是死记硬背。本项目用浅树当零件、再用 GBDT 把很多棵浅树叠起来既抓得住规律又不至于背死。决策树的好处是能直接读规则坏处是单棵太死板问的问题稍微变一点整棵树就换样而且单棵树抓不住多个特征合起来才说明问题的情况——这正是下一节 GBDT 要补的。GBDT把很多棵不太准的树叠起来本项目用的主模型是一类叫GBDT梯度提升树的方法——同样是监督模型也可以选神经网络为什么最后选了树本章最后一节会说清楚。它的想法很朴素先种一棵简单的树它肯定看不太准再看它错在哪儿种第二棵专门补这些错再看剩下的错种第三棵……最后把所有这些树的判断加起来就是最终预测。每一棵新树都在纠正前一堆树没搞定的部分专业地说是拟合前面模型的残差。单棵树弱叠几十上百棵就强了而且能捕捉特征之间拧在一起的关系——比如领得多且趋势没掉才高概率回来这种组合单棵树很难一次问清。残差新树到底在补什么“补错用大白话讲就是模型先把所有人统一猜成平均水平”——示例里 134 / 162 的人都回来了所以开局每个人都被估成 0.827八成会回来。对 U0009 这种实际没回来的人开局就猜高了差了 0.827 − 0 0.827这个差就是残差分类里它严格说是损失函数对当前预测的负梯度但直觉上就是猜的和真相差多少。第二棵树不预测回不回而是专门去学这个差值 0.827——它努力把 U0009 这类人的分往下拉。第三棵再学拉完之后还差多少继续补。所以 GBDT 不是在造 100 个独立的分类器而是在反复追问我现在还差哪儿没猜对一层层把错削小。看叠加怎么纠错概率随树棵数收敛把 GBDT默认 100 棵、学习率 0.1在示例训练表上跑起来盯着 U0036真回来和 U0009真没回两个老熟人看它们的概率怎么随树一棵棵加上去而变化已叠加的树U0036真实 1U0009真实 01 棵0.8440.8365 棵0.8810.82410 棵0.9200.75630 棵0.9680.58050 棵0.9790.437100 棵0.9920.219开头两棵几乎没把他俩分开都贴在 0.83 附近因为模型还只会瞎猜平均。往后每加一棵U0036 被稳稳往上推到 0.99、U0009 被一点点拽到 0.22——这就是叠加纠错长什么样不是一步到位是几十棵小树一点点把每个人挪到该去的地方。最终 0.99 / 0.22 正好就是下一节抽查用的两个数。这里有个值得盯的细节第 1 棵小树是一次性去拟合所有人的残差本身是个折中——U0009 在第一个切分上看着和活跃人群没两样领取次数高所以第 1 棵反而把他往上带了零点几0.836得等后面的树看到他在掉才把他一路拉回 0.22。光看领取次数这种历史活跃特征起初根本分不出他和真活跃的人——树要叠起来才看得清。学习率为什么是一百小步而不是几大步看上面这张表每加一棵概率只挪一点点比如 U0009 从 0.836 到 0.824 才动一丢丢。GBDT 故意这样每棵树的修正都先乘一个很小的数学习率默认 0.1再叠加叫收缩shrinkage。好处是任何一棵树都掀不起大浪得靠很多棵一起把预测推到位模型更稳、不容易被个别怪样本带偏。所以 GBDT 的套路是很多棵浅树 小步快跑而不是一棵深树一步登天——这也和上面决策树别长太深是一个道理。写成式子就是这个加法的样子最终分数 开局平均 0.1×树₁ 0.1×树₂ … 0.1×树₁₀₀概率 把这个分数塞进 S 形函数sigmoid压到 0~1 之间用同一张训练表训一个 GBDT看它认为哪些特征最影响回不回f_total_claims 0.250 特征期总领取次数最主要的信号 f_age 0.173 龄第一次出现距今多久 f_active_rate 0.149 活跃率来过的天数占观测期的比例 f_trend 0.084 趋势近 7 天比前 7 天多还是少 f_recency 0.083 新近度多久没来了 f_entropy 0.069 偏好熵任务偏好的分散程度 f_days_total 0.069 全期活跃天数 f_longest_streak 0.057 最长连续活跃天数 f_task_types 0.045 任务种类数 f_top_share 0.022 主任务占比特征期总领取次数排第一和浅树第一句话问的它一致——说明这件事模型自己反复确认领得越多越可能接着来。这和直觉对得上也让人放心模型没在乱学。拿两个老熟人验证一下预测对不对U0036几乎天天来、啥都领GBDT 给的概率0.99真实标签 1确实回来了。U0009历史活跃但快凉第2、3、6、8章多次出现的反例概率0.22真实标签 0这次真没回来。U0009 这个例子把监督和无监督的分工说得很透行为上他依然是高频多任务那一堆无监督把他和 U0036 分到类似的群但光看历史活跃会误判他会回来——监督模型吃了趋势、新近度这些特征读出他在掉给了低概率。这正是第2章说的行为像 ≠ 命运一样。超参数从哪来早停、网格搜索、防过拟合旋钮前面用的 GBDT 是100 棵、深 3、学习率 0.1。这三个数不是拍脑袋——但得坦白示例只有 105 行训练样本调参能捞的收益很小这一节教的是怎么调的流程不是调完一定变强。早停的直觉树越多越好吗把树的棵数从 10 加到 200看训练和测试两边的分数棵数训练 PR-AUC测试 PR-AUC测试 ROC-AUC100.9980.8540.741300.9990.8610.740601.0000.9030.7851001.0000.8270.6891501.0000.8500.7222001.0000.8440.701训练分数从 10 棵起就贴着 1——树背训练数据的能力太强再加棵树它也记得住。测试分数不一样60 棵附近最高0.903往后开始晃0.827、0.850、0.844。训练一路降、测试涨到某处就停甚至往回掉就是再加树只是在背数据的信号该停了——这就是早停的直觉。一个小提醒要摆明示例的测试曲线自己就在晃60 棵 0.903100 棵 0.827150 棵又回 0.850因为 57 人的测试集噪声大。所以早停不能盯单点要看验证集的整体趋势——这正是第 8 章三切分里验证集存在的意义之一。网格搜索换参数组合试超参数不会自己跳出来最朴素的办法是网格搜索——几个参数各取几个值组合起来都跑一遍。示例上试了深度 × 学习率组合测试 PR-AUC测试 ROC-AUCdepth2, lr0.10.8150.694depth3, lr0.1默认0.8270.689depth5, lr0.10.8320.690depth3, lr0.050.8980.786depth5, lr0.050.8280.694depth3、lr0.05 看着最好0.898。但有条纪律得说在前面真实流程是训练 → 验证 → 测试三层参数用验证集选测试集只碰一次。上面这张表直接拿测试集挑参数是演示用的小作弊——真实项目这么干等于把测试集也泄给了调参过程最后报出来的 0.898 会虚高。而且 0.898 和默认 0.827 的差距在 57 人测试集上同样是噪声级别——参数可以调但要认命样本就这么大能捞的就这么多。防过拟合旋钮还有几个开关除了棵数和深度GBDT 还有几个别让模型太自由的开关subsample每棵树只随机看一部分行再分裂0.8 看 80%。树之间看到的数据不一样、更独立平均起来更稳。示例上 subsample0.8 的测试 PR-AUC 0.863比 1.0 的 0.827 略好。min_samples_leaf叶子最少装几个人。太细的叶子比如一个叶子只装 1 个人等于在背个体不让它长。这就是深度简单规则 vs 死记硬背那节的另一种拧法——不限制深度、限制叶子大小效果类似。一句话默认参数能跑调参是锦上添花调参的流程比参数本身重要——早停看验证集趋势选参用验证集测试集最后碰一次。另一种主流神经网络在做什么GBDT 走的是问一连串是非题的路子那当下更常被提起的神经网络走的是另一条。想象一排小开关叫神经元每个开关把接到的几个数各自乘一个权重、加起来再过一道把结果压到 0~1 之间的函数吐出一个新数。把很多这样的开关排成一层一层接一层——第一层接原始特征后面每层拿前一层的输出当输入最后一层吐出预测概率。这就是多层感知机MLP最基础的那种神经网络# 结构 10 → 32 → 16 → 110 个特征进中间两层各 32、16 个神经元输出 1 个概率MLPClassifier(hidden_layer_sizes(32,16))那学习学的是什么就是这些权重。训练时先把样本喂进去顺着网络算出一个预测前向传播看看和真相差多少再从后往前把每个权重要为这个误差担多少责任算出来各自往让误差变小的方向挪一点反向传播配梯度下降。喂一批挪一点、再喂一批再挪一点成千上万轮下来权重就落在了一个总体误差不大的位置。和树模型对比着看更清楚树是比大小、走分支——“领取次数 ≤ 3.5 吗”非此即彼规则看得见。网络是加权求和——每个特征贡献多少由一个权重说了算几百个权重拧在一起很难讲清它到底看中了什么。神经网络真正厉害的地方是能自己学特征该怎么表达。给它一张图片不用人先告诉它边缘在哪、眼睛在哪前几层自己就学会描边后面几层慢慢拼出形状。图像、语音、文字这种原始信号人很难手工总结出好特征正好交给它。代价也实在参数多。上面那个不起眼的 10 → 32 → 16 → 1待学权重就有897 个。参数越多要喂的样本就越多。吃预处理。权重乘的是特征原值所以得先缩放到差不多的范围标准化否则量纲大的一家独大。树靠比大小不吃这一套。不好解释。897 个权重各是多少说不出个所以然只能讲它觉得这个人分数高。第15章会拿本项目的示例数据真跑一遍神经网络和 GBDT 比分数、比稳定性。这里先有个概念接着看为什么本项目最后选了树。为什么是 GBDT不是深度学习新手常有个疑问现在不是都在用深度学习吗怎么这项目还用树因为咱们的数据是表格型的——一行一个用户、一列一个特征特征之间没像素那样的空间/序列结构。这类数据上树模型GBDT 及其变体长期是实用首选原因很实在量纲不敏感天数十几、次数几十、偏好熵0~几点几混在一起树靠比大小分割不用像神经网络那样先标准化第9章标准化是为了聚类距离树模型本身不需要。缺失值友好某个特征空了比如冷启动用户的部分特征树可以走没这个值的分支不像神经网络要求每列都填满。小样本更稳示例才 162 行树模型换次训练分数几乎不动神经网络在这个量级也能跑出像样的分数但换一次初始化结果就变第15章会拿两组实测数字比给你看。能解释上面的特征重要性、决策规则都是看得见的出了问题能查。深度学习在图像、文本、语音这种原始信号上厉害在咱们这种已经整理好的小表格上属于杀鸡用牛刀还更难解释。所以这一章先把树模型吃透足够应付本项目的监督主模型。第15章会把神经网络也拉进来跑一遍——不是比谁分数高是比谁更让人放心。集成不只有一条路bagging、boosting 与 stackingGBDT 是很多棵树串行补残差这条集成路线叫boosting。但把很多模型合起来不止这一种玩法还有两条bagging很多棵树并行独立训练每棵随机看部分行、部分特征结果投票或平均代表是随机森林。单个模型波动大一平均波动就小了——它管的是减方差。stacking把不同种类的模型拼起来比如随机森林 GBDT预测合在一起再学一层。它们犯的错不一样取长补短。同一份数据105 行训练 / 57 行测试三条路线各跑一遍路线本质PR-AUCROC-AUC随机森林bagging并行独立树投票0.9230.806GBDTboosting串行补残差0.8270.689简单融合stacking两个概率平均0.9230.802单看这一行随机森林和简单融合明显更高0.923 vs 0.827。先别急着下该换随机森林的结论——换 4 个种子再看模型4 个种子的 ROC-AUC跨度随机森林0.762 ~ 0.8060.044GBDT0.686 ~ 0.6900.005随机森林 4 个种子全都比 GBDT 高最差 0.762 GBDT 最好 0.690但跨度是 GBDT 的将近九倍——它在这份数据上确实占优只是也更抖。那前面几章为什么一路用 GBDT因为选它靠的不是单点分数最高特征重要性、缺失值友好、规则看得见这些工程与解释性上的优势在这份特征少、要解释、样本小的数据上更顺手。选模型看的是综合取舍不是一张表里最高的那个数。真实项目怎么挑路线看数据的性格特征多而杂、容易过拟合 →bagging平均天然抗噪特征少而精、要可解释 →boostingGBDT 一条路走到底要冲极限分数、工程上养得起 →stacking把前两种都拿来拼。本项目是特征少、要解释、样本小所以走了 boosting——这个选择在第 15 章被神经网络挑战过一次这一节再被随机森林挑战一次结论都一样分数不是唯一的尺子。它和双模型的关系到这儿第2章画的双模型就完整了行为分类无监督吃左边特征 → 吐他属于哪类行为风格不碰标签。活跃度预测监督本章吃左边特征 右边标签 → 学未来 7 天回来的概率。两个模型共享同一份特征底座第7章那套但回答不同的问题谁也不替谁。下一章第13章先给训练样本做一遍准入体检——样本分布、有没有被少数高频用户主导、训练和测试的分布对不对得上体检不过就白训第14章讲标签怎么变成损失、样本不均衡和同用户多样本该怎么加权第16章讲概率为什么要校准第17章把训练 → 评估 → 每日评分三步串起来跑通。动手跑附件/05_活跃度预测篇/activity_gbdt_intro.py它会先打印那棵浅树规则再打印特征重要性最后抽查 U0036、U0009 的预测。对照正文看树第一句话问了什么、U0009 概率是不是真的低。打开生成的附件/05_活跃度预测篇/activity_train_table.csv随便挑一行照着浅树的规则走一遍看它落到哪个叶子、叶子判断是 0 还是 1。想一个边界情况如果只拿近 7 天活跃天数 ≥ 3 就预测会回来当规则第3章我们试过对照训练表U0009 在近 7 天其实也有几天——这种只看一个特征的硬规则会漏掉多少看起来还行但其实在掉的人这也是为什么需要模型而不是拍阈值。跑附件/05_活跃度预测篇/activity_ch12_principle.py它会打印根节点和第一刀的基尼不纯度对照正文那个 0.2859 → 0.2221 的下降以及 U0036 / U0009 随树棵数变化的概率表对照正文那张收敛表。改一下脚本里的stages列表看 20 棵、80 棵时他俩分别在哪。跑附件/05_活跃度预测篇/activity_hyperparam.py对照超参数从哪来那节训练 PR-AUC 一路贴 1、测试 PR-AUC 60 棵见顶后开晃把subsample从 0.8 改成 0.6 重跑看测试分怎么动。跑附件/05_活跃度预测篇/activity_ensemble.py对照集成不只有一条路那节随机森林单点 0.923 vs GBDT 0.827但换 4 个种子随机森林跨度 0.044、GBDT 只有 0.005——这就是分数最高的不一定是选中的那个。本章配套脚本附件/05_活跃度预测篇/activity_train_table.py从明细生成训练表、附件/05_活跃度预测篇/activity_gbdt_intro.py决策树 GBDT 演示、附件/05_活跃度预测篇/activity_ch12_principle.py基尼不纯度挑问题 GBDT 逐阶段概率、附件/05_活跃度预测篇/activity_hyperparam.py早停曲线 网格搜索 防过拟合旋钮、附件/05_活跃度预测篇/activity_ensemble.pybagging/boosting/stacking 三条路线对比。用到的 numpy、scikit-learn 已在第4章附件/00_公共/requirements.txt中列出环境搭建见第4章。
返回列表