ARTICLE DETAIL

资讯详情

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

《模型不玄学》第9章 聚类是什么:让行为像的人自己抱成团

《模型不玄学》第9章 聚类是什么:让行为像的人自己抱成团 第9章 聚类是什么让行为像的人自己抱成团小白一句话聚类就是机器自己把行为像的用户归到一伙你不用提前告诉它分成几类、每类长什么样——它只看特征谁离得近就谁一伙。前面第2章说过本项目有两套模型。活跃度预测监督回答未来 7 天回不回来那是第 5 部分的主菜。这一章先讲另一套行为分类无监督。它回答的是另一个问题——这群人里谁和谁的行为风格是一类为什么需要这个因为活跃不活跃和行为是什么风格是两码事。一个每天来领、五种任务都碰的人和一个每周只来一次、只领一种任务的人活跃度可能都不低但行为画像天差地别。把这种风格摸清楚既能单独用给运营分群也能喂给后面的活跃度模型当额外特征。而它最大的特点是不需要标签。我们手头没有这个用户属于哪类行为的标准答案就让机器自己从数据里找结构。聚类的直觉距离 行为像不像聚类的前提只有一个能把每个用户变成一串数字特征向量。这件事第7章已经做完了——每个用户到评分日为止都有一份行为指纹新近度、频率、持续性、趋势、偏好那些。有了这串数字“两个用户行为像不像就可以翻译成他俩的向量离得近不近”。距离近 → 行为像 → 该一伙距离远 → 行为不像 → 分开。最常用的算法是K-Means它的想法朴素到能一句话讲完先随便撒 k 个中心点把所有点分给最近的中心然后挪中心到各堆的重心再重新分再挪中心……反复几轮直到中心点不动了分堆就定了。就这么来回迭代机器慢慢把空间切成几块每块里的人彼此最像。上手用示例数据跑一个最简单的聚类我们用第7章算好的行为指纹先挑两个最直观的维度来看——全期活跃天数来得多不多和任务种类数行为丰富不丰富。把 57 个有充分历史的用户评分日前零记录的冷启动用户先排除画到这两维上再让 K-Means 自动分 3 堆。代码用第4章装好的 scikit-learn几行就够importnumpyasnpfromsklearn.clusterimportKMeans# fps: 第7章算好的行为指纹列表每人含 dall(全期活跃天数)、ntask(任务种类数) 等X2np.array([[fp[dall],fp[ntask]]forfpinfps],dtypefloat)kmKMeans(n_clusters3,random_state20260827,n_init10).fit(X2)forcinrange(3):mem[fp[uid]forfp,ainzip(fps,km.labels_)ifac]cx,cykm.cluster_centers_[c]print(f簇{c}: 中心({cx:.1f}天,{cy:.1f}类) 人数{len(mem)})跑出来的真实结果簇中心全期天数, 种类数人数这一堆的人大概什么样簇 0(10.9 天, 5.0 类)24来得挺勤、五种任务都碰簇 1(3.1 天, 2.2 类)20来得稀、只碰一两种任务簇 2(19.7 天, 5.0 类)13几乎天天来、五种任务全碰看这张表机器干了件你肉眼也做得到、但 57 个人时懒得做的事它把几乎天天来且啥都领的人簇 2、来得中等且啥都领的人簇 0、“来得稀且只领一两种的人簇 1自动隔开了。没人告诉它高频多任务”低频少任务这些词它只看了数字就近乎还原了这些行为模式。横轴是全期活跃天数纵轴是任务种类数。蓝色点簇 0和中绿点簇 2都集中在 y5 附近但它俩被横轴切成了中频多任务和高频多任务两堆橙色点簇 1全在低区y 值通常只有 1~3。黑色 X 是每个簇的中心。三堆几乎不打架边界清楚——这就是机器按距离抱团的结果。簇编号只是代号不是等级新手最容易犯的错是看到簇 0、簇 1、簇 2顺手当成弱、中、强三等。这是错的。K-Means 给簇编号纯粹是第一堆、第二堆、第三堆的代号编号大小跟强弱无关。上面表里簇 0 中心是 (10.9, 5.0)、簇 2 是 (19.7, 5.0)——簇 2 比簇 0 更活跃但编号反而更大。如果把编号当等级结论就反了。所以无监督聚类产出的是分群不是打分。这堆人行为像、那堆人行为像但哪一堆好哪一堆差模型不关心也没资格关心——它根本没见过标签。这也是为什么本项目把行为分类和活跃度预测拆成两个模型第2、3章讲过分群告诉你他是哪类人预测才告诉你他会不会回来两件事不能混。维度一多就得先把尺子拉平标准化刚才只用两维天数和种类数都是十以内的小整数尺度差不多直接喂进去问题不大。但真实聚类用的是第7章那一整排特征全期活跃天数顶多 22总奖励金额却上百趋势在 −3~1 之间偏好熵在 0~2.3 之间。不处理的话K-Means 算距离时会被数值大的维度牵着走——总奖励几百轻轻一动就比天数差十几还大天数、趋势这些小维度直接被淹没聚类就变成按花钱多少分堆了不是我们想要的行为风格。解决办法是标准化把每个特征都变成均值 0、标准差 1相当于把所有尺子拉到同一把刻度上再比距离。scikit-learn 里一行搞定fromsklearn.preprocessingimportStandardScaler keys[recency,d7,d14,dall,longest,trend,ntask,top_share,entropy,amount]rawnp.array([[fp[k]forkinkeys]forfpinfps],dtypefloat)XsStandardScaler().fit_transform(raw)# 每列都变成均值0、标准差1我们对标准化后的 10 维特征再跑一次 K-Means这次分 5 堆附件/04_行为聚类篇/behavior_cluster_intro.py里是同一段逻辑结果很有意思簇人数中心原始尺度节选这堆的行为风格簇 05全期 1.2 天 / 1 种 / 主占比 1.0 / 熵 0极稀疏、只领一种几乎冷启动边缘簇 110全期 12.1 天 / 5 种 / 趋势 0.6 / 熵 2.3中高频、啥都领、还在涨簇 215全期 3.7 天 / 2.7 种 / 趋势 0低频、只碰少数几种、持平簇 315全期 10.5 天 / 4.9 种 / 趋势−1.8/ 熵 2.2中高频、啥都领、但在掉簇 412全期 20.0 天 / 5 种 / 趋势 −0.2 / 熵 2.3近乎天天来、啥都领、稳注意簇 1 和簇 3都是中高频、五种任务都碰但簇 1 的趋势是 0.6在涨簇 3 的趋势是 −1.8在掉。靠全期天数这一维这两堆会被混在一起加上趋势维度、标准化后一起看机器就把正在变凉的高频用户单独挑出来了。这正是多特征 标准化的价值——它抓到了单看一个维度抓不到的结构。这张图不是用原来的天数/种类数坐标了而是把 10 维特征先标准化、再聚类最后用 PCA 压缩到 2D 给你看分群结构。横纵轴PCA-1/PCA-2本身已经没有天数或奖励那么直观的含义它只是帮你肉眼判断5 个簇是不是各据一块、彼此分开。从图上看橙色、蓝色、紫色、红色、绿色五坨点基本各自抱团说明高维聚类确实切出了单看一两维切不出的细分结构。这 5 堆只是演示用 k5真实项目里 k 选几、每堆叫什么是下一章跑通行为聚类要专门讲的。聚类不是只有 K-MeansK-Means 好懂好用但它有脾气得先指定分成几堆k、对形状不规则的堆不敏感、对异常点比较脆。真实项目里行为分群也常用GMM高斯混合模型——它不光告诉你归哪堆还给你属于每堆的概率更适合行为有渐变、不好硬切的情况。本项目行为分类用的就是这一类思路。不过对入门来说先把 K-Means 的直觉吃透就够了它本质上就是按距离把像的人抱团其余算法是在这个想法上补各种短板。动手自己看机器怎么分打开附件/04_行为聚类篇/behavior_cluster_intro.py依赖第4章的 numpy scikit-learn跑一遍python 附件/04_行为聚类篇/behavior_cluster_intro.py你会看到和上面表格一致的簇中心和人数。然后做两件事不用改算法也能体会到聚类的意思先把簇编号遮住自己目测分 3 堆。看着 (全期天数, 种类数) 这两个数你会怎么把 57 个人分成高频多任务 / 中频多任务 / 低频少任务再和机器输出的簇对一下是不是八九不离十想想簇编号能当分数吗。机器给簇 2 编了最大的号但簇 2 只是几乎天天来那一堆。如果运营拿簇编号当活跃等级去发奖励会发生什么把你的答案和本章簇编号无意义那节对照一下。打开生成的图再和表格对一下。跑附件/04_行为聚类篇/behavior_cluster_viz.py会输出附件/04_行为聚类篇/behavior_cluster_2d.png和附件/04_行为聚类篇/behavior_cluster_pca.png。先遮住图例自己给三个色块各起一个人话名字比如几乎天天来、啥都领再对照上面表格里的簇中心看你对不对得上。把聚类 按距离自动抱团、编号只是代号、多特征要先标准化这三件事记牢下一章就能顺着它把真实的行为分群跑通、再给每堆起上人话名字。本章配套脚本附件/04_行为聚类篇/behavior_cluster_intro.py打印簇中心和附件/04_行为聚类篇/behavior_cluster_viz.py生成配图。二者都基于 scikit-learn所需的 numpy、scikit-learn、matplotlib 已在第4章附件/00_公共/requirements.txt中列出环境搭建见第4章。
返回列表