
做行为聚类这事听起来像是有专门的算法工程师才能碰的活实际上真不是。我带团队跑用户行为聚类跑了三年多越到后面越觉得这个环节最难的从来不是模型选型而是三件看起来特别不模型的事k 到底怎么定、分出来的族群怎么起名、以及新用户进来怎么安置。这一章就把这三件事一次讲透顺便把我踩过的坑也交代清楚。先说个总体的判断标准给你放这儿好的行为聚类落地不是看轮廓系数多高不是看分了多少个簇而是看运营同事拿到簇列表之后能不能在两分钟内说出这群人是谁、他需要什么、我们该怎么触达。如果你的聚类结果让运营看半天还挠头那不管算法上多漂亮都等于没做。2. 行为聚类到底聚的是什么特征工程才是真正的第一关聊 k 怎么选之前必须先把一个问题掰扯清楚你喂给聚类算法的那些行为到底是怎么变成一行行特征向量的。很多人在这个环节栽跟头不是因为聚类算法不行而是因为他压根没搞清楚自己在聚什么。2.1 行为数据不是一堆事件是谁在什么时候干了什么行为聚类的原材料业务上叫事件日志。一次点击、一次浏览、一次下单、一次投诉、一次退款这些都是事件。但事件本身不能直接进算法必须得先回答三个问题谁干的用户 ID什么时候干的事件时间戳干了什么事件类型、对象、附带信息这三要素缺一不可。我见过不少团队从数仓里拉出来的数据只有事件类型和日期没有用户 ID也没有具体到小时的时间戳。这种数据做出来的聚类基本没法用因为行为天然带着节奏感——一个人是早上刷还是半夜刷是工作日连续来还是周末集中来这些信息的价值甚至比行为类型本身还高。行为数据的抽象逻辑可以类比成一个记了三年的账本不是问他花了多少钱这种流水账而是要问他通常什么时候花钱、花在什么品类上、决策慢还是快。每一页流水都单独看没意义放在一起才能看出习惯。2.2 行为特征怎么造从事件到向量的三条路把事件转成特征向量业内最常用的有三个思路各有各的适用场景路线一频次统计特征统计每个用户在一个时间窗口内的行为次数。比如过去 30 天登录次数过去 7 天浏览商品次数过去 30 天发帖次数。这条路最容易理解实现也最快但它的盲区在于它把行为压缩成了一个数字丢失了行为的结构信息。路线二行为占比特征如果你关心的是用户的行为结构而不是总活跃度就用每种行为占到总行为次数的比例。比如浏览行为占比 70%、下单行为占比 10%、收藏行为占比 20%。这种特征的好处是天然做了归一化高频用户和低频用户的差距被抹平了聚出来的是行为习惯相似的人。路线三序列与节奏特征更进一步把行为之间的顺序、间隔也编码进去。比如平均每次会话间隔多少小时从第一次浏览到第一次下单隔了多久行为序列中『浏览→加购→下单』路径的占比。这条路表达能力强但工程复杂度也高入门阶段可以先不做。我的建议很直白第一次跑聚类先把路线一和路线二结合起来用节奏特征放到第二版再迭代。原因很简单行为聚类是一套全链路的东西特征的复杂度直接拖累后面的特征解释和冷启动映射一上来搞得太复杂后面每一步都费劲。2.3 一个反复出现的脏数据坑归一化的方向错了特征造完之后归一化这步几乎人人都会踩坑。频次特征的天生问题是量纲差异巨大。有的用户一天登录 50 次有的用户一个月只来一次有的用户一次性下单 100 单有的用户一次下 1 单。如果不做归一化聚类结果就会被高频用户主导整个簇边界全被最活跃的那一小撮人牵着走。但这道题的关键不在于要不要归一化而在于按什么维度归一化。我自己的经验是用 z-score 或者 min-max 都行但要按特征维做不要按样本行做。按行做归一化等于把所有用户的特征长度拉到同一水平这会抹掉用户之间真实的总量差异而总量差异恰恰是聚类的重要信号。另外对占比类特征比如行为占比建议直接用原始比例值不要额外的标准化。因为它本身已经有限定范围了再标准化反而会破坏占比的语义——60% 浏览和 80% 浏览之间的绝对差异是 20 个百分点这个差异是真实且有业务意义的标准化会把它扭曲成偏离均值多少倍。3. 选 k 的实战路线从肘部法则到业务约束说完输入进入正题k 怎么选。网上聊 k 值选择永远绕不开肘部法则和轮廓系数教材里讲了一堆但老实说我见过太多团队把这俩指标用错地方。这一节我把我的完整筛选流程写出来你照着走一遍基本不会出大问题。3.1 业务约束比算法指标更靠谱第一步先不要碰算法先问业务方一个问题你们运营上最多能承接几类用户这不是一句废话。聚类结果最后要落到运营动作上每一类用户都得有人管、有对应的策略。如果你们团队只有三套运营模板那聚出 20 个簇的结果其中 17 个簇根本没有资源去运营这 17 个簇就变成了纯展览品。我做过一个电商项目销售团队明确说了我们最多做四套不同的人群策略。那聚类 k 值的天花板就是 4别的指标算出来再好看都没用。业务约束先砍成可选项再把候选 k 值缩小到一个区间。比如说业务说 3 到 5那你的工作就是在这三个数里选一个而不是在一堆数学指标里打转。这时候再用算法指标辅助判断才有意义。3.2 肘部法则知道原理也要知道它的失效边界肘部法则的原理很简单就是算不同 k 下的簇内误差平方和SSE然后画一条k 值 vs SSE的曲线。k 从 1 涨到 2 时 SSE 下降特别快涨到某个点之后下降就变缓了拐点那个 k 就是建议的簇数。它背后逻辑是经济学里的边际效用递减簇越多对 SSE 的改善越有限。但这个法子有两个容易忽略的坑。第一个坑是拐点很多时候并不明显。真实数据不会像教科书那样给你一个平滑的递减曲线经常是一条一路缓降的曲线根本没有清晰的肘。这时候你要是强行看图找拐点容易陷入主观判断。第二个坑是SSE 用的是欧氏距离它对特征的量纲和离群点敏感。如果前面归一化没做到位一个极端高频用户可能让某个簇的质心被拉偏导致 SSE 曲线整体失真。我的实操建议是SSE 算完之后不要光看绝对数值看相对下降幅度。比如 k3 时 SSE 是 100k4 时是 75k5 时是 73。从 4 到 5 的降幅只有 2.6%而 3 到 4 的降幅是 25%这时候 4 就是更合理的选择。用降幅的百分比判断比看绝对拐点靠谱得多。3.3 轮廓系数别过度依赖它的打分轮廓系数衡量的是样本与其所在簇的紧密程度和它与邻近簇的分离程度。取值范围在 -1 到 1 之间越接近 1 说明聚类效果越好。听起来很简单但我得提醒你一个反直觉的事实轮廓系数高不代表聚类结果有业务价值。我自己碰到过一个案例数据里有明显的离群流量——某种爬虫刷量行为导致一大批样本行为模式高度异常。用 k4 聚类时轮廓系数高达 0.72看着很漂亮仔细一看发现其中两个簇就是把刷量用户拆出来的两个子簇。从特征空间看分离度确实好但业务上这两个簇根本没法运营——总不能给爬虫推打折券吧所以我的用法是轮廓系数拿来横向对比不同 k 的聚类质量但绝不拿它当一票否决的指标。相比系数高低更重要的是看每个簇的业务画像是否可解释。遇到某簇特征明显异常但轮廓系数很高的情况先怀疑数据里的异常流量而不是怀疑聚类算法不行。3.4 最实用的一招降维可视化直接看簇长什么样前面几个指标都是间接判断最直接的判断方法其实很土把特征降到二维或三维然后画散点图用 k 种颜色标注簇的归属肉眼判断簇是否分开。我用 PCA主成分分析降维降到二维保留的方差一般能覆盖 60% 到 80% 的信息。画出来之后重点看三件事不同颜色的点是不是混在一起如果大量重叠说明这个 k 下分不开内核过近得调参或者换特征。有没有特别小的簇比如某个簇就三五个点小簇通常是噪声如果业务上没特殊意义可以降低 k 或者做一次离群点剔除。簇之间是拉丝状分布还是团块状分布拉丝状说明数据本身是渐变过渡的天然没有清晰边界大大降低簇数才是正事。这个方法不保证给你最优 k但它能快速排除掉一批明显冗余的 k 值。配合前面业务约束和肘部下降幅度基本能收敛到 2 到 3 个候选人再做下一步。3.5 k 折交叉验证聚类场景的用法和分类完全不同搜索热词里有k 折交叉验证我得专门说明一下分类的 k 折交叉验证思路不能直接搬到聚类上因为它依赖监督信号标签。聚类里没有标签没有正确答案所以无法拿测试集和验证集的准确率来调 k。如果你硬套交叉验证常见的错误做法是在整份数据上跑 k 折每折单独聚类再算指标最后看哪个 k 的平均指标高。这个流程的问题在于每次聚类簇的编号都是任意的不同折之间簇无法对齐你根本没法比较第 1 折的簇 2和第 2 折的簇 2是不是同一个族群。真要利用交叉验证的思路正解是分区验证法将用户随机分成训练集和保留集在训练集上确定 k 并完成聚类用保留集样本计算最近质心然后检验保留集的簇结构和训练集的簇结构是否一致比如比较簇内距离分布如果保留集分配到各簇的占比和训练集样本占比接近说明聚类结构还算稳定。如果两边的分布差距很大说明 k 选得不稳一次聚类的运气成分太高。这个方法不常见但比硬套 k 折聪明得多。4. 起名不是拍脑袋是给每个簇写人物小传选完 k或者更准确地说选完之后发现聚类结果看起来差不多能用接下来就是从 0 到 1 的第一件体验型任务给这 k 个簇起名字。很多技术团队会小看这一步觉得名字不重要后面反正要看特征的。这话只对了一半。聚类簇名承载的是技术结果和业务认知之间的翻译。没有这层翻译运营和产品根本没法把你的聚类结果用起来。4.1 起名的正确顺序先看质心画像再做业务翻译正确做法分两步第一步把每个簇的特征画像拉出来。把簇内每个特征维度的均值或中位数汇总成一张表再看一遍。第二步对照画像用业务语言描述这个群体是谁、他在平台上是怎样行为的。举个例子假设聚类出来 k3画像长这样簇编号周均登录天数浏览/加购占比下单转化率主力时段簇 05.268%/21%1.8%20:00-23:00簇 11.473%/8%0.6%12:00-13:00簇 26.833%/31%11.5%9:00-22:00如果光看编号三个簇在业务眼里没有任何意义。但如果翻译成簇 0夜间闲逛型来的勤逛得多买得少晚上是主力场簇 1午休碰运气型低频但目标明确转化率塌方簇 2高转化核心用户几乎全天在线购买决策果断这一下子就对了。运营不需要看任何特征工程细节拿着这个标签就能去设计策略。4.2 起名的质量打分能不能经受住拿样本验证的拷问我给团队定了条规矩起完名字必须做一轮抽人验证。从每个簇里随机抽 20 个真实用户出来不看算法给的簇标签只把名字和画像描述写在纸上挨个看用户的实际行为是不是符合描述。如果有超过三分之一对不上就说明名字起得太虚或者聚类结果本身有问题。这条流程看着繁琐但它能防住两件事。一是防止你被聚类结果误导有些簇画像均值和真实样本差异巨大普遍原因是聚类时用了过多高相关特征导致簇内样本不稳定。二是防止名字过度脑补人脑天生会把标签语义放大你以为夜间闲逛型的人工作日晚间活跃实际可能只是刷到短视频的时间碰巧在晚上两者运营策略完全不同。4.3 起名的常见反面案例别把特征描述当名字最常见的问题是名字过于技术化比如高 T 频次组低频短交互簇PDP 决策中枢群——这种名字别说运营看了头大你自己两周后回来看也会忘了是啥意思。我推荐一个卡名字的检查标准名字里不能出现只有你自己才懂的缩写和参数名。如果非要用英文缩写那就必须配一句业务翻译放在旁边。一个合格行为聚类簇名应该是食堂阿姨听了也能大概想象出这种人平时大概什么样的程度。如果实在起不出形象的名字有个兜底策略按核心特征标签的格式命名。比如低频-高客单-决策谨慎型虽然不够形象但至少描述是精确的后续替换形象化名字也不晚。4.4 起名和策略的映射名字背后必须挂可执行动作光有个名字还不够每个名字底下得挂上运营动作。这一步不是可选项是让聚类产生业务价值的胜负手。我的建议是起名的当天就做一张簇-策略映射表至少包含簇名、核心画像、触达偏好、可执行动作举例、预期目标。比如夜间闲逛型的策略是在晚上 8 点到 11 点推生活好物种草内容目标是提高加购率而非直接推商品卡。如果这张表做不出来说明聚类结果在业务上还是无法驱动行动的状态。这个时候别急着上线先回去想想是 k 太多了导致簇太细碎还是特征维度太少导致画像不够立体。5. 冷启动安置聚类结果怎么接住新用户聚类本身是个批处理活跑完一批老用户产出 k 个族群。但现实业务是流式的每天都有新用户进来每个新用户都想知道他是哪类人。这个衔接问题术语叫冷启动安置是所有行为聚类落地时必定会撞上的坎。遇到过很多技术团队聚类报告交上去之后运营问一句那这个用户来了该归到哪类全场沉默。因为根本没做安置方案。5.1 冷启动安置的本质聚类模型是在线分类的老大哥要理解安置方法得先理清楚聚类的本质。传统的聚类是无监督学习它只是把数据点分成集合没有学出一个输入到标签的映射函数。而安置新用户是需要一个映射函数的给我一个新用户的特征向量告诉我他属于哪个簇。这一步相当于把无监督的聚类结果转换成一个有监督的分类问题。所以安置本质是一种模型转换或者说从无监督到有监督的桥接。5.2 方法一最近质心映射法成本最低先跑起来最简单的方法是拿每个簇的质心各维特征的均值和待安置用户做距离计算找最近的那个质心把它记为用户所属簇。核心代码如下Python 伪代码import numpy as np # centroids: shape (k, n_features) def assign_to_cluster(user_vector, centroids, metriceuclidean): distances [np.linalg.norm(user_vector - c) for c in centroids] return int(np.argmin(distances)), float(np.min(distances))最省事、最容易实现效果也不错。但问题出在归属度上如果新用户和质心 A、质心 B 的距离都很近比如差距只有 0.01直接强分到 A 其实是比较武断的。边界样本的归属容错率很低。我的做法是给最近距离设定一个绝对阈值超过阈值的用户不强制归类标记为未知待确认等后续积累了更多行为数据再重新判断。5.3 方法二训练代理分类器稳定性更高如果用户基数很大或者你希望安置结果稳定可复现另一个更好的方案是用聚类产生的簇标签作为训练数据训练一个多分类器逻辑回归、随机森林、XGBoost 都行把安置过程变成一个标准的分类任务。步骤很简单跑完聚类后把每个训练样本的簇标签取出来用原始特征作为 X簇标签作为 y训练一个分类器新用户进来时分类器直接输出类别和置信度这个方法的好处有两点。一是分类器天然给置信度你可以设置阈值做拒绝判定比距离法灵活。二是分类器能捕捉非线性边界如果你的簇在特征空间里的边界是弧形的距离法会分错分类器可以学得更准。代价是需要维护一个额外的模型文件并且当聚类结果因为新数据而刷新时代理分类器也要跟着重新训练。这是冷启动安置的真正成本所在但值得。5.4 冷启动的第 0 天行为数据还不够怎么办上面的方法都预设了一个前提用户已经有足够的行为历史能算出特征向量。但新用户第一天来可能就只有一次浏览或一个注册动作特征向量全是稀疏值或默认值这时候不管距离法还是分类器效果都很差。针对这种情况我的做法是按数据成熟度分成两个世界不足阈值的行为荒疏期也就是冷启动期不代表任何簇走策略通道。比如所有新用户都进新用户探索组给它推新手任务和通用货架。过了行为阈值后的成熟安置期当该用户累积行为次数达到预先设定的最小值通常我定在 5 到 10 个关键行为事件进入正式的簇安置流程。这个设计说白了就是在信息不足时不强行做判断先用通用策略过渡等条件成熟再去细分。看似简单但很多项目死就死在非要第一天就判断一个用户是哪类人结果被稀疏数据带偏后续想要纠正非常费劲。5.5 安置的更新节奏什么时候重新训练模型安置完了后面的事情还没完。用户行为是动态的上周的低频用户这个月可能变成高频用户了。聚类模型如果一直不更新金块一个个过期。我的更新节奏建议是离线全量聚类每周或每两周跑一次更新簇质心和分类器在线安置每次请求实时计算用最邻近的质心或分类器预测周期性质量检视每月看一次各簇的用户流动情况有没有簇越来越小、有没有簇几乎没什么变化最关键的一点是模型更新后老用户的簇标签会变。这个迁移要提前和业务方沟通好否则运营会发现上个星期还是夜间闲逛型的用户怎么这周变成高转化核心用户了这套系统就失去可信度了。6. 跑通整套流程后的几个隐蔽坑前面聊了框架最后分享几个实操中特别容易翻车的细节。这些坑不踩一遍很难意识到但踩过一次就能长很多记性。6.1 时间穿越特征里混进了未来信息这是行为聚类里最隐蔽的坑。很多人在做特征工程时顺手取了用户过去 30 天行为但是数据清洗的时候没注意事件发生时间结果把用户发生行为之后的数据也卷进来了。最典型的场景你想预测的是用户当前属于哪个行为族群但特征向量里包含了文化预测之后的一个月数据。这在离线训练时看不出来问题一上线做实时联合计算时数据质量立刻崩因为线上根本拿不到未来一个月的行为。检测方法也很简单每次建模前随机抽一批用户肉眼检查特征计算窗口的时间边界确保特征生成时间永远早于预测时点。6.2 低频用户的处理基础簇的建设要提前电商、内容社区、工具类产品用户行为分布基本都是长尾的。懒惰用户占大头可能 60% 的用户一个月的关键行为次数不超过 3 次。这批人的特征向量几乎全是 0 或极小值聚类算法很容易把它们聚成一坨——不是因为他们相似而是因为他们都很空。如果你不想让低频用户主导所有簇的结构有两个办法先剔除低频用户单独成组不参与聚类当作低频沉默人群走独立的运营策略在特征里引入是否活跃级别的常量标记避免全零向量参与距离计算6.3 簇数变化带来的连锁反应策略映射表必须同步更新前面选 k 选了 3过了两个月数据变化重新聚类发现 k4 更合理。这时不只是改个数字的事所有簇名、策略映射表、代理分类器、运营动作全部要配套更新。如果哪个环节漏了线上就会同时存在两套不一致的标签体系数据治理直接崩溃。我的建议是第一次做聚类就定好族谱管理规范每个簇有个唯一 ID簇名和策略是归档存下来的不能只在代码里改数字。模型迭代时族谱工整切换新旧版本的簇对应关系提前算好哪些要合并、哪些要拆分、哪些要新生都要走评审再落地。6.4 替代沉默信号打标维护要跟进行为聚类的长期使用中一定会遇到一个情况有些簇的人群画像越来越模糊行为慢慢趋同簇内差异变大。这不是聚类算法的问题而是因为用户行为本身在演化原来的簇边界已经盖不住真实世界了。遇到这种情况我的黄金处理路径是先拿簇内距离趋势图做预判发现持续上升就留意然后做一次单体行为采样真实看看用户的行为轨迹最后才决定是调整特征、合并簇、还是重新跑一轮模型。不要一上来就重新聚类频率过高会引发标签位移危机运营追不上你的节奏。这一章的内容到这里如果你已经跟着前面的章节把行为聚类整体跑通了那这套从选 k 到起名再到冷启动安置的链路基本就是你在所有项目上都能重复使用的地基工程。说句实在话行为聚类的代码门槛真的不高但要把一个技术结果变成业务上真正能跑起来的分群体系考验的是全局观和边界感。最后分享一个我个人的心得做行为聚类要尽量把模型当成路边摊的招牌而不是实验室的黑箱。能用一个简单清晰、人人看得懂的解释就用简单的方案能用最少的簇数承载业务目标就不追求复杂精美的结构。这行做久了你会发现真正省心的模型不是最聪明的那个是最听话的那个。