CitySpark · 城事雷达 概念封面

想解决的问题

城市里的展览、手作、脱口秀、市集、沙龙、戏剧,大多没有像样的分发渠道。要推得准,得同时满足五个条件:同城、没去过、还能报名、时间不冲突、合口味。任何一个不满足,推荐就是无效的。

CitySpark 把这件事拆成一条完整的推荐链路,并且把「凭什么推这个」也一起交出来。

六路召回,各自都能跑

路径 实现 缺可选依赖时
UserCF 加权 Pearson / Cosine / Jaccard 混合相似度 + 共同数收缩 无需可选依赖
ItemCF 活动向量余弦、热门校正、Top-K 相邻活动 无需可选依赖
MF implicit 的 BPR 降级为 sklearn TruncatedSVD
图传播 归一化二部图上的个性化重启传播 始终可用(未声称实现可训练 LightGCN)
语义 标题 + 描述 + 标签 + 规则/LLM 画像;TF-IDF 或句向量 降级为 TF-IDF + NumPy 余弦
热门探索 同城对数热门度 + 新活动指数衰减 无需可选依赖

隐式反馈按 view=1 / favorite=3 / share=4 / signup=5 加权,每条事件再乘时间衰减(半衰期 30 天),同时给每个活动加 1/log(1+活跃用户数) 的热门惩罚——否则热门活动会把长尾全吃掉。

过滤是这道题的一半

推荐系统最容易翻车的地方不是排序,是「推了个你已经报过名的活动」。这里做七类过滤:已收藏、已报名、标记不感兴趣、异地、下架或售罄、已经开始、与历史报名时段冲突,再加距离阈值和重复事件去重(同 event_group 只留一条)。

余量按截点前的不重复报名数算,距离用模拟经纬度的 Haversine。

实验是怎么做的

没有随机拆行。 按时间切分,最后一周永远留作测试:

阶段 可见历史 标签窗口
排序训练 10-08 之前 [10-08, 10-15)
测试 10-15 之前(召回重训,排序器冻结) [10-15, 10-22)

数据是 160 用户、240 活动、11,438 条行为、860 条评分的模拟集(seed 42),测试截点前特意注入了零历史的新用户和新活动,冷启动不是事后补的。

结果

K=10,109 个有可推荐正例的用户,193 个目标:

方案 Recall@10 NDCG@10 覆盖率 新颖度
纯 Pearson UserCF 0.1578 0.0925 0.5919 2.0875
增强 UserCF baseline 0.1356 0.0782 0.6233 2.1925
ItemCF 0.1073 0.0561 0.7085 2.6349
BPR-MF 0.2021 0.1011 0.7489 2.2778
多路融合 · 加权 0.2739 0.1407 0.8161 2.6639
多路融合 · 投票(RRF) 0.2506 0.1411 0.7130 2.5398
多路融合 · LightGBM 0.2162 0.1178 0.8610 3.4280

三件我原本预期相反的事,报告里都按实测写了:

  1. 加权融合的 Recall@10 高于 LambdaRank。 学过排序不一定赢过调好的权重,至少在 109 个用户的样本量上如此。
  2. 增强版 UserCF 没有全面优于纯 Pearson。 加了热门惩罚、共同数收缩和相似度混合之后,Recall 反而从 0.1578 掉到 0.1356——这道题上它没赚回来。
  3. 六路召回的候选上限是 0.9145,实际最好的方案只有 0.2739。 瓶颈不在召回,在排序和过滤。

冷启动

17 个冷用户在纯协同过滤下 Recall 全为 0(这是必然的,没有历史就没有邻居)。多路融合把冷用户 Recall 拉到 0.1961(加权)和 0.2745(LightGBM)——靠的是语义画像和热门探索这两条不依赖历史的路。

冷活动(29 个)相反:加权融合仍然拿不到正例,LightGBM 能到 0.2414,靠的是特征里有新旧程度和标签匹配。

可解释

LambdaRank 的每种召回路径返回一个 TreeSHAP 贡献组(含 context 和 bias),各贡献之和等于原始排序分数;界面里能直接展开看每路给了多少分,同时附上原始召回证据。排序分数不是概率,负贡献也是正常的——界面里写明了这一点,不把分数包装成置信度。

当前边界

  • 全部是模拟数据,单个合成时间窗。「离线指标高」不等于「线上就好」,真实系统需要多窗口验证和线上 A/B。
  • 协同相似度在演示规模上用稠密矩阵计算,百万级用户/活动必须换稀疏 Top-K、ANN 和增量训练。
  • 活动价格、区域目前是排序信号和解释维度,不是被学出来的因果因素。
  • 没有生产鉴权、多租户隔离或分布式库存事务,API 默认绑定回环地址。前端是 Streamlit,属于演示界面而言而非产品级前端。

项目图集

推荐卡片展开「推荐依据与各路贡献」:召回来源 usercf / mf / graph / semantic / popular,TreeSHAP 按路径归组的贡献分数
推荐卡片展开「推荐依据与各路贡献」:召回来源 usercf / mf / graph / semantic / popular,TreeSHAP 按路径归组的贡献分数
实验对比页签:15 个方案在保留测试窗口上的 Recall@10 与 NDCG@10 对比表,以及柱状图
实验对比页签:15 个方案在保留测试窗口上的 Recall@10 与 NDCG@10 对比表,以及柱状图