# 推荐策略的设计与实现

# 一些初始的设定

# 用户分类

系统会将用户分为新用户与老用户, 新用户即仅有少量用户行为的用户, 老用户是有大量 (30 条以上) 用户行为的用户. 系统要求用户登录后使用系统, 以降低系统复杂度.

# 新闻类别分类

# 完整的新闻类别表

英文 中文 英文 中文 英文 中文
society 社会 entertainment 娱乐 tech 科技
military 军事 sports 体育 car 汽车
finance 财经 world 国际 fashion 时尚
travel 旅游 discovery 探索 baby 育儿
regimen 养生 story 故事 essay 美文
game 游戏 history 历史 food 美食

# 定义的 对时间敏感的类别

英文 中文 英文 中文 英文 中文
society 社会 entertainment 娱乐 tech 科技
military 军事 sports 体育 car 汽车
finance 财经 world 国际 fashion 时尚
game 游戏

# 定义的 对时间不敏感的类别

英文 中文 英文 中文 英文 中文
travel 旅游 discovery 探索 baby 育儿
regimen 养生 story 故事 essay 美文
history 历史 food 美食

# 用户行为定义 (完整)

  1. 无动作
  2. 文章编辑
  3. 文章浏览
  4. 文章点赞 (-3)
  5. 文章点踩 (-4)
  6. 对文章评论, 即数据库中的评论 (-5)
  7. 对文章评论点赞 (-6)
  8. 对文章评论点踩 (-7)
  9. 对评论评论, 即数据库中的回复 (-8)
  10. 对评论评论点赞 (-9)
  11. 对评论评论点踩 (-10)
  12. 关注用户 (-11)

实际情况下用不到这么多行为.

# 推荐算法

# 新闻排分

对新闻打分, 然后推荐. 新闻打分时, 系统使用了四个参数: 新闻时间 (新闻发布时间距离当前时间的小时差的绝对值), 新闻评论数量, 新闻回复数量以及新闻阅读数量. 这四个参数分别使用了四个不同的权重值 (当然有相同的权重问题也不是很大) , 其中新闻时间使用的是负权重, 作为新闻分数的惩罚.

# 协同过滤算法

协同过滤, 基于用户相似度. 相似度的计算对两个用户特征向量计算求和平方差, 值越小, 用户相似度越高. 所谓的用户特征向量, 就是用户在 18 种不同类别下做出的用户行为的统计值.

相似用户计算, 这应该是我这活到现在, 写过的最长的一个 SQL.

<select id="getRelativeCusList" resultType="java.lang.Integer">
    select
        a.cfc_cus_id
    from CusFeatureCount as a,
        (select
            cfc_news_society, cfc_news_entertainment, cfc_news_tech, cfc_news_military, cfc_news_sports, cfc_news_finance,
            cfc_news_world, cfc_news_fashion, cfc_news_travel, cfc_news_discovery, cfc_news_baby, cfc_news_regimen,
            cfc_news_story, cfc_news_essay, cfc_news_game, cfc_news_history, cfc_news_food, cfc_news_car
        from CusFeatureCount where cfc_cus_id = #{cusId}) as b
    where a.cfc_cus_id != #{cusId}
    order by
        SQRT(
            POW((cast(a.cfc_news_society as signed) - cast(b.cfc_news_society as signed)), 2) +
            POW((cast(a.cfc_news_entertainment as signed) - cast(b.cfc_news_entertainment as signed)), 2) +
            POW((cast(a.cfc_news_tech as signed) - cast(b.cfc_news_tech as signed)), 2) +
            POW((cast(a.cfc_news_military as signed) - cast(b.cfc_news_military as signed)), 2) +
            POW((cast(a.cfc_news_sports as signed) - cast(b.cfc_news_sports as signed)), 2) +
            POW((cast(a.cfc_news_finance as signed) - cast(b.cfc_news_finance as signed)), 2) +

            POW((cast(a.cfc_news_world as signed) - cast(b.cfc_news_world as signed)), 2) +
            POW((cast(a.cfc_news_fashion as signed) - cast(b.cfc_news_fashion as signed)), 2) +
            POW((cast(a.cfc_news_travel as signed) - cast(b.cfc_news_travel as signed)), 2) +
            POW((cast(a.cfc_news_discovery as signed) - cast(b.cfc_news_discovery as signed)), 2) +
            POW((cast(a.cfc_news_baby as signed) - cast(b.cfc_news_baby as signed)), 2) +
            POW((cast(a.cfc_news_regimen as signed) - cast(b.cfc_news_regimen as signed)), 2) +

            POW((cast(a.cfc_news_story as signed) - cast(b.cfc_news_story as signed)), 2) +
            POW((cast(a.cfc_news_essay as signed) - cast(b.cfc_news_essay as signed)), 2) +
            POW((cast(a.cfc_news_game as signed) - cast(b.cfc_news_game as signed)), 2) +
            POW((cast(a.cfc_news_history as signed) - cast(b.cfc_news_history as signed)), 2) +
            POW((cast(a.cfc_news_food as signed) - cast(b.cfc_news_food as signed)), 2) +
            POW((cast(a.cfc_news_car as signed) - cast(b.cfc_news_car as signed)), 2)
            )
    limit #{num};
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 推荐场景

系统需要提供热点新闻推荐与个性化新闻推荐. 同时为了避免推荐系统抽风了一样向用户推荐他 "想要的" 内容, 避免用户陷入坑内无法跳到其他类别中; 同时也是为了给所有的新闻能够在用户面前呈现的机会, 系统在不同的推荐场景下的推荐内容基本都不是来源于单一的方式.

# 热点新闻推荐

使用新闻排分的推荐方式, 不区分用户类型, 这是最简单的推荐. 热点新闻需要来源于对时间敏感的类别, 同时新闻发布时间距离当期时间不超过 72 小时. 热点新闻依据新闻排分择优录取.

# 个性化推荐

# 新用户综合推荐

使用新闻排分推荐.

新闻来源

  • 20% 新创建的新闻 (仅依据时间排序)
  • 70% 对时间敏感的新闻
  • 10% 对时间不敏感的新闻

# 新用户单一类别推荐

使用新闻排分推荐.

新闻来源

  • 10% 此类别新创建的新闻 (仅依据时间排序)
  • 90% 此类别新闻 (排分推荐)

# 老用户综合推荐

使用相似用户推荐, 当相似用户推荐内容结束后, 系统将切回到新用户综合推荐 (大概).

新闻来源

  • 30% 热点新闻 (新闻排分推荐)
  • 60% 相似用户推荐
  • 10% 新创建的新闻 (仅依据时间排序)

# 老用户单一类别推荐

计划也是使用相似用户推荐, 但是一个问题是, 某些用户并没有在某些类别下有用户行为, 强行的相似用户推荐并不是一个好主意, 所以系统的具体实现使用的仍然是新用户单一类别推荐.

新闻来源

  • 10% 此类别新创建的新闻 (仅依据时间排序)
  • 90% 此类别新闻 (排分推荐)
Last Updated: 6/3/2020, 12:36:35 AM