天池入门赛- 新闻推荐-task1-baseline

#赛题及数据简介
此次比赛是新闻推荐场景下的用户行为预测挑战赛, 该赛题是以新闻APP中的新闻推荐为背景, 数据来自某新闻APP平台的用户交互数据,包括30万用户,近300万次点击,共36万多篇不同的新闻文章,同时每篇新闻文章有对应的embedding向量表示。目的是要求我们根据用户历史浏览点击新闻文章的数据信息预测用户未来的点击行为, 即用户的最后一次点击的新闻文章, 这道赛题的设计初衷是引导大家了解推荐系统中的一些业务背景, 解决实际问题。

#赛题理解
把该预测问题转成一个监督学习的问题(特征+标签),其中特征中会有用户和文章,分类的标签就是用户是否会点击某篇文章,即点击率预测的问题(用户, 文章) --> 点击的概率(软分类)。

#baseline
step1:为了获取线上提交结果,将测试集中的点击数据合并到总的数据中。
step2:给每个用户根据物品的协同过滤推荐文章,其主要思想是物品 a 和物品 c具有很大的相似度是因为喜欢物品 a 的用户大都喜欢物品 c。
1.可以通过余弦相似度式等来判断物品间的相似程度,公式如下。
在这里插入图片描述
其中,|N(u)|是喜欢物品i的用户数,|N(v)|是喜欢物品j的用户数,|N(u)&N(v)|是同时喜欢物品i和物品j的用户数。 从上面的定义看出,在协同过滤中两个物品产生相似度是因为它们共同被很多用户喜欢,两个物品相似度越高,说明这两个物品共同被很多人喜欢。
CODE:
def itemcf_sim(df):
“”"
文章与文章之间的相似性矩阵计算
:param df: 数据表
:item_created_time_dict: 文章创建时间的字典
return : 文章与文章的相似性矩阵
思路: 基于物品的协同过滤(详细请参考上一期推荐系统基础的组队学习), 在多路召回部分会加上关联规则的召回策略
“”"

user_item_time_dict = get_user_item_time(df)

# 计算物品相似度
i2i_sim = {}
item_cnt = defaultdict(int)
for user, item_time_list in tqdm(user_item_time_dict.items()):
    # 在基于商品的协同过滤优化的时候可以考虑时间因素
    for i, i_click_time in item_time_list:
        item_cnt[i] += 1
        i2i_sim.setdefault(i, {})
        for j, j_click_time in item_time_list:
            if(i == j):
                continue
            i2i_sim[i].setdefault(j, 0)
            
            i2i_sim[i][j] += 1 / math.log(len(item_time_list) + 1)
            
i2i_sim_ = i2i_sim.copy()
for i, related_items in i2i_sim.items():
    for j, wij in related_items.items():
        i2i_sim_[i][j] = wij / math.sqrt(item_cnt[i] * item_cnt[j])

# 将得到的相似性矩阵保存到本地
pickle.dump(i2i_sim_, open(save_path + 'itemcf_i2i_sim.pkl', 'wb'))

return i2i_sim_

2.根据物品的相似度和用户的历史行为给用户生成推荐列表。
ItemCF通过如下公式计算用户u对一个物品j的兴趣:
在这里插入图片描述
其中,Puj表示用户u对物品j的兴趣,N(u)表示用户喜欢的物品集合(i是该用户喜欢的某一个物品),S(i,k)表示和物品i最相似的K个物品集合(j是这个集合中的某一个物品),Wji表示物品j和物品i的相似度,Rui表示用户u对物品i的兴趣。
CODE:
# 基于商品的召回i2i
def item_based_recommend(user_id, user_item_time_dict, i2i_sim, sim_item_topk, recall_item_num, item_topk_click):
“”"
基于文章协同过滤的召回
:param user_id: 用户id
:param user_item_time_dict: 字典, 根据点击时间获取用户的点击文章序列{user1: [(item1, time1), (item2, time2)…]…}
:param i2i_sim: 字典,文章相似性矩阵
:param sim_item_topk: 整数, 选择与当前文章最相似的前k篇文章
:param recall_item_num: 整数, 最后的召回文章数量
:param item_topk_click: 列表,点击次数最多的文章列表,用户召回补全
return: 召回的文章列表 [(item1,score1) ,(item2,score2)…]
注意: 基于物品的协同过滤(详细请参考上一期推荐系统基础的组队学习), 在多路召回部分会加上关联规则的召回策略
“”"

# 获取用户历史交互的文章
user_hist_items = user_item_time_dict[user_id] # 注意,此时获取得到的是一个元组列表,需要将里面的user_id提取出来
user_hist_items_ = {user_id for user_id, _ in user_hist_items}

item_rank = {}
for loc, (i, click_time) in enumerate(user_hist_items):
    for j, wij in sorted(i2i_sim[i].items(), key=lambda x: x[1], reverse=True)[:sim_item_topk]:
        if j  in user_hist_items_:
            continue
            
        item_rank.setdefault(j, 0)
        item_rank[j] +=  wij

# 不足10个,用热门商品补全
if len(item_rank) < recall_item_num:
    for i, item in enumerate(item_topk_click):
        if item in item_rank.items(): # 填充的item应该不在原来的列表中
            continue
        item_rank[item] = - i - 100 # 随便给个负数就行
        if len(item_rank) == recall_item_num:
            break

item_rank = sorted(item_rank.items(), key=lambda x: x[1], reverse=True)[:recall_item_num]
    
return item_rank
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值