我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

关联规则与协同过滤:原理差异、选型判断与组合落地

关联规则与协同过滤:原理差异、选型判断与组合落地 做推荐系统这些年我收到最多的业务需求其实就两类一类是“用户买了这个你再给他搭个什么最合适”另一类是“你得让每个用户打开首页看到的都是他喜欢的东西”。这两句话听起来都在说“推荐”但底层用的完全是两套思路。前者大多是关联规则在起作用后者才是协同过滤的主场。这篇系列笔记的2.21篇我想把这两个算法摊开来讲清楚它们各自的原理是什么本质差异在哪里以及在真实业务里到底应该怎么选、怎么结合。很多人会把“关联规则”和“协同过滤”当成一回事觉得反正都是“根据用户历史行为推东西”。实际上关联规则从头到尾都不关心“用户是谁”它只在乎“哪些东西经常一起出现”而协同过滤的核心恰恰是“人”它的一切计算都围绕“你和谁像”“你喜欢的东西和什么像”展开。这个认知一旦建立起来后面所有选型和落地判断都会顺很多。1. 两个最容易在企业需求里被搞混的场景先看两个我经常遇到的业务需求我管它们叫“看起来一样、其实两码事”的经典组合。第一个场景是商品详情页底部的“搭配购”或者“一起买”。业务方的原话通常是“系统能不能告诉我买了相机的人通常还会配什么我们把三脚架、内存卡、防潮箱这些做成一键加购套餐。”注意这里需求的核心是“哪些商品之间存在稳定的组合关系”它不关心买相机的是男是女、收入如何、过去喜欢什么只关心“订单里出现相机时同时出现三脚架的概率有多大”。这是典型的关联规则问题。第二个场景是首页信息流的“猜你喜欢”。业务方的原话通常是“我得让不同用户看到的10个商品完全不一样不能所有人进来都是同一个爆款榜单。”这里需求的核心是“这个特定用户可能对什么感兴趣”系统必须为每一个人单独计算一份候选排序。这就不是共现统计能解决的了需要用到协同过滤——找到和你行为相似的人把他们的选择当作你的偏好来源。这两个场景在企业里常年被混在一起提最典型的说法就是“我们要做个推荐系统把大家都喜欢的东西推给每个人”。如果照着这个思路去建设大概率会做出一个不伦不类的东西既没有真正的个性化也没有稳定的组合转化率。所以第一步要先明确你要解决的是“商品与商品之间怎么搭配”的问题还是“用户与用户之间怎么借力”的问题。这个判断直接决定了后面选什么算法、做什么工程架构。顺带说一句业界有个流传很广的经典案例说某超市发现啤酒和纸尿布经常被一起购买于是把这两个货架摆到一起销售明显提升。这个案例里的挖掘思路就是关联规则它的本质是发现“订单层面的共现规律”并不需要知道买纸尿布的是爸爸还是妈妈。这一点恰恰是它和协同过滤最大的分水岭。2. 关联规则先用共现说话再看提升度关联规则是一套从“事务数据”里挖掘规律的算法体系。所谓事务数据在电商里就是一张张订单里的商品集合在线下零售里就是一张张购物小票。每一行数据记录的是“这笔交易里出现了哪些商品”至于用户是谁、怎么逛的、为什么买统统不需要。正是这种数据形态决定了它擅长回答的问题范围。2.1 支持度、置信度、提升度三个指标定位一条规则先定义清楚一条关联规则长这样X → Y表示“买了X的人也会买Y”。要判断这条规则成不成立标准算法里主要看三个量。支持度Support衡量的是规则覆盖的交易范围。它的计算公式是Support(X → Y) 同时包含X和Y的订单数 / 总订单数。比如一共有1000笔订单其中200笔同时包含“咖啡”和“纸杯蛋糕”那么规则“咖啡 → 纸杯蛋糕”的支持度就是200 / 1000 20%。支持度解决的是“这条规律是不是足够普遍”的问题。如果一条规则只出现在3笔订单里哪怕置信度是100%也没有商业价值因为你没法靠一个只覆盖3笔订单的组合去做大促方案。置信度Confidence衡量的是规则的可靠程度。它的计算公式是Confidence(X → Y) 同时包含X和Y的订单数 / 包含X的订单数。接上面的例子假设1000笔订单里有600笔包含咖啡其中240笔同时包含咖啡和纸杯蛋糕那么置信度就是240 / 600 40%。也就是说用户买咖啡之后有40%的概率会再买纸杯蛋糕这个数字看起来已经不算低了。但这里有个坑我见过不少初学者只看置信度结果被它坑得很惨。你再看看另一个数字纸杯蛋糕在全部1000笔订单里出现了300次也就是它的独立购买概率是30%。买咖啡的人里有40%买蛋糕而整体顾客里本身就有30%买蛋糕——咖啡对蛋糕的“带动作用”其实相当有限。这时候就需要第三个指标出场。提升度Lift衡量的是“X出现时Y出现的概率相比Y整体的出现概率提升了多少”。计算公式是Lift(X → Y) Confidence(X → Y) / (Y出现的订单数 / 总订单数)。继续用刚才的数据算一下40%除以30%提升度约等于1.33。大于1说明X对Y的出现有正向促进作用等于1说明X和Y相互独立小于1说明X的出现反而会抑制Y的出现。实战中我一般会要求提升度至少大于1.2甚至1.5否则这条规则的“强关联”成色不足。下面用一个更直白的反例说明只看置信度有多危险。假设1000笔订单里500笔都有牛奶400笔有面包200笔两者同时出现。规则“牛奶 → 面包”的置信度是200 / 500 40%而面包本身的整体出现率也是400 / 1000 40%提升度正好是1.0。这算什么这说明牛奶和面包完全无关它们只是各自都是畅销品而已。如果你不懂提升度光凭置信度40%就去做“牛奶配面包”的套餐大概率白忙一场。2.2 Apriori算法是怎么从海量商品里找频繁组合的第三个指标解决“这条规则强不强”的问题但工程上还有个更现实的问题一家超市几千个SKU商品之间的两两组合就有几百万种三三组合更是天文数字总不能全算一遍吧Apriori算法的核心贡献就是在这里。Apriori的精髓是一条先验性质如果一个项集是频繁的那它的所有子集也必须是频繁的。反过来说如果“三脚架”本身出现次数就很少不满足最小支持度那么“三脚架 相机 内存卡”这个组合也绝不可能频繁。利用这条性质算法可以逐层生成候选集先从所有单品里筛出频繁项再在频繁单品的基础上生成两两组合候选筛出频繁二元项集再生成三元组合以此类推。每一层都只保留支持度达标的项集这样剪枝之后真正需要计算的数量级就小多了。实际工程里我一般会用现成库来做这一步没必要自己从头实现。比如用Python里的mlxtend库把订单数据转换成“订单 × 商品”的0/1矩阵之后两行代码就能跑完频繁项集和规则生成from mlxtend.frequent_patterns import apriori, association_rules # basket 是订单×商品的0/1 DataFrame frequent_itemsets apriori(basket, min_support0.02, use_colnamesTrue) rules association_rules(frequent_itemsets, metriclift, min_threshold1.2)注意这里的两个参数min_support决定了你愿意接受多冷门的组合metriclift表示用提升度作为筛选规则强度的标准。实际业务里min_support不要设太低否则会跑出一堆只在个别订单里出现的噪音规则也不要设太高否则只剩那些人人都在买的热门品组合毫无增量价值。我一般会结合订单量来定比如一天订单量在几万笔时min_support取0.01到0.05之间先跑一版再根据结果调整。2.3 关联规则的边界能发现组合却看不见“人”把原理梳理完之后你一定也感觉到了关联规则自始至终都在处理“物与物”的关系。它输出的是“X→Y”这样一条条可读性极强的规则非常适合放在运营和销售团队面前去讨论这是它的巨大优势。因为业务方能够看懂、能够沟通落地也就更容易。但它的劣势同样明显它没有用户的维度。它不能回答“用户小张今天更可能喜欢哪个单品”只能回答“用户小张如果把A放进了购物车他买B的概率会变高多少”。而且关联规则对行为强度的利用也很弱它只看“买/没买”这个布尔值不会区分用户是强偏好、随手买还是买来退货。在需要精细化个性化的场景里这套逻辑就不够用了。3. 协同过滤同一个矩阵里藏着人和物的偏好关系如果说关联规则是在一堆订单里数共现次数那么协同过滤就是在一个“用户 × 物品”的矩阵上做相似性推理。它最大的特点是它从设计之初就把用户这个维度放进了核心位置所有推荐行为都围绕“某一个具体用户”展开。3.1 从用户-物品矩阵说起协同过滤的输入通常是一个打分矩阵行是用户列是物品Cell里的值可以是显式评分比如5分制、10分制也可以是隐式反馈比如点击次数、观看时长。在没有评分数据的场景下我们也会把“是否购买”“是否点击”编码成0/1放进矩阵。矩阵一旦建立算法要做的事情就非常核心如果两个用户的历史行为高度重合那么他们未来的选择也大概率类似可以把其中一个用户看过的、另一个用户没看过的物品推荐给后者。这就是基于用户的协同过滤UserCF。同样的逻辑也可以用在物品上如果用户喜欢的物品A和物品B经常被同一个用户群选择那么喜欢A的人也值得收到B的推荐这就是基于物品的协同过滤ItemCF。相似度的计算方式有很多种最常用的是余弦相似度。假设两个用户分别有打分向量u和v那么它们的相似度是cos(u, v) (u · v) / (|u| × |v|)具体到代码里就是这样import numpy as np def cosine_sim(u, v): return np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))这个公式的理解方式很简单把每个用户在所有物品上的打分看作一个高维空间里的向量如果两个向量方向越接近说明这两个用户的行为模式越像。如果只有0/1数据用Jaccard相似度也很多Jaccard衡量的是两个用户共同打交道的物品占他们所有覆盖物品的比例公式是交集大小除以并集大小。3.2 UserCF 和 ItemCF 的分岔路口到这里协同过滤内部已经分裂成两条技术路线了。很多人卡在这里不知道怎么选我给的判断口径是这样的UserCF更适合“用户少、物品多、强调社交感”的场景。它的逻辑是找到和你品味相似的人直接借用他们的行为来给你推荐。所以在内容社区、校园网络这类用户群体比较聚焦的场景里UserCF能制造一种“我朋友都在看这个”的传播效应。但它的短板是计算成本高因为每一对用户都要算一次相似度用户量一大就撑不住而且它的实时性也不理想用户行为一变整个相似关系就要重新算。ItemCF更适合“用户多、物品相对稳定”的电商、视频平台等场景。它先根据全体用户的行为计算出物品之间的相似度再根据用户当前正在看的物品扩展出推荐列表。它的最大优点是稳定物品种类不像用户那样频繁增长“物品A和物品B类似”这个结论可以离线算好存下来线上直接查表。这也是为什么绝大多数电商场景最终都倒向ItemCF而不是UserCF。我举个例子帮你快速区分。用户甲最近看了一部科幻片ItemCF推荐给他的是“其他看了这部科幻片的用户也看了的科幻片”或者“同一导演的同类作品”UserCF则是去找“行为上最像甲的另一位用户”把那位用户最近看的一堆片子塞给甲哪怕那些片子和科幻毫无关系。前者围绕“物以类聚”后者围绕“人以群分”这就是两条路线的本质分岔。3.3 稀疏性协同过滤真正的拦路虎协同过滤有一个绕不开的痛点就是矩阵稀疏。一个用户一辈子能接触的物品相对平台动辄百万千万的物品池来说只是沧海一粟。100万用户、1000万物品的矩阵里绝大部分格子都是空的可能99%以上的位置都没有数据。这会带来一个直接的连锁反应两个用户如果各自只和很少的物品有过交互他们的共同覆盖区域可能小得可怜甚至为空算出来的相似度要么噪音很大要么干脆没法算。这个问题在冷启动阶段暴露得特别明显——新用户刚注册什么都没点系统根本无从猜他喜欢什么新商品刚上架没有交互记录也不会进入任何推荐候选池。后面我会专门讲怎么用关联规则来“补位”事实上很多工业级系统正是靠各种规则来兜冷启动的底。4. 本质区别到底在哪里共现关系 vs 偏好矩阵其实前面两套原理讲完本质区别已经呼之欲出了。我再用一张表把核心差异收拢一下方便你在做技术方案时快速对照。对比维度关联规则协同过滤数据视角物与物的共现关系用户与物品的偏好关系输入数据事务记录订单、购物小票用户行为/评分矩阵是否关心用户个体不关心只看订单集合高度关心以用户为单位对行为强度的利用弱只看买/没买强可用评分、时长、次数核心输出X→Y规则置信度、提升度每个用户独立的候选排序可解释性强“买了A的人常买B”中低“因为你喜欢A所以推荐B”典型场景购物篮、捆绑套餐、交叉销售首页猜你喜欢、内容流排序看过这张表你应该能抓住那条主线关联规则回答的是“什么和什么适合放在一起出现”协同过滤回答的是“这个用户自己最可能喜欢什么”。前者在挖掘数据里的统计规律后者在模拟人的选择偏好。它们处理的信息维度不在一个层级上这也是为什么哪怕输入数据完全一样两种算法产出的推荐形态也完全不同。从信息密度上再补一刀。关联规则的输入可以看作一个布尔共现矩阵它只关心“同时出现/不同时出现”这个二元状态协同过滤的输入则天然包含了偏好强度同样是看了三个商品看了30秒和看了3小时表达出的兴趣浓度完全不一样。所以协同过滤理论上能捕捉到更细颗粒度的偏好差异但代价是它对数据的数量和质量要求也更高。这也是为什么很多小体量项目里关联规则的冷启动效果反而比协同过滤友好得多。5. 回到业务现场什么场景用关联规则什么场景用协同过滤理论说得再多最后还是要落到选型上。我在实际项目里看过的判断框架是这样的先问自己一句话我到底要推荐“一组搭配”还是推荐“一个人想看的一个列表”这个问题的答案直接决定了算法方向。5.1 关联规则的主场购物篮、捆绑套餐、交叉销售凡是订单里天然存在“组合购买”模式的业务关联规则都是优先选择。比如线下超市、便利店、水果店系统要解决的核心问题是“怎么把客单价做上去”怎么设计货架动线、怎么设置第二件半价。这些动作讲究的是“用户买了A之后要不要顺手带一个B”本质上就是一个关联规则问题。我也接过生鲜类的项目里面最有效的推荐不是“猜你喜欢吃啥”而是“你加了牛肉是不是该配一包黑胡椒酱”“买了三文鱼要不要顺便带芥末”。这种搭配逻辑非常明确用户接受度也高更适合直接做成下单页的加购模块。当时用协同过滤调了很久效果反而不如跑一遍关联规则来得实在因为这类消费具有很强的组合惯性它更多是规律问题不是偏好问题。关联规则在线下陈列里也特别常见。比如把高频搭配的商品放到相邻货架在收银台附近放和畅销品搭配出现率高的低频品这些都是规则直接驱动的商业动作。5.2 协同过滤的主场内容分发、个性化首页、社交推荐影视、音乐、资讯、短视频这类场景则是协同过滤的天下。这些平台物品数量巨大用户又希望看到“每个人不一样”的内容流。拿视频推荐举例一个初来乍到的用户看了几部科幻片之后协同过滤能立刻从大量和他行为相似的用户里找出更多科幻、悬疑类内容这种推荐质量远不是“买了A的人还买B”式的搭配规则能比的。内容型业务还有一个特点就是用户偏好比购买行为复杂得多同样一个用户可能同时喜欢喜剧和纪录片也可能在工作日和周末的观看倾向完全不同。协同过滤的矩阵模型能通过多个用户的共同行为把这些交叉偏好都编码进去这是单纯的共现统计很难做到的。电商首页“猜你喜欢”我也更倾向于用ItemCF做主算法因为物品相似度可以在后台提前算好线上按用户历史点击记录直接拉候选响应快、稳定效果也经得起检验。相比起来关联规则更适合出现在详情页、购物车页做“临门一脚”的转化工具而不是首页流的主排序逻辑。5.3 冷启动阶段先用规则撑住再平滑过渡到协同新用户没有行为数据时协同过滤是没有用武之地的。这时候关联规则反而能发挥价值用户哪怕只点了当前正在看的这一个商品系统也能立刻根据“当前商品 → 搭配商品”的规则推出一组相关候选。比如用户点开了一个手机壳规则立刻推同机型的高清膜、支架、充电头用户点开了一本书规则推同一系列的续作、同作者的另一本。这种推荐不依赖任何用户历史画像却能保证“相关性”不会跑偏。当用户积累了一定行为数量之后再把它逐步切到协同过滤的个性化通道上。这也是工业界非常常见的“冷启动过渡”方案前几次访问以规则和热门兜底为主访问到第十次、第二十次之后开始大量引入协同过滤结果。等用户行为足够稠密关联规则的占比就可以降下去只在购物车、结算页这些特定入口保留。5.4 一张选型表看清看透不同业务阶段、不同产品场景不妨照着下面这张表来做决策。业务诉求推荐选择原因提升购物车客单价、组合转化关联规则直接输出搭配关系可解释、可运营线下货架陈列、品类摆放设计关联规则提供商品间关联强度指导空间布局首页信息流千人千面协同过滤ItemCF优先需要针对个体用户排序同一用户不同时期的长线偏好变化协同过滤UserCF优先能捕捉群体流行趋势变化新用户/新品冷启动关联规则 热门兜底不依赖个体历史能立刻响应推荐理由需要展示给用户关联规则“经常一起购买”本身就有说服力6. 一个系统里同时用两种算法分层设计的落地思路最后说点工程上的实操。我见过很多团队在“选A还是选B”上纠结很久但实际上成熟的推荐系统里这两种算法通常不是互斥的而是分层配合的。最常用的结构是“规则做召回、协同做排序”。第一步用关联规则从前端当前上下文里捞出一批强组合候选。举例来说用户在商品详情页看了一台相机规则模块立刻捞出“和三脚架、内存卡、相机包”这些高频组合形成一个规模小但相关性强、理由清晰的候选集。第二步把这个候选集交给协同过滤模块按当前用户的偏好特征重新排序——如果这个用户是个刚入门的摄影爱好者就优先排入门级配件如果他是个专业人士就优先排高端型号。这样既保留了规则的“相关性”又注入了协同的“个性化”。另一种常用姿势是反过来协同过滤负责生成大范围候选关联规则负责给出推荐理由。这个在很多内容平台也有应用推荐结果列表里偶尔会出现一条“因为你看过A所以推荐B”的文案这里的“因为”其实不一定来自协同过滤内部而是用关联规则补了一个人话版的解释。用户看到推荐理由之后点击意愿会明显提高这个现象在很多A/B实验里都能复现。工程实现上还有几个细节值得注意。关联规则的频繁项集和规则列表需要定期增量更新一般按天重算比较稳妥太长会漏掉季节性变化太短则会产生抖动协同过滤相似度矩阵也不用每次都实时计算离线算好、每小时或每天加载到线上服务里就好线上只做查表和排序。两个模块最好分别设计监控规则模块关心的是“带出率、套餐加购率”协同过滤模块关心的是“点击率、停留时长、转化率”防止后端用同一个指标糊弄过去。我在实际项目里最大的感受是不要试图让一个算法同时回答两个不同的问题。很多团队把协同过滤调了一个月也没达到“搭配购”的预期回过头才发现业务要的其实是规则挖掘也有团队辛辛苦苦堆规则想让首页“千人千面”起来结果推来推去都一样。先想清楚业务要的是共现规律还是用户偏好再决定算法栈这条路通常不会走偏。
返回列表