天池新闻推荐比赛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 ...
随机推荐
- 03 . Gin+Vue开发一个线上外卖应用(用户数据创建,插入,跨域处理)
功能和背景介绍 在项目的登录功能中,如果在登录时发现用户名和密码在用户表中不存在,会自动将用户名和密码保存在用户表中,创建一个新的用户. 因此,除了使用手机号和验证码登录以外,还支持使用用户名.密码进 ...
- Java学习的第五十一天
1.例9.3 析构函数 public class Cjava { public static void main(String[]args) { Student s1=new Student(1001 ...
- python栈、队列、文件目录遍历
一. 栈与队列 关注公众号"轻松学编程"了解更多. 1. 栈 stack 特点:先进先出[可以抽象成竹筒中的豆子,先进去的后出来] 后来者居上 mystack = [] #压栈[向 ...
- Charles使用part2——代理设置
一.charles代理原理: 如果本地开了代理: 二.设置代理 1.设置代理端口: proxy->proxy setting 打开代理设置界面,代理端口默认是 8888,可以使用默认也可以自己 ...
- python socket 二进制
问题 在工作中经常会用到socket传输数据,例如客户端给服务器发送数据(双方约定了数据格式),在交测之前,自己用python写个接受数据的server,解析下拼成的数据格式是否正确.用python写 ...
- SSM实现文件上传
1.导入上传需要的jar包 commons-fileupload-1.3.3.jar commons-io-2.6.jar 2.创建 index.jsp <%@ page contentType ...
- 我的第三次C语言作业
我的第三次C语言作业 这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/SE2020-2 这个作业要求在哪里 https://edu.cnblogs.co ...
- C++ 设计模式 3:结构型模式
0 结构型模式 让类和类进行组合,获得更大的结构,获得新功能的方式. 1 代理模式 Proxy 模式又被叫做代理模式,是结构型的设计模式之一,它可以 为其他对象提供一种代理以控制对这个对象的访问. 所 ...
- C++ 数据结构 1:线性表
1 数据结构 1.1 数据结构中基本概念 数据:程序的操作对象,用于描述客观事物. 数据的特点: 可以输入到计算机 可以被计算机程序处理 数据是一个抽象的概念,将其进行分类后得到程序设计语言中的类型. ...
- 无法将“add-migration”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。解决方案
在程序包管理控制台中执行 Install-Package Microsoft.EntityFrameworkCore.Tools