天池新闻推荐比赛1:赛题理解+baseline
天池新闻推荐比赛1:赛题理解+baseline
一、比赛信息
比赛链接:
https://tianchi.aliyun.com/competition/entrance/531842/information
比赛简介:
赛题以预测用户未来点击新闻文章为任务,该数据来自某新闻APP平台的用户交互数据,包括30万用户,近300万次点击,共36万多篇不同的新闻文章,同时每篇新闻文章有对应的embedding向量表示。为了保证比赛的公平性,将会从中抽取20万用户的点击日志数据作为训练集,5万用户的点击日志数据作为测试集A,5万用户的点击日志数据作为测试集B。
评价指标:
以MRR作为评价指标,MRR(Mean reciprocal rank)是一个国际上通用的对搜索算法进行评价的机制,即第一个结果匹配,分数为1,第二个匹配分数为0.5,第n个匹配分数为1/n,如果没有匹配的句子分数为0。最终的分数为所有得分之和。对于本次比赛,每个用户都会向推荐Top5的文章,故每个用户的MRR定义如下:
(\text {score}(u s e r)=\sum_{k=1}^{5} \frac{s(u s e r, k)}{k} )
最终的得分为所有用户分数的平均值。
二、赛题理解
本次比赛是新闻背景下的推荐系统,可用的特征为新闻特征+用户特征。新闻特征主要是文章的长度、文章类型和文章创建时间,而用户特征为用户本身的信息+之前的点击日志构成。最终的预测值用户的最后一次点击的文章。关键是如何将真实场景下的用户日志转化为可以作为模型输入的特征,这是本次比赛的一个挑战。
三、赛题Baseline
Baseline采用item-based协同过滤,item-based协同过滤常见思路如下:
构建物品相似度矩阵
根据相似度矩阵和用户之前购买过的物品,找出TopN个相似物品
对TopN个物品排序
具体的代码和思路如下:
导入相关的库
import time, math, os
from tqdm import tqdm
import gc
import pickle
import random
from datetime import datetime
from operator import itemgetter
import numpy as np
import pandas as pd
import warnings
import collections
from collections import defaultdict
warnings.filterwarnings('ignore')
# 数据读取,用训练集+测试集的物品一起构建物品相似度矩阵
data_path = './data_raw/'
save_path = './tmp_results/'
train_click = pd.read_csv(data_path + 'train_click_log.csv')
test_click = pd.read_csv(data_path + 'testA_click_log.csv')
all_click_df = train_click.append(test_click)
按点击时间排序,获取用户:[点击文章,点击时间] 字典
def get_user_item_time(click_df):
# 对点击时间排序
click_df = click_df.sort_values('click_timestamp')
def make_item_time_pair(df):
return list(zip(df['click_article_id'], df['click_timestamp']))
# 以用户id为分组,进行[点击文章,点击时间]的配对
user_item_time_df = click_df.groupby('user_id')['click_article_id', 'click_timestamp'].apply(lambda x: make_item_time_pair(x))\
.reset_index().rename(columns={0: 'item_time_list'})
user_item_time_dict = dict(zip(user_item_time_df['user_id'], user_item_time_df['item_time_list']))
return user_item_time_dict
获取点击最多的文章,为后面缺失值补充
def get_item_topk_click(click_df, k):
topk_click = click_df['click_article_id'].value_counts().index[:k]
return topk_click
用全部数据集,构建物品相似度矩阵
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_
基于相似度矩阵进行召回
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]
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
定义提交文件函数
# 生成提交文件
def submit(recall_df, topk=5, model_name=None):
recall_df = recall_df.sort_values(by=['user_id', 'pred_score'])
recall_df['rank'] = recall_df.groupby(['user_id'])['pred_score'].rank(ascending=False, method='first')
# 判断是不是每个用户都有5篇文章及以上
tmp = recall_df.groupby('user_id').apply(lambda x: x['rank'].max())
assert tmp.min() >= topk
del recall_df['pred_score']
submit = recall_df[recall_df['rank'] <= topk].set_index(['user_id', 'rank']).unstack(-1).reset_index()
submit.columns = [int(col) if isinstance(col, int) else col for col in submit.columns.droplevel(0)]
# 按照提交格式定义列名
submit = submit.rename(columns={'': 'user_id', 1: 'article_1', 2: 'article_2',
3: 'article_3', 4: 'article_4', 5: 'article_5'})
save_name = save_path + model_name + '_' + datetime.today().strftime('%m-%d') + '.csv'
submit.to_csv(save_name, index=False, header=True)
设置基本的参数
# 定义
user_recall_items_dict = collections.defaultdict(dict)
# 获取 用户 - 文章 - 点击时间的字典
user_item_time_dict = get_user_item_time(all_click_df)
# 去取文章相似度
if os.path.exists(save_path + 'itemcf_i2i_sim.pkl'):
i2i_sim = pickle.load(open(save_path + 'itemcf_i2i_sim.pkl', 'rb'))
else:
i2i_sim = itemcf_sim(all_click_df)
# 相似文章的数量
sim_item_topk = 10
# 召回文章数量
recall_item_num = 10
# 用户热度补全
item_topk_click = get_item_topk_click(all_click_df, k=50)
得到测试集结果
# 获取测试集的结果
for user in tqdm(test_click['user_id'].unique()):
user_recall_items_dict[user] = item_based_recommend(user, user_item_time_dict, i2i_sim,
sim_item_topk, recall_item_num, item_topk_click)
# 将字典的形式转换成df
user_item_score_list = []
for user, items in tqdm(user_recall_items_dict.items()):
for item, score in items:
user_item_score_list.append([user, item, score])
recall_df = pd.DataFrame(user_item_score_list, columns=['user_id', 'click_article_id', 'pred_score'])
# 生成提交文件
submit(recall_df , topk=5, model_name='itemcf_baseline')
四、总结
这个baseline虽然只是最基础的模型,而且还有许多的用户和新闻的信息并没有利用起来。但让我们熟悉了新闻推荐的基本流程,了解了常见的数据处理方法,最终从用户日志中得到可以使用的特征。
天池新闻推荐比赛1:赛题理解+baseline的更多相关文章
- 《阿里云天池大赛赛题解析》——O2O优惠卷预测
赛事链接:https://tianchi.aliyun.com/competition/entrance/231593/introduction?spm=5176.12281925.0.0.7e157 ...
- 【天池大数据赛题解析】资金流入流出预测(附Top4答辩ppt)
http://mp.weixin.qq.com/s?__biz=MzA3MDg0MjgxNQ==&mid=208451006&idx=1&sn=532e41cf020a0673 ...
- O准备如何苟进复赛圈?华为软挑开挂指南(附赛题预测)
事先声明,这不是华为软挑的软广,我也不是海军. 这篇文章纯粹是心血来潮,原因是去年上传到github的参赛代码,前几天又有两个人star和fork了. 记得star热潮还是去年4月复赛刚结束的那几天, ...
- Python小白的数学建模课-A3.12 个新冠疫情数模竞赛赛题与点评
新冠疫情深刻和全面地影响着社会和生活,已经成为数学建模竞赛的背景帝. 本文收集了与新冠疫情相关的的数学建模竞赛赛题,供大家参考,欢迎收藏关注. 『Python小白的数学建模课 @ Youcans』带你 ...
- Hitcon 2016 Pwn赛题学习
PS:这是我很久以前写的,大概是去年刚结束Hitcon2016时写的.写完之后就丢在硬盘里没管了,最近翻出来才想起来写过这个,索性发出来 0x0 前言 Hitcon个人感觉是高质量的比赛,相比国内的C ...
- 潭州课堂25班:Ph201805201 django 项目 第二十三课 文章主页 轮播图前端实现 热门新闻推荐实现 详情页实现 (课堂笔记)
前台代码 // 在static/js/news/index.js文件中 $(function () { // 新闻列表功能 let $newsLi = $(".news-nav ul li& ...
- 6、DRN-----深度强化学习在新闻推荐上的应用
1.摘要: 提出了一种新的深度强化学习框架的新闻推荐.由于新闻特征和用户喜好的动态特性,在线个性化新闻推荐是一个极具挑战性的问题. 虽然已经提出了一些在线推荐模型来解决新闻推荐的动态特性,但是这些方法 ...
- CSDN 轻松周赛赛题:能否被8整除
轻松周赛赛题:能否被8整除 题目详情 给定一个非负整数,问能否重排它的全部数字,使得重排后的数能被8整除. 输入格式: 多组数据,每组数据是一个非负整数.非负整数的位数不超过10000位. 输出格式 ...
- 18、DKN(Deep Knowledge-Aware Network for News Recommendation)---新闻推荐
摘自:https://blog.csdn.net/qq_40006058/article/details/89678866 DKN:Deep Knowledge-Aware Network for N ...
随机推荐
- Redis发布订阅使用方法
Redis发布订阅 发布订阅模式中发布消息的为publisher即发布者,接收消息的为subscriber即订阅者.在Redis中,所有的消息通过channel即频道进行发布,一个发布者可以向多个ch ...
- ERP的主数据的操作与设计--开源软件诞生25
赤龙ERP主数据管理讲解--第25篇 用日志记录"开源软件"的诞生 [进入地址 点亮星星]----祈盼着一个鼓励 博主开源地址: 码云:https://gitee.com/redr ...
- 虚拟机中安装Centos 7
VMware中安装centos7系统 一.首先需要准备必要文件 1.VMware软件的安装包,建议使用12以上版本 VMwareWorkstation14版本下载链接 链接:https://pan.b ...
- 记一次使用idea插件CamelCase技巧
1.在idea中下载插件CamelCase插件 2.使用Shift+Alt+U快捷键进行转换 3.由于转换格式比较导致多次使用快捷键才能达到自己想要的效果,此插件提供了允许禁用某些转换或更改它们在首 ...
- 索引--mysql 数据库Load data大量数据时性能因素之一
发现load data infile 插入数据时越来越慢,后来发现是因为创建表时有创建索引的动作. 把索引创建删除掉之后,导入很迅速,导入后再创建索引,效率果有提高.
- c语言 :write与read系统调用总结
在学习的时候总是有点迷糊于是在网上找到一些比较好的分享一下 下面举一个例子: 1 #include <stdio.h> 2 #include <unistd.h> 3 #in ...
- 聊聊Spark的分区、并行度 —— 前奏篇
通过之前的文章[Spark RDD详解],大家应该了解到Spark会通过DAG将一个Spark job中用到的所有RDD划分为不同的stage,每个stage内部都会有很多子任务处理数据,而每个sta ...
- Selective Acknowledgment 选项 浅析 1
抓包的时候,发现 tcp 三次握手中一般会有几个options 一个是mss 一个是ws 一个sack perm 这次主要是来说一说 sack 这个选项: 1. 只重传超时的数据包,比较实用与后 ...
- linux 异步I/O 信号
if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_log_error(NGX_LOG_ALERT, cycl ...
- 小程序·云开发地表最强CI利器来了
小程序CI 与 CloudBase-FrameWork 从2017年开始,微信小程序的能力也随着前端的大发展的趋势越来越多,包体积限制越来越宽松,大型微信小程序的开发团队越来越多,为了适应形式,微信小 ...