离线用户基于内容召回集

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


3.5 离线用户基于内容召回集

学习目标

  • 目标
    • 知道离线内容召回的概念
    • 知道如何进行内容召回计算存储规则
  • 应用
    • 应用spark完成离线用户基于内容的协同过滤推荐

3.5.1 基于内容召回实现

基于Item协同过滤与基于内容协同过滤区别:

  • 基于物品的协同过滤: 用户喜欢的东西,然后从剩下的物品中找到和他历史兴趣近似的物品推荐给他,核心是要通过两个物品被同时喜欢的用户数等决定。
假设有A、B、C、D4个用户:
用户A买了a、b、d三个商品;
用户B买了a、c;
用户C买了b、e;
用户D买了c、d、e

推荐给A:我们就需要比较c和e哪个商品与a和b和d的相似度总和最大?

例如我们现在先比较c和a的相似度(对c和b、c和d进行相同处理),就是(同时拥有c和a的用户数/喜欢a的用户数),同理可以用来考察e和a
  • 基于内容的过滤:给用户推荐和他们之前喜欢的物品在内容上相似的其他物品。核心任务就是计算物品的内容相似度。

    • 给物品内容建模,如Word2vec模型得到词向量或者文章向量
  • 目的:实现定时离线更新用户的内容召回集合

  • 步骤:
    • 1、过滤用户点击的文章
    • 2、用户每次操作文章进行相似获取并进行推荐

过滤用户点击的文章

ur.spark.sql("use profile")
user_article_basic = ur.spark.sql("select * from user_article_basic")
user_article_basic = user_article_basic.filter('clicked=True')

用户每次操作文章进行相似获取并进行推荐

# 基于内容相似召回(画像召回)
ur.spark.sql("use profile")
user_article_basic = self.spark.sql("select * from user_article_basic")
user_article_basic = user_article_basic.filter("clicked=True")

def save_content_filter_history_to__recall(partition):
    """计算每个用户的每个操作文章的相似文章,过滤之后,写入content召回表当中(支持不同时间戳版本)
    """
    import happybase
    pool = happybase.ConnectionPool(size=10, host='hadoop-master')

    # 进行为相似文章获取
    with pool.connection() as conn:

        # key:   article_id,    column:  similar:article_id
        similar_table = conn.table('article_similar')
        # 循环partition
        for row in partition:
            # 获取相似文章结果表
            similar_article = similar_table.row(str(row.article_id).encode(),
                                                columns=[b'similar'])
            # 相似文章相似度排序过滤,召回不需要太大的数据, 百个,千
            _srt = sorted(similar_article.items(), key=lambda item: item[1], reverse=True)
            if _srt:
                # 每次行为推荐10篇文章
                reco_article = [int(i[0].split(b':')[1]) for i in _srt][:10]

                # 获取历史看过的该频道文章
                history_table = conn.table('history_recall')
                # 多个版本
                data = history_table.cells('reco:his:{}'.format(row.user_id).encode(),
                                           'channel:{}'.format(row.channel_id).encode())

                history = []
                if len(_history_data) > 1:
                  for l in _history_data:
                    history.extend(l)

                # 过滤reco_article与history
                reco_res = list(set(reco_article) - set(history))

                # 进行推荐,放入基于内容的召回表当中以及历史看过的文章表当中
                if reco_res:
                    # content_table = conn.table('cb_content_recall')
                    content_table = conn.table('cb_recall')
                    content_table.put("recall:user:{}".format(row.user_id).encode(),
                                      {'content:{}'.format(row.channel_id).encode(): str(reco_res).encode()})

                    # 放入历史推荐过文章
                    history_table.put("reco:his:{}".format(row.user_id).encode(),
                                      {'channel:{}'.format(row.channel_id).encode(): str(reco_res).encode()})

        conn.close()

user_article_basic.foreachPartition(save_content_filter_history_to__recall)
  • 1、获取用户点击的某文章相似文章结果并排序过滤
    • 相似结果取出TOPK:根据实际场景选择大小,10或20
# 循环partition
for row in partition:
    # 获取相似文章结果表
    similar_article = similar_table.row(str(row.article_id).encode(),
                                        columns=[b'similar'])
    # 相似文章相似度排序过滤,召回不需要太大的数据, 百个,千
    _srt = sorted(similar_article.items(), key=lambda item: item[1], reverse=True)
    if _srt:
        # 每次行为推荐若干篇文章
        reco_article = [int(i[0].split(b':')[1]) for i in _srt][:10]

取出结果的测试演示:

import happybase
pool = happybase.ConnectionPool(size=10, host='hadoop-master', port=9090)
with pool.connection() as conn:

    similar_table = conn.table('article_similar')
    similar_article = similar_table.row(str('116644').encode(),
                                        columns=[b'similar'])
    # 相似文章相似度排序过滤,召回不需要太大的数据, 百个,千
    _srt = sorted(similar_article.items(), key=lambda item: item[1], reverse=True)
    print(_srt)
    print([int(i[0].split(b':')[1]) for i in _srt][:10])
  • 2、过滤历史召回的所有文章(所有的召回类型)
# 获取历史看过的该频道文章
history_table = conn.table('history_recall')
# 多个版本
data = history_table.cells('reco:his:{}'.format(row.user_id).encode(),
                           'channel:{}'.format(row.channel_id).encode())

 history = []
  if len(data) > 1:
    for l in _history_data:
      history.extend(l)

# 过滤reco_article与history
reco_res = list(set(reco_article) - set(history))
  • 3、对结果进行存储,历史推荐存储
# 进行推荐,放入基于内容的召回表当中以及历史看过的文章表当中
if reco_res:
    # content_table = conn.table('cb_content_recall')
    content_table = conn.table('cb_recall')
    content_table.put("recall:user:{}".format(row.user_id).encode(),
                      {'content:{}'.format(row.channel_id).encode(): str(reco_res).encode()})

    # 放入历史推荐过文章
    history_table.put("reco:his:{}".format(row.user_id).encode(),
                      {'channel:{}'.format(row.channel_id).encode(): str(reco_res).encode()})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值