基于项目聚类与时间衰减的协同过滤推荐算法:破解稀疏与兴趣漂移

发布时间:2026/10/14 18:02:50
基于项目聚类与时间衰减的协同过滤推荐算法:破解稀疏与兴趣漂移 简介这是一份面向推荐系统学习者与科研训练参与者的算法实践资料围绕项目聚类与时间衰减两大策略改进传统协同过滤解决用户兴趣随时间漂移、推荐多样性不足的问题。资源包共139个文件约113.29MB以67篇pdf文献、12个py脚本、6个dat数据集及doc实验记录为主另含pptx汇报、xml配置与png图表覆盖理论参考、代码实现与实验数据三类内容。其中Python代码涉及用户-项目交互矩阵构建、余弦相似度与皮尔逊相关系数计算、基于用户或项目的协同过滤建模以及时间衰减因子的计算与应用曲线拟合部分借助艾宾浩斯遗忘曲线模拟记忆规律用于优化衰减参数。参考的硕士论文与期刊文献为项目聚类和时间衰减提供理论支撑。目前已有934人学习适合希望从原理到代码完整复现改进型协同过滤、并理解时效性建模思路的读者参考。1. 基于项目聚类与时间衰减的协同过滤推荐算法为什么你的推荐列表总在炒冷饭做过推荐系统的同行大概率遇到过这种场景离线指标 AUC 涨了线上 CTR 却纹丝不动用户刷出来的还是那几样老面孔。问题往往不在模型容量而在协同过滤本身的两个硬伤——项目侧相似度矩阵太稀疏以及用户兴趣随时间漂移但算法还在用三年前的交互打分。基于项目聚类与时间衰减的协同过滤推荐算法就是冲着这两个痛点去的先用聚类把 Item 压成簇缓解稀疏再给每次交互乘一个随时间衰减的权重让近期行为说话更响。它适合已经有基础 CF 管线、想在不换深度模型的前提下把召回质量往上抬一档的团队也适合数据量不大、冷启动明显的中小场景。下面按「原理选型 → 聚类实现 → 时间衰减 → 融合打分 → 避坑 → 调参与验证」的顺序拆开讲。2. 项目聚类怎么压稀疏从相似度矩阵到簇级近邻协同过滤在项目侧的核心是算 Item-Item 相似度但真实交互矩阵里两个 Item 被同一批用户共同交互过的概率极低导致相似度矩阵大面积为零。项目聚类的思路是先把 Item 按特征或交互模式聚成若干簇相似度计算和近邻搜索在簇级别先做一轮粗筛再在簇内做细排。这样既降低了计算量也让那些单独看很稀疏、但同簇的 Item 能互相借力。2.1 为什么选聚类而不是直接上矩阵分解矩阵分解MF确实能降维但它把 Item 映射到隐空间后可解释性差且冷启动 Item 因为没有交互隐向量基本是随机初始化的。聚类不一样只要 Item 有内容特征类目、标签、文本 embedding就能先归簇冷启动 Item 至少能落到一个簇里拿到簇内平均相似度作为兜底。常见做法是「内容特征 交互共现」拼成一个混合向量再聚类纯内容聚类在行为稀疏时更稳纯共现聚类在行为丰富时更准。我一般会按数据稀疏度选交互密度低于千分之一优先内容特征高于千分之五可以混入共现信号。2.2 用 KMeans 对 Item 向量做聚类的可复现步骤下面这段代码演示从 Item 特征矩阵到簇标签的完整流程特征可以是类目 one-hot、TF-IDF 文本向量或预训练 embedding这里用后者举例。import numpy as np from sklearn.cluster import KMeans from sklearn.preprocessing import normalize # item_feats: shape (n_items, dim)每行是一个 Item 的向量 # 先做 L2 归一化避免模长差异主导距离 item_feats normalize(item_feats, norml2) # n_clusters 是核心参数经验值 sqrt(n_items/2)再按轮廓系数微调 n_clusters int(np.sqrt(item_feats.shape[0] / 2)) kmeans KMeans( n_clustersn_clusters, initk-means, # 比随机初始化更稳避免空簇 n_init10, # 多次重启取最优防止局部最优 max_iter300, random_state42 ) cluster_labels kmeans.fit_predict(item_feats) # 输出每个簇的 Item 数量检查是否有超小簇 unique, counts np.unique(cluster_labels, return_countsTrue) for c, n in zip(unique, counts): print(fcluster {c}: {n} items)逻辑说明归一化是为了让余弦距离和欧氏距离在聚类时表现一致n_init10是防止 KMeans 陷入局部最优的后悔药尤其当 Item 向量分布不均匀时。参数上n_clusters不要拍脑袋先用sqrt(n/2)起步再画轮廓系数曲线选下降拐点。如果出现某个簇只有个位数 Item说明该簇是离群点集合可以考虑合并到最近的大簇或者直接标记为长尾簇单独处理。2.3 簇级相似度与簇内细排的两级检索聚类完成后相似度计算分两级第一级算目标 Item 所在簇与其他簇的簇心相似度取 Top-N 簇第二级只在候选簇内算 Item-Item 余弦相似度。这样把 O(n²) 的相似度矩阵压缩到 O(k² m²)k 是簇数m 是簇内平均 Item 数。实际落地时簇心相似度可以离线算好缓存簇内相似度按需实时算召回延迟能从几百毫秒降到几十毫秒。注意簇内细排时仍要用原始 Item 向量不要用簇心代替否则推荐结果会趋同用户刷到的全是「簇代表」多样性直接崩掉。3. 时间衰减怎么加让三年前的点击不再和昨天等价时间衰减要解决的是兴趣漂移。用户半年前买过婴儿奶粉不代表现在还需要上周刚搜过机械键盘权重就该拉高。做法是给每次交互一个衰减权重权重随「当前时间与交互时间之差」指数下降再把这个权重乘进相似度或预测分里。3.1 指数衰减与半衰期的参数选择最常用的是指数衰减w exp(-λ * Δt)其中 Δt 是距今天数λ 控制衰减速度。λ 越大衰减越快。更直观的参数是半衰期 T经过 T 天后权重降到 0.5此时 λ ln2 / T。半衰期怎么定电商类目通常 30 到 90 天内容资讯类 3 到 7 天工具类可以拉到 180 天。我一般会按业务复购周期来复购周期中位数是多少天半衰期就设成它的 1 到 2 倍。import numpy as np from datetime import datetime def time_decay_weight(event_time, now_time, half_life_days30): event_time / now_time: datetime 对象 half_life_days: 半衰期单位天 返回 0~1 之间的衰减权重 delta_days (now_time - event_time).total_seconds() / 86400.0 # 防止未来时间导致权重 1 delta_days max(delta_days, 0.0) lam np.log(2) / half_life_days return np.exp(-lam * delta_days) # 示例30 天前的一次点击半衰期 30 天 w time_decay_weight( datetime(2024, 5, 1), datetime(2024, 5, 31), half_life_days30 ) print(round(w, 4)) # 约 0.5逻辑说明max(delta_days, 0.0)是防止数据里混入未来时间戳导致权重异常放大这是线上常见的脏数据坑。半衰期参数不要全局一刀切不同类目可以配不同值比如快消品 15 天、耐用品 120 天用配置表管理方便 A/B 实验时按类目调。3.2 把衰减权重乘进相似度矩阵拿到每次交互的权重后Item-Item 相似度不再是简单的共现计数而是加权共现。具体做法对每个用户把他交互过的 Item 两两组合共现次数加 1 乘以两个交互权重的乘积或几何平均。这样近期共同被交互的 Item 对相似度会明显高于很久以前的组合。from collections import defaultdict import math def build_weighted_item_sim(user_items, item_sim, half_life_days30): user_items: {user_id: [(item_id, event_time), ...]} item_sim: 预分配的 defaultdict(float)存加权共现 now datetime.now() for uid, records in user_items.items(): # 先算每条记录的权重 weighted [] for iid, et in records: w time_decay_weight(et, now, half_life_days) weighted.append((iid, w)) # 两两组合累加 for i in range(len(weighted)): for j in range(i 1, len(weighted)): a, wa weighted[i] b, wb weighted[j] if a b: continue # 用几何平均避免单个高权重主导 pair_w math.sqrt(wa * wb) item_sim[(a, b)] pair_w item_sim[(b, a)] pair_w return item_sim逻辑说明用几何平均而不是直接相乘是为了防止某次刚发生的交互权重接近 1把历史信号完全淹没。如果业务更看重近期可以改成wa * wb如果更看重长期稳定偏好可以改成min(wa, wb)。这个选择没有标准答案建议做成可配置项用线上指标说话。3.3 预测分融合相似度、簇归属与衰减的三路加权最终给用户算某个 Item 的预测分时把三路信号融合簇级相似度粗、Item 级加权相似度细、以及该 Item 在用户历史中的衰减权重如果有直接交互。常见公式是score α * sim_item β * sim_cluster γ * decay_histα、β、γ 用网格搜索或贝叶斯优化在验证集上定。注意三路信号量纲不同融合前都要做 min-max 或 z-score 归一化否则数值大的那路会直接主导排序。4. 避坑与常见问题排查聚类和时间衰减最容易翻车的五个点4.1 簇数量拍脑袋导致推荐结果趋同现象推荐列表里全是同一类目或同一风格的商品多样性指标断崖下跌。原因n_clusters设得太小每个簇内 Item 差异大簇内细排时相似度区分度不够排出来都差不多。解决先用轮廓系数和 Davies-Bouldin 指数扫一遍簇数选指标拐点再在簇内细排时引入随机扰动或多样性重排比如 MMR最大边际相关做后处理。4.2 半衰期全局统一快消和耐用品互相拖累现象快消类目的推荐明显滞后用户刚买完的东西还在推耐用品类目又过度偏向近期长期偏好被忽略。原因半衰期写死在代码里所有类目共用。解决把半衰期做成类目维度的配置表快消 7 到 15 天耐用品 90 到 180 天用配置中心下发改参数不用发版。4.3 未来时间戳导致权重爆炸现象某些 Item 的预测分异常高排查发现交互时间戳比当前时间还晚。原因数据同步延迟、时区处理错误或测试数据混入生产。解决在衰减函数里加max(delta, 0)兜底同时在数据接入层做时间戳校验超过当前时间 5 分钟的记录直接丢弃并告警。4.4 冷启动 Item 落不进任何簇现象新上架的 Item 没有交互聚类时因为特征缺失被分到随机簇推荐效果极差。原因聚类只用了交互共现特征新 Item 没有共现记录。解决聚类特征里必须包含内容特征类目、标题 embedding新 Item 至少能按内容归簇同时给新 Item 一个探索权重在预测分里加一个小的随机项保证有曝光机会。4.5 加权共现矩阵内存溢出现象离线任务跑着跑着 OOM。原因两两组合是 O(L²)L 是单用户交互序列长度重度用户 L 可能上千组合数爆炸。解决对单用户交互序列做截断只保留最近 N 条比如 200 条或者用稀疏矩阵存储只累加共现次数超过阈值的 Item 对低于阈值的直接丢弃。5. 调参与线上验证把离线指标翻译成业务收益5.1 三个必调参数与搜索范围参数含义建议范围调参方法n_clustersItem 聚类簇数sqrt(n/2) 上下浮动 50%轮廓系数 线上多样性指标half_life_days时间衰减半衰期类目复购周期的 1~2 倍按类目网格搜索α / β / γ三路信号融合权重各 0~1和为 1贝叶斯优化目标线上 CTR调参顺序建议先定 half_life_days因为衰减直接影响相似度矩阵的数值分布再定 n_clusters聚类质量决定召回上限最后调融合权重这一步对最终排序影响最直接但也最容易过拟合验证集建议用时间切分的验证集而不是随机切分。5.2 离线评估指标与线上 A/B 的对应关系离线看 RecallK 和 NDCGK但这两个指标涨了线上不一定涨。我的血泪经验是离线 Recall 涨但线上 CTR 不涨通常是召回结果多样性下降用户刷两下就没了新鲜感。所以离线阶段除了准确率指标一定要加覆盖率Coverage和基尼系数Gini监控。线上 A/B 至少看三个指标CTR、人均曝光 Item 数、以及次日留存。如果 CTR 涨但留存跌说明推荐在透支用户兴趣衰减参数可能设得太激进。5.3 一个容易被忽略的验证技巧时间穿越检查做时间衰减的离线验证时最容易犯的错是用未来数据算历史权重。比如用 6 月的数据训练却用 5 月的交互时间算衰减导致权重全错。正确做法是验证集的每条样本只允许使用该样本发生时间之前的数据来算相似度和权重严格按时间切分。我一般会在数据管道里加一个断言检查所有特征的时间戳都早于样本时间戳不通过就直接报错这个黑匣子检查能省掉大量排查时间。这套方案我在几个中等数据量的场景里跑过最深的教训是聚类和时间衰减都不是银弹它们解决的是特定问题——稀疏和漂移。如果数据本身很稠密、用户兴趣很稳定硬加这两层反而引入噪声。上线前先做小流量 A/B确认离线指标和线上收益方向一致再全量。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询