文章

推荐系统第一版:行为权重、标签兴趣和相似度

语之溪

·

代码

·

⚠️ 本文最后更新于2026年03月21日,已经过了156天没有更新,若内容或图片失效,请留言反馈

HAOVP 的推荐服务已经有了第一版实现。它没有使用机器学习模型,也没有依赖 Spark 之类的数据处理平台,而是从平台当前能够获得的数据出发,把用户行为、标签兴趣、视频相似度和热门内容组合起来。

这样的第一版更容易解释:一条推荐为什么出现,可以追溯到用户近期行为、内容标签、视频分类或热门分数。它的能力有限,但每一部分都可以单独验证。

推荐服务需要哪些输入

当前可以使用的信号主要有四类:

  • 用户对视频产生的浏览、点赞、收藏、评论、分享和完整观看行为;
  • 视频所属的标签和分类;
  • 用户近期行为形成的标签兴趣;
  • 一段时间内累计的热门分数。

一条简化的数据链路是:

用户行为
    -> 行为记录
    -> 标签兴趣 / 热门分数
    -> 候选视频
    -> 去重与补位
    -> 首页、相似或标签推荐

推荐服务不负责保存视频详情。它通过内容服务取得视频、分类和标签信息,再把推荐结果映射为前端需要的结构。

行为权重表达信号强弱

浏览一次和收藏一次表达的兴趣强度不同。第一版在记录行为时,为不同类型设置了不同权重。

可以把热门分数抽象为:

score(video) = Σ 行为次数 × 行为权重

例如浏览是较弱信号,点赞、收藏和完整观看可以设置为更强信号。具体数值只是当前规则参数,不代表经过实验得到的最优值。

当前实现还按不同时间窗口生成热门内容:

最近一天  -> 日榜
最近七天  -> 周榜
最近三十天 -> 月榜

首页需要热门内容时,先取较短周期的数据,不足再由更长周期补充。这个策略可以给新近内容机会,也能在当天行为数据不足时保留结果。

标签兴趣是怎样形成的

用户行为发生后,推荐服务会统计近期行为涉及的标签,再把各标签出现次数除以总次数,得到一组归一化兴趣。

某标签兴趣权重 = 近期涉及该标签的行为次数 / 所有标签行为次数

假设一段时间内得到以下计数:

Java       5
数据库     3
容器部署   2
总计      10

归一化后分别是 0.50.30.2。这些数字是解释算法的通用示例,不是 HAOVP 的真实用户数据。

这里需要区分两类权重:

  • 行为权重用于区分浏览、点赞、收藏等信号,并参与热门分数计算;
  • 标签兴趣在当前实现中按近期行为次数归一化。

也就是说,当前代码没有直接把每条行为的行为权重累加到标签兴趣中。文章标题里的“行为权重”和“标签兴趣”是两条相关但不同的计算链路,不能把它们写成一个已经统一训练过的模型。

标签兴趣怎样变成候选视频

有兴趣标签时,第一版会按标签权重扩充候选标签池。权重越高的标签,在候选池中出现的机会越多,再通过打乱顺序避免结果完全固定。

一个简化示例:

for (TagInterest interest : interests) {
    int quota = Math.round(interest.weight() * 10);
    for (int i = 0; i < quota; i++) {
        candidateTags.add(interest.tagId());
    }
}
Collections.shuffle(candidateTags);

这是按当前思路整理的脱敏示例,不是仓库源码原样复制。

服务随后按标签向内容服务查询视频,并使用集合过滤已经加入结果的内容。这里的“权重”主要影响候选机会,并不等于最终推荐概率经过严格校准。

没有兴趣数据时怎么办

新用户或游客没有足够行为,无法立即得到稳定的标签兴趣。如果此时强行个性化,只会制造没有依据的结果。

第一版采用分层回退:

有标签兴趣
    -> 按兴趣标签选择内容

没有标签兴趣,但有近期行为
    -> 查找近期行为视频的相似内容

没有可用行为
    -> 使用热门内容

个性化结果数量不足时,也由热门内容补位。这样至少保证页面有内容,同时把“个性化推荐”和“热门兜底”区分开。

视频相似度如何计算

第一版的视频相似度使用标签和分类,不分析标题语义、画面、音频或用户向量。

标签部分使用 Jaccard 相似度:

标签相似度 = 两个视频共有标签数 / 两个视频全部不同标签数

例如:

视频 A 标签:Java、Spring、MySQL
视频 B 标签:Java、Spring、Redis

交集:Java、Spring,共 2 个
并集:Java、Spring、MySQL、Redis,共 4 个
标签相似度 = 2 / 4 = 0.5

