第二编 Section End
做一个电商用户分群与流失预警系统:非线性建模与表示问题如何进入工程实践
第二编到这里,读者已经看到机器学习的发展为什么不会停留在第一编的线性框架中。第一编告诉我们,学习问题可以被写成监督学习、经验风险最小化、线性回归与概率判别的问题;但第二编进一步说明,一旦真实任务中的结构开始变得更复杂,线性模型、原始特征和浅层表示很快就会暴露出边界。于是,新的问题自然出现了:在真实工程里,程序员究竟是怎样感觉到“线性方法已经不够”的?又是怎样一步步把特征映射、核方法、聚类和降维这些看起来更抽象的数学对象,真正放进系统里的?
这一节的目的,就是把这件事写清楚。这里选择的工程任务,是为一个电商平台建立“用户分群与流失预警”系统。这个任务很适合作为第二编结尾的案例,因为它同时包含两个方向:一方面,团队想知道平台上的用户自然会分成哪些群体,这对应无监督学习;另一方面,团队还想预测哪些用户可能即将流失,这对应非线性监督学习。也就是说,它非常适合用来展示第二编中“表示问题”和“非线性问题”是怎样在一个工程系统里相遇的。
我们可以把自己放进一个真实团队里来想象这个需求。平台运营部门提出的问题通常不会是“请做一个核方法实验”,而会是更直接的业务表达:我们想知道不同类型的用户到底在平台上表现出哪些差异;我们也想尽早识别那些快要不再下单的用户,以便有针对性地做运营触达和优惠激活。于是,一个看上去像业务分析的问题,很快就会自然变成第二编所讨论的核心问题:如何通过更好的表示发现结构,又如何通过更强的非线性判别能力识别风险。
1. 先把业务问题拆成两个学习任务
程序员接到这样的需求后,第一步仍然是先把问题拆清楚,模型选择可以稍后再谈。这里至少有两个不同的任务。
第一个任务是用户分群。它要解决的,是从行为数据中发现平台上的用户是否会自然形成若干群体,例如高频复购用户、价格敏感用户、只在活动期出现的用户、浏览很多但购买很少的用户等。这个任务关注的是数据内部结构本身,并不以立刻预测一个外部标签为目标。这个问题的特点是:标签事先并没有给定,它需要从数据内部结构中逐步显现出来。
第二个任务是流失预警。这个任务则更接近监督学习,因为平台通常可以先定义“什么叫流失”。例如,若一个用户在过去 60 天曾有活跃购买行为,但之后连续 45 天没有再访问或下单,就可以把他标成潜在流失样本。于是,系统要做的,就是根据过去一段时间的行为特征,预测某个用户是否会进入这个流失状态。
这样一拆开,第二编的理论主线就已经进入工程了。分群任务对应的是无监督学习与表示问题,流失预警任务对应的是非线性监督学习与判别边界问题。更重要的是,这两个任务并不是彼此孤立的。工程团队很快会发现,分群结果常常能帮助理解流失模式,而流失预测模型的误差又常常提示“当前特征表示还不够好”。也就是说,表示与判别在真实系统里往往是交替推进的。
2. 数据准备:原始日志并不会自动变成可学的表示
对于电商平台而言,最原始的数据往往来自用户行为日志、交易流水和基础属性表。常见字段包括:最近 7 天、30 天、90 天的访问次数,浏览商品数,加入购物车次数,下单次数,支付金额,平均客单价,退款次数,优惠券使用率,品类偏好,访问时间分布,来源渠道,设备类型,注册时长等。
从数学上看,程序员此时仍然是在构造样本,只不过样本对象已经从“单个房源”变成了“单个用户在某段时间内的行为摘要”。设第 $i$ 个用户的表示为
其中 $p$ 表示特征维度,$x_i$ 的每个坐标都对应一个被整理后的统计量或行为特征。
这一步和第一编最大的不同在于:这里的原始输入远比房价任务更不自然。用户行为是连续发生的时间序列,不同于一行已经整理好的结构化表格。因此,程序员首先要做的,往往是先定义观测窗口。比如,把“过去 30 天内的行为”作为输入窗口,把“接下来 15 天是否流失”作为预测目标窗口。只要这个窗口一改,特征的统计意义和标签定义就都会变化。
这件事在工程里非常关键,因为它说明输入空间 $\mathcal X$ 并不是给定不变的,它需要由程序员通过窗口切分、特征汇总和行为编码一步步设计出来。也就是说,第二编中的“表示问题”在数据整理阶段就已经开始了,并不是后面才突然出现。
与此同时,数据准备还要面对几个很典型的现实问题。第一,用户行为极不均匀。少数高活跃用户会产生大量记录,而大量普通用户几乎只有零散行为。第二,原始统计量的量纲差别很大,例如“访问次数”和“总支付金额”往往不在一个尺度上。第三,某些看似简单的字段其实带有很强的偏态分布,例如支付金额、优惠券使用次数和商品曝光量。
这些问题一旦进入工程,就会直接影响第二编中的数学对象。比如,如果程序员不先处理尺度差异,那么后面的距离计算、聚类目标和核方法都会被极端量纲主导;如果不先定义清楚观测窗口,那么所谓“用户表示”本身就不稳定。换句话说,这一阶段看似还是“数据工程”,但实际上已经在为后面的特征空间、相似性结构和判别边界做准备。
3. 程序员为什么会开始做非线性特征工程
当第一轮特征整理完成后,团队通常会先跑一个最基础的线性分类模型,看看流失预警是否已经有足够效果。此时往往会很快出现一个熟悉现象:某些局部模式是明显存在的,但线性模型怎么调都抓不住。
例如,用户访问次数过低当然可能意味着流失,但“访问很多却一直不下单”的用户也可能是高风险群体;再例如,总支付金额高的用户不一定稳定,因为有些只在大促期间集中下单;又例如,浏览和加购之间的比例,往往比它们的绝对值更有信息。这些现象都有一个共同特点:它们不是单个原始变量的简单线性作用,而更像是变量之间的交互、比率和局部组合关系。
于是,程序员会自然开始做第二编意义上的特征映射。比如,构造“加购率”“下单转化率”“最近 7 天与最近 30 天活跃比”“折扣敏感度”“高价品类占比”“夜间活跃比例”等新特征。从工程角度看,这叫手工特征工程;从数学角度看,它等价于把样本从原始空间映射到一个更丰富的特征空间。
若把原始特征记为 $x$,而构造后的新表示记为 $\phi(x)$,那么模型实际上已经从
转成了
这里,$\phi(x)$ 表示特征映射,$w$ 表示映射后空间中的参数向量。这个式子的意义非常直接:工程上看起来只是“多加了几列手工特征”,但数学上本质上是在更高维或更复杂的表示空间中重新建立线性模型。
从程序员视角看,训练在这里也会随之变化。原来训练的是原始矩阵 $X$,现在训练的则是映射后的矩阵
程序员通常会做这样一条迭代链:先加一批交互特征,再重新训练模型,然后看验证集 AUC、召回率或分段表现有没有改善;如果效果变好,就保留这批映射;如果效果没变好,甚至更不稳定,就删掉或重构。也就是说,第二编中的“特征映射”在工程里对应的是一轮轮“设计表示 -> 重新训练 -> 观察边界是否更合理”的实验过程,而不只是一句抽象理论。
4. 用户分群:无监督学习是怎样进入系统的
当团队只盯着流失标签时,常常会遇到另一个问题:模型虽然能给出概率,但运营团队还是会问,“这些高风险用户到底是些什么人?”这时,单纯的监督模型不一定能给出令人满意的结构解释。于是,用户分群任务就会真正派上用场。
设全部用户表示为
程序员希望把它们划分成 $K$ 个群体,并为每个群体找到一个代表中心
若采用 k-means,那么工程上真正优化的目标是
这里,$\|x_i-\mu_k\|_2^2$ 表示用户 $x_i$ 到第 $k$ 个簇中心的平方欧氏距离。这个式子在业务中的含义很容易理解:希望同一簇里的用户彼此相似,不同簇之间则尽量分开。
从程序员角度看,训练 k-means 并不像监督学习那样有“标签”和“损失下降曲线”,它更像一个反复执行的交替过程。第一步,先随机或按某种启发式方式初始化簇中心;第二步,把每个用户分配给最近的中心;第三步,重新计算每个簇的均值作为新中心;第四步,不断重复,直到簇分配基本稳定。
这里最值得注意的是,第二编中的无监督学习在工程里并不是“没有标签,所以就随便跑一下聚类”。相反,程序员会非常关心几件事:不同的标准化方式是否改变了簇形状;簇数 $K$ 变动后结果是否稳定;某些特征是否把聚类完全主导了;分出来的簇是否真的有业务可解释性。也就是说,k-means 的目标函数只是起点,真正可用的用户分群还需要和业务语义不断来回核对。
5. 程序员如何用 PCA 帮业务“看见”表示空间
用户分群做完之后,运营团队通常会问另一个很自然的问题:这些群体到底为什么会不同?这时,仅仅给出簇编号往往是不够的。程序员需要一种方式,把高维用户表示空间压到一个更容易观察的低维空间里。这就是 PCA 在工程里非常常见的原因。
设经过中心化后的用户表示矩阵为
其样本协方差矩阵写为
PCA 所做的,是寻找一个方向向量 $u\in\mathbb R^p$,使样本在这个方向上的投影方差最大。对应优化问题可以写为
这里,约束 $\|u\|_2=1$ 表示方向向量长度归一化。这个问题的解就是协方差矩阵的主特征向量。
对程序员来说,PCA 的价值并不在于“又学了一个线性代数算法”,而在于它提供了一种观察表示空间的办法。工程上常见做法是:先把用户向量降到二维或三维,再把聚类结果、流失标签或高价值标签叠加到图上看。如果某些高风险用户在低维空间里确实聚成片状区域,那么团队会更有信心认为“当前表示空间里确实存在稳定结构”;如果不同簇在降维后几乎完全重叠,那就说明现在的特征表示可能还不够好。
也就是说,PCA 在工程里的角色常常更接近表示诊断工具。它帮助程序员和业务方共同看到:当前的高维表示到底是不是在按某种有意义的方式组织样本,因此它通常不会被当作最终模型。
6. 当线性分类器不够时,支持向量机是怎么进入工程的
在流失预警任务中,程序员做完一轮手工特征工程后,通常会先尝试线性分类器。如果验证集表现仍然不理想,就会出现第二编的另一个典型问题:是否需要更强的非线性判别边界?
这时,支持向量机就会成为一个非常自然的候选方法,尤其是在样本规模还不算极端大、但特征维度较高且边界比较复杂的时候。它的基本思想是寻找一个区分正负样本的最大间隔边界,不会把重点放在把所有样本都尽可能贴紧地拟合上。
若把训练样本记为
则线性可分情况下的基本形式可以写为
这里,$w$ 是分类超平面的法向量,$b$ 是偏置项。这个目标的含义是:在正确分类训练样本的前提下,让间隔尽可能大。
但在真实工程中,更常见的是非线性、不可完全分开的情况。于是,程序员往往会把重点放到核方法上。也就是说,不再显式构造巨大的特征映射 $\phi(x)$,而是通过核函数
隐式地在更高维空间里做分类。
从程序员视角看,训练支持向量机通常不像线性回归那样“先看看系数解释”,而更像一个边界实验:换不同核函数、换不同间隔惩罚参数、换不同核尺度,再反复观察验证集表现。程序员真正关心的问题是:当前数据里的非线性结构,究竟能不能被某个核函数稳定地展开;如果能展开,分类边界是否比线性模型明显更干净;如果边界确实改善了,这种改善又是否会在测试集上保留下来。
这正是第二编中核方法最工程化的一面。数学上看,核函数是在隐式高维空间中做内积;工程上看,它是在帮助程序员用一种不显式写出所有高维特征的方式,试探“更复杂的边界是否真的存在”。
7. 训练在这里为什么变成了“表示、聚类、分类”三条线并行推进
如果把第二编这个系统放到真实团队里看,程序员的工作流通常不再像第一编那样只围绕一个监督模型打转,而是会变成三条线同时推进。
第一条线是表示线。程序员不断修改特征窗口、比率特征、时间衰减特征和交互特征,希望让输入空间更贴近用户行为结构。第二条线是结构线,也就是聚类与降维,用来观察当前表示空间是否真的形成了稳定群体。第三条线是判别线,也就是流失预测模型本身,用来检验这些表示究竟是否能支撑更好的边界。
这三条线在工程里会不断来回影响。例如,若聚类结果看起来很有结构,但流失预测仍很差,团队往往会怀疑“表示已经有结构,但监督标签定义可能有问题”;反过来,若流失模型效果一般,而 PCA 图上样本完全挤成一团,团队则更可能认为“现在的特征还没有把用户差异表达出来”。这说明第二编中的“表示问题”会在真实工程中直接变成“为什么这个模型学不动”的诊断问题,不会停留在独立于任务之外的哲学讨论。
因此,从程序员角度看,第二编最核心的变化,在于训练过程开始明显依赖表示设计,而不只是“模型列表变长了”。第一编中,训练更多是在既定特征上拟合参数;而在第二编中,训练越来越像“设计表示空间,再看学习是否变得容易”。
8. 工程上如何验收这个系统
到了上线前,团队不会只关心流失预测的一个总指标,也不会只关心用户分群有没有分成几堆。真正的验收往往有两部分。
第一部分是分群验收。团队通常会看簇内是否足够相似、簇间是否有明显差异、不同随机初始化下结果是否稳定,以及每个簇是否能被运营团队说出清晰含义。例如,一个簇如果表现为“高浏览、低转化、优惠券使用频繁”,那它就不仅是一个几何簇,也是一类可以被运营策略直接针对的用户群。
第二部分是流失预警验收。这里除了看 AUC、召回率、精确率之外,还会特别看不同用户簇中的表现是否均衡。因为若模型只对高活跃用户有效,对低活跃新用户几乎无效,那么这个系统在实际运营里就会非常偏。
从数学上说,这一步仍然是在问“总体风险到底该如何被近似衡量”。只不过到了第二编,风险已经不只和一个监督任务有关,还和表示是否稳定、簇结构是否可靠、边界是否足够稳健同时相关。工程验收由此变成了一个更综合的问题:我们不仅要问模型会不会分类,还要问当前表示空间是不是让分类这件事真正变得更合理。
9. 从这个案例回头看第二编,数学知识是怎样被真正用起来的
如果把整个项目重新回看一遍,就会发现第二编中的几个核心对象已经全部进入了工程主流程。
首先,特征映射在这里不再只是理论符号 $\phi(x)$,而是程序员每天都在修改和试验的交互特征、比率特征和时间窗口特征。它直接决定当前输入空间是否足够表达用户行为结构。
其次,核方法与支持向量机在这里扮演的是“试探更强边界”的角色。它们告诉团队:如果原始空间里的线性分界已经不够,那么也许应该考虑更高维表示中的线性可分性。
再次,无监督学习与聚类在这里承担的作用,是帮助团队理解数据内部是否真的存在群体结构,以及这些结构是否值得进入后续运营策略,并不只是“做个分析图”。
然后,PCA 和降维在这里是帮助程序员和业务方共同看见表示空间的一种手段,并不是独立的数学游戏。它让“高维表示是否有意义”这件事变得更可观察。
因此,这个案例最值得带走的,是一种更深的认识:第二编中的“非线性建模”和“表示问题”之所以重要,并不只是因为数学变得更复杂,更因为真实工程一旦走出第一编的线性起点,就几乎必然会遇到“原始表示不够、线性边界不够、内部结构看不见”这三类问题。第二编的理论,正是在回答这些工程上迟早会出现的问题。
10. 这个系统为什么还会继续走向第三编
尽管到这里为止,团队已经通过特征工程、聚类、降维和核方法把系统推进了一大步,但很快还会遇到新的瓶颈。最明显的一点是:手工特征工程越来越重。每当效果不够好,程序员就要继续想新的交互项、新的时间窗口、新的比率关系。换句话说,表示仍然主要依赖人工设计。
此外,核方法虽然优雅,但当数据规模继续增大时,训练和调参都会变得越来越重;而聚类和 PCA 虽然能帮助观察结构,却往往仍停留在较浅层的表示上。于是,一个更深的问题自然会出现:能不能让机器自己从数据中学出更复杂、更层次化的表示,而不再把表示设计的负担主要压在程序员身上?
这正是第三编必然出现的原因。第三编对应的,是工程实践顺着第二编继续往前走时迟早会碰到的下一层问题:既然表示如此重要,那么表示本身能不能成为可学习对象,而不只是人工构造对象?