推荐系统
1 推荐系统概述
1.1 推荐系统的目的
- 让用户更快更好的获取到自己需要的内容
- 让内容更快更好的推送到喜欢它的用户手中
- 让网站(平台)更有效的保留用户资源
1.2 推荐系统的应用
- 个性化音乐
- 电子商务
- 电影视频
- 社交网络
- 位置服务…
1.3 推荐系统的基本思想
- 利用用户和物品的特征信息,给用户推荐那些具有用户喜欢的特征的物品。
- 利用用户喜欢过的物品,给用户推荐与他喜欢过的物品相似的物品。
- 利用和用户相似的其他用户,给用户推荐那些和他们兴趣爱好相似的其他用户喜欢的物品。
1.4 推荐系统的数据分析
- 用户:个人信息、喜好标签、上下文信息
- 物品:内容信息、分类标签、关键词
- 行为数据:评分/评价、点击/浏览、收藏/购买
1.5 推荐系统分类
- 根据实时性分类
- 离线推荐
- 实时推荐
- 根据推荐是否个性化分类
- 基于统计的推荐
- 个性化推荐
- 根据推荐原则分类
- 基于相似度的推荐
- 基于知识的推荐
- 基于模型的推荐
- 根据数据源分类
- 基于人口统计学的推荐【用户数据】
- 基于内容的推荐【商品数据】
- 基于协同过滤的推荐【行为数据】
2 推荐算法简介
2.1 基于人口统计学的推荐算法
- 用户画像:用户信息标签化的过程。
- 就是企业通过收集与分析消费者社会属性、生活习惯、消费行为等主要信息的数据之后,完美的抽象出一个用户的商业全貌作为企业应用大数据技术的基本方式。
2.2 基于内容的推荐算法
- 对于物品的特征提取—打标签
- 专家标签(PGC)
- 用户自定义标签(UGC)
- 降维分析数据,提取隐语义标签(LFM)
- 对于文本信息的特征提取—关键词
- 分词、语义处理和情感分析(NLP)
- 潜在语义分析(LSA)
2.3 基于协同过滤的推荐算法
-
协同过滤:Collaborative Filtering【CF】
-
基于近邻的协同过滤
- 基于用户(User-CF)
- 基于物品(Item-CF)
-
基于模型的协同过滤
- 奇异值分解(SVD)
- 潜在语义分析(LSA)
- 支撑向量机(SVM)
2.4 混合推荐
- 实际网站的推荐系统往往都不是单纯只采用了某一种推荐的机制和策略,往往是将多个方法混合在一起,从而达到更好的推荐效果。
- 比较流行的组合方法有:
- 加权混合
- 切换混合
- 分区混合:采用多种推荐机制,并将不同的推荐结果分不同的区显示给用户
- 分层混合
3 推荐系统评测
3.1 推荐系统实验方法
- 离线实验
- 通过体制系统获得用户行为数据,并按照一定格式生成一个标准的数据集
- 将数据集按照一定的规则分成训练集和测试集
- 在训练集上训练用户兴趣模型,在测试集上进行预测
- 通过事先定义的离线指标评测算法在测试集上的预测结果
- 在线实验
- AB测试
3.2 推荐系统评测指标
- 预测准确度
- 用户满意度
- 覆盖率
- 多样性
- 惊喜度
- 信任度
- 实时性
- 健壮性
- 商业目标
3.3 推荐准确度评测
- 评分预测
- 很多网站都有让用户给物品打分的功能,如果知道用户对物品的历史评分,就可以从中学习一个兴趣模型,从而预测用户对新物品的评分。
- 评分预测的准确度一般用均方根误差(RMSE)或平均绝对误差(MAE)计算。
- Top-N推荐
- 网站提供推荐服务时,一般是给用户一个个性化的推荐列表,这种推荐叫做Top-N推荐
- Top-N推荐的预测准确率一般用精确率(precision)和召回率(recall)来度量
- 准确率、精确率和召回率
- 准确率:就是所有的预测正确(正类预测正确和负类预测正确)的占总的比重。
- 精确率:真正正确的占所有预测为正的比例。
- 召回率:真正正确的占所有实际为正的比例。
4 基于UGC的推荐
-
用户用标签来描述对物品的看法,所以用户生成标签(UGC)是联系用户和物品的纽带,是反映用户兴趣的重要数据源
-
一个用户标签行为的数据集一般由一个三元组(用户,物品,标签)的集合表示,其中一条记录(u,i,b)表示用户u给物品i打上了标签b
-
一个最简单的算法:
-
对于一个用户,首先找到他常用的标签,然后找到具有这些标签的最热门的商品,推荐给他
-
计算公式如下:
p ( u , i ) = ∑ b n u , b n b , i p(u,i)=\sum_bn_{u,b}n_{b,i} p(u,i)=b∑nu,bnb,i
其中, n u , b n_{u,b} nu,b是用户u打过标签b的次数, n b , i n_{b,i} nb,i是物品i被打过标签b的次数。
-
-
存在的问题:
- 这种方法倾向于给热门标签、热门物品比较大的权重,如果一个热门物品同时对应着热门标签,那么它就会霸榜,推荐的个性化、新颖度就会降低
-
解决方案:
-
TF-IDF算法
- 词频-逆文档频率:是一种用于资讯检索与文本挖掘的常用加权技术
- TF-IDF是一种统计方法,用以评估一个词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降: T F I D F = T F ∗ I D F TFIDF=TF*IDF TFIDF=TF∗IDF
- 主要思想:
- 如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类
-
应用上述的思想对算法作出改进:
-
在简单的算法基础之上,直接加入对热门标签和热门物品的惩罚项
-
公式如下:
p ( u , i ) = ∑ b n u , b / l o g ( 1 + n b ( u ) ) ∗ n b , i / l o g ( 1 + n i ( u ) ) p(u,i)=\sum_bn_{u,b}/log(1+n_b^{(u)})*n_{b,i}/log(1+n_i^{(u)}) p(u,i)=b∑nu,b/log(1+nb(u))∗nb,i/log(1+ni(u))
其中, n b ( u ) n_b^{(u)} nb(u)记录了标签b被多少不同的用户使用过, n i ( u ) n_i^{(u)} ni(u)记录了物品i被多少不同的用户打过标签
-
-
4.1 TF-IDF算法实现
# TF-IDF算法示例
import numpy as np
import pandas as pd
import math
# 1. 定义数据和预处理
docA = "The cat sat on my bad"
docB = "The dog sat on my knees"
bowA = docA.split(" ")
bowB = docB.split(" ")
# 构建词库
wordSet = set(bowA).union(set(bowB))
# 2. 进行词数统计
# 用统计词典来保存词出现的次数
wordDictA = dict.fromkeys(wordSet,0)
wordDictB = dict.fromkeys(wordSet,0)
# 遍历文档,统计词数
for word in bowA:
wordDictA[word] += 1
for word in bowB:
wordDictB[word] += 1
# 3. 计算词频TF
def computeTF(wordDict, bow):
# 用一个字典对象记录TF,把所有的词对应在bow文档里的TF都算出来
tfDict = {}
nbowCount = len(bow)
for word, count in wordDict.items():
tfDict[word] = count / nbowCount
return tfDict
tfA = computeTF(wordDictA,bowA)
tfB = computeTF(wordDictB,bowB)
# 4. 计算逆文档频率IDF
def computeIDF(wordDictList):
# 用一个字典对象保存IDF,每个词作为key,初始值为0
idfDict = dict.fromkeys(wordDictList[0], 0)
N = len(wordDictList)
for wordDict in wordDictList:
# 遍历字典中的每个词
for word, count in wordDict.items():
if count > 0:
idfDict[word] += 1
return idfDict
idfs = computeIDF([wordDictA,wordDictB])
# 5. 计算TF-IDF
def computeTDIDF(tf, idfs):
tfidf = {}
for word, tfval in tf.items():
tfidf[word] = tfval * idfs[word]
return tfidf
tfidfA = computeTDIDF(tfA,idfs)
tfidfB = computeTDIDF(tfB,idfs)
5 基于协同过滤的推荐算法
5.1 基于近邻的协同过滤
- 在User-CF和Item-CF两个策略中应该如何选择呢?
- Item-CF应用场景:
- 基于物品的协同过滤推荐机制是Amazon在基于用户的机制上改良的一种策略。因为在大部分的Web站点中,物品的个数是远远小于用户的数量的,而且物品的个数和相似度相对比较稳定,同时基于物品的机制比基于用户的实时性更好一些,所以Item-CF成为了推荐策略的主流。
- User-CF应用场景:
- 设想一下在一些新闻推荐系统中,也许物品—也就是新闻的个数可能大于用户的个数,而且新闻的更新程度也很快,所以它的相似度依然不稳定,这时候用User-CF可能效果更好。
- Item-CF应用场景:
5.2 基于模型的协同过滤
- 基本思想
- 用户具有一定的特征,决定着他的偏好选择
- 物品具有一定的特征,影响着用户是否选择它
- 用户之所以选择某一个商品,是因为用户特征与物品特征相互匹配
- 基于这种思想,模型的建立相当于从行为数据中提取特征,给用户和物品同时打上标签;
- 基于模型的协同过滤推荐,就是基于样本的用户偏好信息,训练一个推荐模型,然后根据实时的用户喜好的信息进行预测新物品的得分,计算推荐
- 训练模型时,可以基于标签内容来提取物品特征,也可以让模型去发掘物品的潜在特征,这样的模型称为隐语义模型(LFM)
- 用LFM来进行协同过滤的目标
- 揭示隐藏的特征,这些特征能够解释为什么给出对应的预测评分
- 这类特征可能是无法直接用语言解释描述的,事实上我们并不需要知道,类似“玄学”
5.3 LFM 梯度下降算法实现
# LFM梯度下降算法实现
import numpy as np
import pandas as pd
# 1. 数据准备
# 评分矩阵 6个用户 5种商品
R = np.array([[4,0,2,0,1],
[0,2,3,0,0],
[1,0,2,4,0],
[5,0,0,3,1],
[0,0,1,5,1],
[0,3,2,4,1]])
# 2. 算法实现
K = 2
max_iter = 10000
alpha = 0.0002
lamda = 0.004
def LFM_grad_desc(R, K, max_iter, alpha, lamda):
# 基本维度参数定义
M = len(R)
N = len(R[0])
# P Q 初始值,随机生成
P = np.random.rand(M, K)
Q = np.random.rand(N, K)
Q = Q.T
# 开始迭代
for step in range(max_iter):
# 对所有的用户u,物品i做遍历,对应的特征向量Pu,Qi梯度下降
for u in range(M):
for i in range(N):
# 对于每一个大于0的评分,求出预测评分误差
if R[u][i] > 0:
eui = np.dot(P[u, :], Q[:, i]) - R[u][i]
# 代入公式,按照梯度下降算法更新当前的Pu,Qi
for k in range(K):
P[u][k] = P[u][k] - alpha * (2 * eui * Q[k][i] + 2 * lamda * P[u][k])
Q[k][i] = Q[k][i] - alpha * (2 * eui * P[u][k] + 2 * lamda * Q[k][i])
# u,i遍历完成,所有特征向量更新完成,可以得到P,Q,那么就可以计算预测评分矩阵
predR = np.dot(P, Q)
# 计算当前损失函数
cost = 0
for u in range(M):
for i in range(N):
if R[u][i] > 0:
cost += (np.dot(P[u, :], Q[:, i]) - R[u][i]) ** 2
# 加上正则化项
for k in range(K):
cost += lamda * (P[u][k] ** 2 + Q[k][i] ** 2)
if(cost < 0.0001):
break;
print(cost)
return P, Q.T, cost
# 3. 测试
P, Q, cost= LFM_grad_desc(R, K, max_iter, alpha, lamda)
predR = P.dot(Q.T)
5.4 协同过滤的优缺点
-
优点:
- 它不需要对物品或者用户进行严格的建模,而且不要求对物品特征的描述是机器可理解的,所以这种方法也是领域无关的
- 这种方法计算出来的推荐是开放的,可以共用他人的经验,很好的支持用户发现潜在的兴趣偏好
-
存在的问题:
- 方法的核心是基于历史数据,所以对新物品和新用户都有冷启动问题
- 推荐的效果依赖于用户历史偏好数据的多少和准确性
- 在大部分的实现中,用户历史偏好是用稀疏矩阵进行存储的,而稀疏矩阵上的计算有些明显的问题,包括可能少部分人的错误偏好会对推荐的准确度有很大的影响等
- 对于一些特殊品味的用户不能给予很好的推荐