推荐系统入门(七):新闻推荐实践2(附代码)
引言
相关系列笔记:
推荐系统入门(一):概述
推荐系统入门(二):协同过滤(附代码)
推荐系统入门(三):矩阵分解MF&因子分解机FM(附代码)
推荐系统入门(四):Wide&Deep(附代码)
推荐系统入门(五):GBDT+LR(附代码)
推荐系统入门(六):新闻推荐实践1(附代码)
推荐系统入门(七):新闻推荐实践2(附代码)
推荐系统入门(八):新闻推荐实践3(附代码)
推荐系统入门(九):新闻推荐实践4(附代码)
推荐系统入门(十):新闻推荐实践5(附代码)
推荐系统一般有三类数据源,一类来自用户的基本信息,一类来自物品的基本信息,还有一类是用户对物品的行为数据。
- 要推荐物品或内容的元数据,例如关键字,分类标签,基因描述等;
- 系统用户的基本信息,例如性别,年龄,兴趣标签等
- 用户的行为数据,可以转化为对物品或者信息的偏好,根据应用本身的不同,可能包括用户对物品的评分,用户查看物品的记录,用户的购买记录等。这些用户的偏好信息可以分为两类:
(1)显式的用户反馈:这类是用户在网站上自然浏览或者使用网站以外,显式的提供反馈信息,例如用户对物品的评分,或者对物品的评论。
(2)隐式的用户反馈:这类是用户在使用网站是产生的数据,隐式的反应了用户对物品的喜好,例如用户购买了某物品,用户查看了某物品的信息等等。
一个典型的推荐系统,处理数据通常会经历以下四步:即数据收集、数据存储、数据分析和数据过滤。
数据收集
实现推荐系统的第一步便是收集数据。这些数据可以是显性数据,也可以是隐性数据。显性数据就是指用户主动输入的数据,例如对内容的评论、点赞、转发、下载等,隐性数据是指用户的浏览历史、阅读时长、观看记录、搜索日志等。后台会为每一个使用该产品/访问该站点的用户创建一个数据集。
用户的行为数据很容易收集,通过站点上的用户行为日志就能获取。如果用户已经在使用APP,获取用户的行为数据就不需要用户的额外操作。但这种方法有一个缺点,获取的数据分析起来很麻烦。比如说,从用户的大量行为日志中过滤出真正需要的日志非常麻烦。
由于每个用户对产品的喜好不一,因此收集到的每位用户的数据集也截然不同。随着时间的推移,收集到的用户数据也越来越多,通过一系列数据分析,推荐的结果也会越来越精准。
数据存储
我们为推荐算法提供的数据越多,推荐的效果就会越精准。这也就意味着,任何推荐问题都可以转变为大数据分析问题来解决。
用于创建推荐结果的数据类型可帮助我们确定应使用的数据存储类型。我们可以选择使用NoSQL(Not Only SQL)数据库、标准SQL数据库,甚至是某种对象存储。根据不同的存储目的如获取用户输入/行为,以及操作的难易程度、存储的数量级、与其他环境的集成以及数据的可移植性等因素,选择合适的数据存储类型。
在保存用户评级或评论时,可扩展和可托管的数据库能够最大限度地减少所需的任务量,将注意力聚焦在推荐结果上。 Cloud SQL可以满足这两种需求,还可以直接从Spark上加载数据。
数据分析
为了获取类似用户参与度之类的数据,我们需要使用不同的分析方法过滤数据。如果想在用户浏览产品时即时给出推荐结果,那么需要更加灵活的数据分析方法。以下是分析数据的一些方法:
- 实时分析
可以在创建数据的同时对其进行处理。这种类型的系统通常包含可以处理和分析事件流的工具。要想给出用户实时的推荐结果,就要创建实时的数据分析系统。
- 批量分析
要求定期处理数据。采用这种方法,意味着要有足够的数据才能分析数据之间的相关性,例如每日阅读量、关注量等。推荐结果可能会通过邮件形式发送给用户。
- 近实时分析
每隔几分钟或几秒钟刷新一次后可以快速收集数据,进行分析。近实时系统最适合在一次浏览会话期间给出推荐结果。
- 数据过滤
下一步便是过滤数据,获取为用户提供推荐所需的相关数据。我们得先从上面的算法中选择一种更合适的算法。比如说:
基于内容的过滤:推荐的产品具有与目标用户喜欢的产品类似的特征;
聚类:对目标用户进行分类,处于某一个簇中的用户会被当成一个整体来对待;
协同过滤:目标用户喜欢其他用户喜欢的某一产品,那他也可能喜欢其他用户喜欢的其他产品。
协同过滤能够使产品属性理论化,并根据用户的口味进行预测。协同过滤的假设基础是:如果一位用户喜欢另一位用户喜欢的某一个产品,那么现在或 将来他也有可能喜欢这位用户喜欢的另一个产品。
我们将产品和用户作为两个不同维度,把有关评级或互动的数据表示为一组矩阵。假设以下两个矩阵相似,如果用数字1代替现有的评级,用0补上缺少的评级,就能得到第二个矩阵。生成的矩阵为真值表,其中数字表示用户与产品之间的交互。
我们可以使用K-Nearest算法、Jaccard系数、Dijkstra算法、余弦相似性来更好地关联用户数据集,以便根据评级或产品特征进行推荐。
实战
# 导入相关包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
plt.rc('font', family='SimHei', size=13)
import os,gc,re,warnings,sys
from sklearn.preprocessing import MinMaxScaler
warnings.filterwarnings("ignore")
# 读取数据
path = './data/'
# train
trn_click = pd.read_csv(path+'train_click_log.csv')
item_df = pd.read_csv(path+'articles.csv')
item_df = item_df.rename(columns={
'article_id': 'click_article_id'}) #重命名,方便后续match
item_emb_df = pd.read_csv(path+'articles_emb.csv')
# test
tst_click = pd.read_csv(path+'testA_click_log.csv')
# 数据预处理
# 计算用户点击rank和点击次数
# 对每个用户的点击时间戳进行排序
trn_click['rank'] = trn_click.groupby(['user_id'])['click_timestamp'].rank(ascending=False).astype(int)
tst_click['rank'] = tst_click.groupby(['user_id'])['click_timestamp'].rank(ascending=False).astype(int)
# 计算用户点击文章的次数,并添加新的一列count
trn_click['click_cnts'] = trn_click.groupby(['user_id'])['click_timestamp'].transform('count')
tst_click['click_cnts'] = tst_click.groupby(['user_id'])['click_timestamp'].transform('count')
# 用户点击日志文件_训练集
trn_click = trn_click.merge(item_df, how='left', on=['click_article_id'])
print(trn_click.head())
# 用户点击日志信息
print(trn_click.info(