# 数据分析 · 第 06 篇|预测分析与建模入门 > 系列:project / 数据分析(共 12 篇)|AI生成|2026-10-27|codebuddy **这一篇讲什么** 前五篇处理的是已经发生的事:描述它、诊断它、用实验验证它。这一篇往前一步,处理还没发生的事——预测。内容刻意避开公式推导,只讲三件事:什么问题能用预测解决、一个模型从定义到上线要经过哪些步骤、以及哪些地方最容易自欺欺人。具体包括:回归、分类、时间序列三类问题的区分;标签、特征、切分、训练、评估、监控的完整流程;用北辰优选流失预测做特征工程;四类模型的直觉与局限;MAE、AUC、精确率、召回率的正确用法;过拟合与数据泄漏的自查;以及阈值如何按成本和收益来定。读完应该能判断一个预测需求靠不靠谱,也能看懂别人模型报告里的水分。 ## 一、三种预测问题:先分清你要预测什么 业务说「帮我预测一下」,这句话几乎没有信息量。预测的目标不同,方法、评估、落地方式全都不同。先分三类。 | 类型 | 预测什么 | 北辰优选例子 | 输出 | 常用评估 | | --- | --- | --- | --- | --- | | 回归 | 一个连续数值 | 预测某用户未来 30 天的消费金额 | 金额(元) | MAE、RMSE、R² | | 分类 | 一个类别或概率 | 预测某用户未来 30 天会不会流失 | 概率 0—1 | AUC、精确率、召回率、F1 | | 时间序列 | 一串按时间排列的数值 | 预测未来 12 周的销量 | 12 个点 | MAE、MAPE、区间覆盖率 | **回归**回答「多少」。典型场景:给每个用户打一个未来 90 天消费额的分,用于分层运营;预测某个门店下周的备货量。它的难点在于极端值——少数大额用户会把误差指标拉得很高,所以常常先做对数变换,或者干脆改成「分档预测」。 **分类**回答「是或否」,但实际输出应该是概率而不是 0/1。因为 0/1 需要先定阈值,而阈值是个业务决策(第七节会展开)。流失预测、欺诈识别、是否点击、是否退款,都属于这一类。分类里最常见的问题是类别不平衡:真实流失率可能只有 5%,模型只要全猜「不流失」就能有 95% 的准确率,这种模型毫无用处。 **时间序列**回答「接下来会怎样」。它和回归的区别在于,样本之间不独立——本周销量和上周强相关,不能随机打乱切分。它要额外处理趋势、季节性、节假日、促销事件。北辰优选预测未来 12 周销量时,必须把「双十一」「年货节」这类固定事件作为特征或单独建模,否则模型会把促销月的峰值当成常态。 三类问题还有个隐藏差别:**预测的时间跨度越长,不确定性越大**。预测明天和预测明年,同样一个模型的可信度差一个量级。业务提需求时,第一个要问的就是「预测多远的未来、用来做什么决策」。如果预测结果不改变任何动作,这个模型就不该做。 ## 二、建模流程:从标签到上线监控 一个能用的模型,工作量的大头不在训练,而在定义问题和准备数据。流程可以拆成六步。 | 步骤 | 要做的事 | 北辰优选流失预测的具体内容 | 常见失误 | | --- | --- | --- | --- | | 1 定义标签 | 明确「什么算流失」和观察窗口 | 截至 9 月 30 日,之后 30 天无 paid 订单 | 标签定义含糊,口径随时改 | | 2 构造特征 | 只用观察点之前的信息 | 近 30 天登录、近 90 天订单、客单价、券使用率 | 用了未来信息,造成泄漏 | | 3 切分数据 | 训练/验证/测试,按时间切 | 2025 年数据训练,2026 上半年验证,三季度测试 | 随机切分,未来信息渗入训练 | | 4 训练模型 | 选算法、调参 | 逻辑回归做基线,梯度提升树做主力 | 一上来就上复杂模型,无法解释 | | 5 评估 | 业务指标 + 统计指标 | AUC、召回率、按阈值算的净收益 | 只看准确率 | | 6 上线监控 | 定期打分、监控漂移、重训 | 每月打分一次,季度重训 | 上线即失联,效果衰减无人发现 | **标签定义**是最容易被低估的一步。「流失」到底是 30 天没下单、60 天没登录,还是主动注销?定义不同,正样本率可能从 3% 变到 30%,模型的难度和用途完全不同。定义要满足三个条件:可观测(数据里有明确记录)、有时效(能在需要干预之前算出来)、有业务含义(对应一个可执行的运营动作)。如果定义了流失却没有任何挽留手段,这个模型从第一天就没有价值。 **切分数据**在时间序列和用户行为场景里必须按时间切,不能随机切。原因很直白:随机切分会让模型在训练时见到「未来」的样本,评估结果虚高,上线后立刻掉下来。正确做法是用较早的一段训练、较近的一段验证、最近的一段测试,模拟真实的「用过去预测未来」。 **基线模型**经常被跳过,但它很重要。逻辑回归或者「按最近一次下单距今天数排序」这种极简规则,往往能拿到 AUC 0.75 左右。先做基线,再上复杂模型,才能说清楚「复杂模型多花的成本换来了多少提升」。如果梯度提升树只比逻辑回归高 0.02 AUC,但解释成本高一个量级,选简单的那个通常更明智。 ## 三、特征工程:把业务动作翻译成列 模型只认数字,特征工程就是把业务理解翻译成列。对流失预测,有四类特征最有用。 | 特征类型 | 具体特征 | 业务含义 | 注意点 | | --- | --- | --- | --- | | 时间窗口计数 | 近 7/30/90 天登录次数、下单次数 | 活跃度与购买频率 | 窗口要覆盖不同行为周期 | | 金额聚合 | 近 90 天 GMV、客单价、最大单笔 | 价值与消费能力 | 极端值要做截断或对数变换 | | 比率特征 | 券使用率、退款率、加购未支付率 | 价格敏感度、履约体验 | 分母为 0 时要单独处理 | | 时间差特征 | 最近一次下单距今天数、注册至今天数 | 衰减程度、生命周期阶段 | 这类特征往往最重要 | 北辰优选的流失预测用了十来个特征,其中「最近一次下单距今天数」(recency)通常排在前三。这符合直觉:一个人越久没买,越可能不再回来。但光有 recency 不够,因为它无法区分「刚注册还没养成习惯」和「老客自然沉睡」,所以要配合注册天数、历史订单数一起看。 几个实操要点。 **时间窗口要多尺度**。只做 30 天会漏掉低频高价值用户——他们可能两个月才买一次,30 天内本来就是 0 单。同时放 7 天、30 天、90 天三个窗口,模型才能区分「低频正常」和「真的不来了」。 **聚合之外要加趋势**。近 30 天订单数从 5 降到 1,和一直稳定在 1,含义完全不同。可以加「近 30 天订单数 ÷ 前 30 天订单数」这类比值特征,捕捉变化方向。 **缺失值本身是信息**。「从未使用过优惠券」和「券使用率为 0」在业务上是两回事,前者可能根本不知道有券。做法是加一个「是否缺失」的标记列,再对数值做填充,而不是简单填 0。 **类别特征要编码**。渠道、城市等级这类文本列,可以用 one-hot(取值少时)或目标编码(取值多时)。目标编码要小心,必须用交叉验证的方式计算,否则会把标签信息泄漏进特征。 特征工程有一条铁律:**任何特征都只能使用预测时点之前就能拿到的信息**。北辰优选以 9 月 30 日为观察点,那么「近 90 天订单数」只能统计 7 月 2 日到 9 月 30 日。如果代码里写成了「全表订单数」,模型就提前知道了未来,离线 AUC 会高得离谱,上线后一塌糊涂。 ```sql -- 示意:以 2026-09-30 为观察点构造特征(只用观察点之前的数据) WITH feat AS ( SELECT u.user_id, u.channel, DATE_DIFF('day', MAX(o.order_date), DATE '2026-09-30') AS recency_days, COUNT(DISTINCT CASE WHEN o.order_date >= DATE '2026-07-02' THEN o.order_id END) AS orders_90d, SUM(CASE WHEN o.order_date >= DATE '2026-07-02' THEN o.amount ELSE 0 END) AS gmv_90d, AVG(CASE WHEN o.order_date >= DATE '2026-07-02' THEN o.amount END) AS aov_90d, AVG(CASE WHEN o.order_date >= DATE '2026-07-02' THEN o.coupon ELSE NULL END) AS coupon_rate_90d FROM users u LEFT JOIN orders o ON o.user_id = u.user_id AND o.status = 'paid' AND o.order_date < DATE '2026-09-30' GROUP BY u.user_id, u.channel ) SELECT * FROM feat; ``` 这段 SQL 的关键在 `o.order_date < DATE '2026-09-30'` 这个条件。少了它,特征里就会混入标签窗口期的订单,模型直接「看到答案」。这类错误在真实项目里出现的频率,比大多数人想象的高。 ## 四、四类模型:直觉、适用与局限 不需要推导公式,但要知道每个模型在做什么、什么时候会失效。 | 模型 | 一句话直觉 | 适合 | 局限 | | --- | --- | --- | --- | | 线性回归 | 给每个特征配一个权重,加起来就是预测值 | 关系近似线性、需要解释系数 | 处理不了强交互和非线性 | | 逻辑回归 | 线性组合过一个 S 形函数,压到 0—1 | 二分类基线、风控评分卡 | 需要人工构造交互特征 | | 决策树 | 一连串「如果……就……」的切分 | 规则清晰、可解释 | 单棵树极易过拟合 | | 随机森林 | 很多棵树投票,降低方差 | 表格数据、特征多、调参少 | 模型大、解释性弱于单树 | | 梯度提升树 | 一棵接一棵,每棵修正前一棵的错 | 表格数据的常用强基线 | 需要调参、训练较慢、易过拟合 | **线性回归**的系数可以直接读:客单价每高 100 元,预测消费额平均高多少。这让它特别适合需要向业务解释「为什么」的场景。但它的假设很强——特征之间不能高度共线,关系要近似线性,异常值影响大。 **逻辑回归**是二分类的默认基线。它输出的是对数几率,配合特征分箱就是风控行业常用的评分卡。它的优点是稳定、可解释、样本需求不大;缺点是需要人手工设计交互项,比如「新客 × 用券」这种组合它自己发现不了。 **决策树**最接近人的思考方式,一条条规则往下切,画出来能给运营看。但单棵树非常容易过拟合——只要允许它一直分下去,它能把训练集每个样本都分对,包括噪音。所以实践中很少用单树。 **随机森林**用「多棵树 + 随机采样特征」来对冲过拟合,几乎不用调参就能拿到不错的效果,是很好的第一选择。代价是模型体积大,解释要靠特征重要性这种间接指标。 **梯度提升树**是表格数据上最常用的强基线,思路是「后面一棵树专门修正前面所有树的残差」。它在结构化数据上往往比神经网络还好用,但对超参数敏感,学习率、树深、树数量配不好就容易过拟合。用它之前,先有一个逻辑回归基线做对照,才知道多出来的复杂度值不值。 选择顺序建议是:先逻辑回归或简单规则做基线,再试梯度提升树,只有在数据量很大且明确是感知类任务(图像、文本)时才考虑深度学习。**大部分业务问题的瓶颈在特征和标签,不在模型复杂度**。 ## 五、评估:准确率 95% 为什么可能没用 评估指标要跟业务目标对齐,而不是跟「看起来高」对齐。 北辰优选的流失模型,在 1,000 个测试用户上跑出下面这个结果:真实流失 50 人,模型判定 12 人会流失,其中 8 人确实流失了。 | | 实际流失 | 实际未流失 | 合计 | | --- | --- | --- | --- | | 预测流失 | 8(TP) | 4(FP) | 12 | | 预测未流失 | 42(FN) | 946(TN) | 958 | | 合计 | 50 | 950 | 1,000 | - 准确率 = (8+946)/1,000 = 95.4% - 精确率 = 8/12 = 66.7% - 召回率 = 8/50 = 16.0% - F1 = 2×0.667×0.16/(0.667+0.16) ≈ 0.26 准确率 95.4%,看起来漂亮。但**全部预测「不流失」的准确率是 95.0%**,模型只比什么都不做高 0.4 个百分点。而它漏掉了 84% 的真实流失用户——如果运营按这个名单去挽留,50 个要走的人里只能拦住 8 个。 | 指标 | 公式 | 回答的问题 | 什么时候优先看 | | --- | --- | --- | --- | | 准确率 | (TP+TN)/全部 | 整体判对多少 | 类别均衡且两类错误代价相近 | | 精确率 | TP/(TP+FP) | 判为流失的人里,多少是真的 | 干预成本高,怕打扰用户 | | 召回率 | TP/(TP+FN) | 真流失的人里,拦住了多少 | 漏掉一个的代价很高 | | F1 | 精确率与召回率的调和平均 | 两者的平衡 | 需要一个综合分做模型对比 | | AUC | ROC 曲线下面积 | 排序能力,与阈值无关 | 只关心「谁更可能流失」的排序 | | MAE | 平均绝对误差 | 平均差多少 | 回归,关心典型误差 | | RMSE | 均方误差开根 | 大误差被放大后的误差 | 回归,大错代价高 | | R² | 1 - 残差平方和/总平方和 | 解释了多大比例的波动 | 回归,快速看拟合程度 | AUC 衡量的是排序能力:随机取一个流失用户和一个未流失用户,模型给前者打分更高的概率。它和阈值无关,所以适合评估「模型本身好不好」;但它不告诉你「在某个阈值下能拦多少人」,所以不能替代精确率和召回率。北辰优选这个模型如果 AUC 是 0.82,说明排序能力尚可,问题出在阈值定得太保守。 回归的指标也有讲究。假设销量预测的 MAE 是 120 件、RMSE 是 210 件,RMSE 明显大于 MAE,说明存在少数大误差——可能是促销周没预测准。这时候要看误差的时间分布,而不是盯着一个总数。R² 为 0.62 意味着模型解释了 62% 的波动,剩下 38% 是模型没捕捉到的因素,对销量预测来说属于中等水平。 ## 六、过拟合、数据泄漏与验证 模型在训练集上表现好、在新数据上表现差,叫过拟合。它和「数据泄漏」是初学者最容易踩的两个坑,而且都会让离线评估严重虚高。 | 自查项 | 异常信号 | 可能原因 | 处理 | | --- | --- | --- | --- | | 训练集与测试集差距 | 训练 AUC 0.95,测试 0.68 | 过拟合 | 减特征、加正则、早停 | | 单个特征重要性异常高 | 某一列贡献 80% | 数据泄漏 | 查该特征的生成时点 | | 切分方式 | 随机切分时间序列数据 | 未来信息渗入 | 改为按时间切分 | | 样本特征比 | 样本数 < 特征数×10 | 维度灾难 | 减特征或增样本 | | 类别分布 | 正样本仅 2% | 不平衡 | 看 PR 曲线,调类别权重 | | 线上效果 | 上线一周效果骤降 | 分布漂移或泄漏 | 对比线上线下特征分布 | **过拟合**的本质是模型记住了噪音。判断方法很简单:训练集和验证集的指标差多少。差 5 个点以内通常可接受,差 20 个点基本就是过拟合。处理手段有四个方向:减少特征数量、增加正则化强度、限制模型复杂度(树深、树数量)、增加样本量。 **数据泄漏**更隐蔽,因为它的表现是「效果好得不像话」。常见形式有三种。第一种是特征里包含了标签窗口期的信息,比如用「未来 90 天订单数」预测流失。第二种是预处理时用了全量数据,比如先对全体做标准化再切分,测试集的均值信息渗进了训练。第三种是 ID 类特征,用户 ID、订单号本身可能编码了时间顺序,模型会偷偷利用它。 **交叉验证**能缓解单次切分的偶然性。把训练集分成 K 份,轮流用 K-1 份训练、1 份验证,取平均。它比单次验证更稳,但对时间序列仍然要特殊处理——必须用「时间序列交叉验证」,保证每次验证集都在训练集之后。 还有一个容易被忽略的检查:**线上线下一致性**。离线评估用的是历史数据,线上打分用的是当天数据,如果特征的计算逻辑在两边不一致(比如离线用 T+1 全量、线上用实时增量),模型效果会莫名其妙地掉。上线前一定要抽样比对同一批用户在两套管道下的特征值。 ## 七、案例:北辰优选流失预测的 10 个用户 下面是一组示意数据:10 个用户,模型给出的流失概率,以及事后观察到的真实结果。 | 用户 | 近 30 天登录 | 近 90 天订单 | 客单价 | 券使用率 | 距上次下单 | 预测概率 | 实际流失 | | --- | --- | --- | --- | --- | --- | --- | --- | | U1 | 0 | 0 | — | 0% | 96 天 | 0.92 | 是 | | U2 | 2 | 1 | 88 元 | 100% | 71 天 | 0.85 | 是 | | U3 | 5 | 2 | 120 元 | 50% | 48 天 | 0.71 | 是 | | U4 | 8 | 4 | 260 元 | 25% | 22 天 | 0.64 | 否 | | U5 | 3 | 1 | 95 元 | 100% | 55 天 | 0.55 | 是 | | U6 | 12 | 6 | 310 元 | 17% | 14 天 | 0.41 | 否 | | U7 | 4 | 2 | 105 元 | 100% | 40 天 | 0.33 | 是 | | U8 | 15 | 8 | 420 元 | 12% | 9 天 | 0.22 | 否 | | U9 | 20 | 9 | 380 元 | 10% | 6 天 | 0.12 | 否 | | U10 | 25 | 12 | 500 元 | 8% | 3 天 | 0.05 | 否 | 真实流失 5 人(U1、U2、U3、U5、U7)。用两个阈值对比: | 阈值 | 触达人数 | 命中 | 误伤 | 漏掉 | 精确率 | 召回率 | 净收益 | | --- | --- | --- | --- | --- | --- | --- | --- | | 0.50 | 5 | 4 | 1 | 1 | 80% | 80% | +140 元 | | 0.33 | 7 | 5 | 2 | 0 | 71% | 100% | +160 元 | 净收益的算法:每次干预成本 20 元(券 + 触达),被成功挽留的用户带来 200 元毛利,挽留成功率 30%,所以命中一个的期望收益是 0.3×200-20 = 40 元,误伤一个损失 20 元。 阈值 0.33 在这个样本上更优,因为它多拦住了一个真实流失用户(U7,概率 0.33),多付出的是一次误伤(U6)。但 0.33 不是标准答案,它来自「成本 20、收益 200、成功率 30%」这组假设。**阈值应该由成本和收益反推**,而不是拍一个 0.5。 通用的推导方式是:设用户流失概率为 p,干预的期望收益为 p×(成功率×用户价值 - 成本) - (1-p)×成本,令其大于 0,解出 p 的临界值。代入本例:p×(0.3×200-20) - (1-p)×20 > 0,即 60p - 20 > 0,p > 1/3。所以 0.33 左右是最优阈值。如果券成本涨到 40 元,临界值会升到 0.5 以上,触达名单就要收窄。 这套算法可以写进打分脚本,每次业务成本变化时重算,而不是把阈值写死在代码里。 ```python import numpy as np from sklearn.model_selection import train_test_split from sklearn.ensemble import GradientBoostingClassifier from sklearn.metrics import roc_auc_score #特征矩阵 X,标签 y(是否流失,1/0) X_tr, X_te, y_tr, y_te = train_test_split( X, y, test_size=0.3, stratify=y, random_state=42 ) model = GradientBoostingClassifier( n_estimators=200, max_depth=3, learning_rate=0.05 ) model.fit(X_tr, y_tr) proba = model.predict_proba(X_te)[:, 1] print("AUC", round(roc_auc_score(y_te, proba), 3)) def net_value(y_true, p, thr, cost=20, value=200, success=0.3): pred = (p >= thr).astype(int) tp = int(((pred == 1) & (y_true == 1)).sum()) fp = int(((pred == 1) & (y_true == 0)).sum()) return tp * (success * value - cost) - fp * cost, tp, fp for thr in np.arange(0.1, 0.9, 0.05): nv, tp, fp = net_value(y_te, proba, thr) print(f"阈值 {thr:.2f} 净收益 {nv:>8.0f} 命中 {tp:>3} 误伤 {fp:>3}") ``` 这段代码有三个细节值得注意:`stratify=y` 保证切分后两类比例一致;`max_depth=3` 是控制过拟合的常用起点;最后那段阈值扫描把「选模型」和「选动作」分开——模型只负责给概率,阈值由业务成本决定。 ## 八、落地与边界:阈值、成本、漂移和不该说的话 模型训练完只是开始,真正决定价值的是落地环节。 **阈值不是 0.5**。0.5 只是「两类错误代价相等」时的默认值,现实中几乎从不成立。挽留一个高价值用户的收益远大于打扰一个低价值用户的成本,所以阈值应该更低;反过来,如果干预手段是打电话,打扰成本很高,阈值就该更高。阈值要写成可配置参数,随成本和策略调整。 **要监控漂移**。用户行为会变,特征分布会变,模型效果会衰减。三个监控项:特征分布的稳定性(比如近 30 天登录次数的均值是否偏移)、预测分数的分布(是否整体上移或下移)、实际效果(触达后的挽留率)。北辰优选可以每月抽 1,000 人做小样本回看,如果 AUC 从 0.82 掉到 0.72,就该重训了。 **要保留可解释性**。运营拿到一份名单,会问「为什么这个人在名单里」。梯度提升树可以用特征贡献解释,至少要能给出前三个原因:比如「96 天未下单、券使用率 0、近 30 天零登录」。给不出理由的名单,一线不会用。 **预测不是因果**。模型告诉你「这类用户容易流失」,不告诉你「发券能留住他」。高流失概率的用户可能正是因为价格敏感才流失,发券有效;也可能是体验太差,发券只会加速他离开。要回答「什么动作有效」,还得回到第五篇的实验。把预测当成决策依据,把实验当成验证手段,两者不能互相替代。 **不要过度承诺**。模型能给的是概率排序和有限的提升,不是「精准预测每一个人」。给业务方的预期应该是「在同样预算下,触达效率提升多少」,而不是「提前知道谁会走」。前者可以验证,后者无法兑现。 最后一个现实约束:**模型的价值上限由动作决定**。如果预测出 1,000 个高危用户,但运营一周只能触达 100 个,那么模型排序的精度比召回率更重要;如果触达成本几乎为零(比如站内弹窗),召回率就更重要。先想清楚「预测完做什么」,再决定模型怎么评估,顺序不能反。 ## 本篇要点回顾 1. 先分清三类问题:回归预测金额、分类预测是否流失、时间序列预测未来 12 周销量,类型不同则评估指标与切分方式全不同。 2. 建模六步里最容易被跳过的是基线:先跑逻辑回归或简单规则拿到 AUC 0.75 左右,才能说清复杂模型多出的提升值不值。 3. 特征只能用观察点之前的信息,少写一个「订单日期早于观察日」的条件,离线 AUC 就会虚高到 0.95 而线上崩盘。 4. 准确率 95.4% 可能毫无价值:在不平衡数据里,全猜「不流失」就有 95.0%,而模型召回率只有 16%,漏掉 84% 的真实流失用户。 5. 阈值由成本反推而非默认 0.5:干预成本 20 元、收益 200 元、成功率 30% 时,临界概率约 0.33,净收益比 0.5 阈值高 20 元。 ## 延伸阅读 - **第 05 篇|统计推断与 AB 实验**:预测回答「谁可能流失」,实验回答「发券能不能留住他」,前者是相关性,后者才是因果,两篇合起来才构成完整的决策闭环。 - **第 03 篇|描述性分析与指标体系**:流失、留存、RFM 的口径在那篇定义,标签定义含糊是预测项目失败的头号原因,回来核对口径往往能省掉一半返工。 - **第 07 篇|分析方法全景与选择**:本篇只讲了预测这一类,那篇把描述、诊断、预测、规范四类方法放在一张图里,帮助判断什么时候根本不需要建模。 - **第 09 篇|行业实战:电商与 SaaS**:电商的复购预测与 SaaS 的订阅流失,特征和阈值逻辑差别很大,那篇给出两类业务的具体拆法。 - **第 08 篇|工具使用:Excel、SQL、Python、BI**:本篇的 SQL 特征表与 Python 训练脚本只是示意,工程化的写法、环境与协作方式在那篇展开。