这仍是通用演算示例,不对应真实视频和标签。

分类部分更简单:同分类记为相似,不同分类记为不相似。当前综合规则可以写成:

综合相似度 = 标签相似度 × 0.7 + 分类相似度 × 0.3

只保存超过当前阈值的相似关系。权重和阈值是第一版规则,需要根据内容数量、标签质量和实际结果继续调整,不能把它们写成普遍适用的最佳参数。

为什么预先保存相似关系

如果每次打开视频详情页,都临时把当前视频和全部视频两两比较,数据量增加后会产生大量重复计算。

第一版使用定时任务计算相似关系并保存:

定时读取视频与标签
    -> 两两计算标签和分类相似度
    -> 过滤低于阈值的组合
    -> 保存双向相似关系
    -> 查询时按分数取前若干条

这样在线查询只需要读取已经计算的结果,再到内容服务获取视频详情。

不过两两比较的计算量会随着视频数量快速增加。当前任务还只处理有限范围内的视频,所以它适合第一版和当前规模,不能直接推导为大规模推荐系统方案。

首页为什么组合多种策略

只用兴趣标签容易让内容越来越单一,只用热门内容又无法体现用户差异。当前首页按页面位置组合基于内容的推荐与热门推荐,并在个性化结果不足时补充热门内容。

可以把目标理解为:

  • 兴趣标签负责相关性;
  • 视频相似度负责从近期行为继续扩展;
  • 热门策略负责冷启动和结果补位;
  • 去重负责避免同一视频反复出现;
  • 不同页面使用不同组合,增加一定多样性。

这是一种规则编排,不是经过在线实验验证的排序模型。页面轮换也不等于真正解决了信息茧房,只是第一版中控制单一结果的一种简单办法。

推荐理由也应该可解释

第一版会给结果设置简单原因,例如“热门推荐”“根据观看历史推荐”或“根据某个标签兴趣推荐”。

推荐理由必须来自真实使用的策略。如果结果实际来自热门补位,就不应该显示成“猜你喜欢”;如果只依据共同标签,也不应该声称系统理解了视频语义。

可解释性有两个作用:

  • 用户能够大致理解内容为什么出现;
  • 开发时可以判断某条结果来自哪条策略,便于排查空结果、重复内容和错误标签。

第一版需要验证什么

我会先验证规则是否按设计执行,而不是直接评价“推荐准不准”。

行为与兴趣

  • 各类行为是否被正确记录;
  • 重复上报是否会放大分数;
  • 近期时间窗口是否生效;
  • 标签计数和归一化结果是否正确;
  • 删除或下架视频后,历史行为如何处理。

相似度

  • 无标签、单标签和完全相同标签能否正确计算;
  • 同分类加分是否符合预期;
  • 相似关系是否双向保存;
  • 定时任务重复执行是否产生重复记录;
  • 视频或标签变化后旧结果是否被更新。

推荐结果

  • 游客是否得到热门内容;
  • 新用户是否能正常回退;
  • 个性化结果不足时是否补位;
  • 已加入结果的视频是否去重;
  • 内容服务不可用时是否返回可解释的失败或空结果;
  • 推荐理由是否和实际策略一致。

这些检查能证明代码路径和数据关系是否正确,但不能证明推荐效果已经成熟。

第一版的边界

当前实现可以确认的是:推荐服务使用行为规则、近期标签兴趣、标签与分类相似度以及热门策略组织结果。

当前不能据此宣称:

  • 使用了机器学习或深度学习模型;
  • 建立了成熟的用户画像;
  • 使用了协同过滤、向量检索或实时特征平台;
  • 已通过 A/B 测试证明效果提升;
  • 已在大规模数据和高并发条件下验证;
  • 当前参数是最优权重。

推荐系统第一版的价值,是先把行为、兴趣、相似内容和热门兜底串成一条可运行、可解释、可检查的链路。等数据积累和验证方法更完整,再决定哪些规则值得保留,哪些部分需要更合适的算法。

现在已有 8 次阅读,0 条评论,0 人点赞
作者:语之溪
作者
推荐系统第一版:行为权重、标签兴趣和相似度
当前文章累计共 3657 字,阅读大概需要 7 分钟。
我负责的第一个竞赛平台模块
2023年7月15日 - 0评论
竞赛平台里的接口、校验和状态流转
2023年10月14日 - 0评论
我第一次接触 ChatGPT
2023年6月24日 - 0评论
评论:共0条
发表
搜索 消息 足迹 排行
你还不曾留言过..
你还不曾留下足迹..
博主 不再显示
博主
未知作品 歌曲封面
立即安装