现如今,网站用推荐系统为你提供个性化的体验,告诉你买啥,吃啥甚至你应该和谁交朋友。尽管每个人口味不同,但大体都适用这个套路。人们倾向于喜欢那些与自己喜欢的其他东西相似的东西,也倾向于与自己身边的人有相似的口味。推荐系统就尝试捕捉这一规律来帮助预测你也可能喜欢的其他东西。

  为帮用户高效挑选商品,电子商务、社交媒体、视频和在线新闻平台已积极部署了他们自己的推荐系统,这是一个双赢的策略。

  

  推荐系统两个最普遍的类型是基于内容过滤法和协同过滤法。协同过滤法基于用户对商品的评价信息来产生推荐,是用大众的智慧来推荐内容。相比之下,基于内容推荐系统关注的是商品的属性,基于它们之间的相似度给你推荐。

  大体上,协同过滤(CF)是推荐引擎工作的是主力。这一算法有一个很有趣的特点,它能够自主学习,这意味着它能够开始学习哪些特点能为己所用。协同过滤又可分为基于内存的协同过滤和基于模型的协同过滤。在此教程中,你将实现运用奇异值分解的基于模型协同过滤法和通过计算余弦相似性的基于内存协同过滤法。

  我们将使用MovieLens数据集,这是用来实现和测试推荐引擎最普遍的数据集之一。它包含来自于943个用户的10万个电影评价和1682部电影集合。你最好将这个数据集(MoviesLens-100k)解压到你的notebook目录。

  

  

1
2
import numpy
as np
import pandas
as pd

 u.data文件中包含了完整数据集。你可以在这里查阅关于这个数据集的简要描述

1
2
header = ['user_id''item_id''rating''timestamp']
df = pd.read_csv('ml-100k/u.data',
sep
='\t',
names
=header)

 先看一眼数据集中的前两行。接下来,让我们统计其中的用户和电影总数。

n_users = df.user_id.unique().shape[0]
n_items = df.item_id.unique().shape[0]
print 'Number of users = ' + str(n_users) + ' | Number of movies = ' + str(n_items)
Number of users = 943 | Number of movies = 1682

你可以使用scikit-learn文库将数据集分为测试和训练两部分。Cross_validation.train_test_split 模块根据测试样本的百分比将数据混合并分为两部分,在这里百分比为0.25

from sklearn import cross_validation as cv
train_data, test_data = cv.train_test_split(df, test_size=0.25)

基于内存协同过滤法

  基于内存协同过滤法可以被主要分为两部分:用户-项目过滤(user-item filtering)和项目-项目过滤( item-item filtering)。 user-item
filtering选取一个特定用户,基于评价相似性找到与该用户相似的其他用户,并推荐那些相似用户所喜欢的项目。相比之下, item-item filtering 先选取一个项目,然后找出也喜欢这个项目的其他用户,并找出这些用户或相似用户也喜欢的其他项目,推荐过程需要项目并输出其他项目。

  • Item-Item Collaborative Filtering: “Users who liked this item also liked …”
  • User-Item Collaborative Filtering: “Users who are similar to you also liked …”

在这两种情况中,你根据整个数据集创建了一个用户-项目的矩阵。因为已经把数据分成了测试和训练两部分所以你需要创建两个[943 x 1682]矩阵。训练矩阵包含75%的评价,测试矩阵包含25%的矩阵。

用户-项目矩阵例子:

创建了用户-项目矩阵之后,计算相似性并创建一个相似度矩阵。

Item-Item Collaborative Filtering算法中项目之间的相似度依靠观测所有的已对相同项目评价的用户来测算。

对于User-Item Collaborative Filtering算法,用户之间的相似性依靠观测相同用户已评价的所有项目。

  推荐系统中通常使用余弦相似性作为距离度量,在n维孔空间中评价被视为向量,基于这些向量之间的夹角来计算相似性。

  用户a和m可以用下面的公式计算余弦相似性,其中你可以使用用户向量uk和ua之间的点积然后除以这两个向量欧式长度之乘。

  而计算项目m和b之间的相似度可以用下面的公式:

首先创建user-item矩阵,因此你需要创建两个矩阵为测试和训练数据集。

1
2
3
4
5
6
7
8
#Create
two user-item matrices, one for training and another for testing
train_data_matrix = np.zeros((n_users,
n_items))
for line in train_data.itertuples():
    train_data_matrix[line[1]-1,
line[
2]-1= line[3
 
test_data_matrix = np.zeros((n_users,
n_items))
for line in test_data.itertuples():
    test_data_matrix[line[1]-1,
line[
2]-1= line[3]

  你可以使用 sklearn 的pairwise_distances函数来计算余弦相似性。注意,因为评价都为正值输出取值应为0到1.

1
2
3
from sklearn.metrics.pairwise import pairwise_distances
user_similarity = pairwise_distances(train_data_matrix,
metric
='cosine')
item_similarity = pairwise_distances(train_data_matrix.T,
metric
='cosine')

  下一步是作出预测。既然构造了相似度矩阵user_similarityitem_similarity,因此你可以运用下面的公式为user-based
CF做一个预测:

  用户k和用户a之间的相似度根据一个相似用户a的一系列评价的乘积(修正为该用户的平均评价)的权重。你将需要标准化相似度这样可以使评价维持在1到5之间,最后一步,统计你想预测用户平均评价的总和。

  这里考虑到的问题是一些用户评价所有电影时可能要么给最高分,要么给最低分。这些用户给出评价的相对不同比绝对值更重要。例如:设想,用户k对他最喜欢的电影评价4颗星,其他的好电影则评价3颗星。假设现在另一个用户t对他/她喜欢的一部电影评价为5颗星,看了想睡觉的一部电影评价为3颗星。这两位用户电影口味可能很相似但使用评价体系的方法不同。

  当为item-based CF做一个推荐时候,你不要纠正用户的平均评价,因为用户本身用查询来做预测。

1
2
3
4
5
6
7
8
9
def predict(ratings,
similarity, 
type='user'):
    if type == 'user':
        mean_user_rating = ratings.mean(axis=1)
        #You
use np.newaxis so that mean_user_rating has same format as ratings
        ratings_diff = (ratings - mean_user_rating[:,
np.newaxis])
        pred = mean_user_rating[:,
np.newaxis] 
+ similarity.dot(ratings_diff) / np.array([np.abs(similarity).sum(axis=1)]).T
    elif type == 'item':
        pred = ratings.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)])    
    return pred
item_prediction = predict(train_data_matrix, item_similarity, type='item')
user_prediction = predict(train_data_matrix, user_similarity, type='user')

评估  

有许多的评价指标,但是用于评估预测精度最流行的指标之一是Root Mean Squared Error (RMSE)。

你可以用sklearn中的 mean_square_error (MSE)函数,RMSE只是MSE其中的一个平方根。想阅读更多关于不同评估指标你可以
查看这篇文章

因为你仅仅想考虑在这个测试数据集中的预测评价,你可以用prediction[ground_truth.nonzero()]过滤测试矩阵中所有其他的元素。

1
2
3
4
5
6
from sklearn.metrics import mean_squared_error
from math import sqrt
def rmse(prediction,
ground_truth):
    prediction = prediction[ground_truth.nonzero()].flatten()
    ground_truth = ground_truth[ground_truth.nonzero()].flatten()
    return sqrt(mean_squared_error(prediction,
ground_truth))

  

1
2
print 'User-based
CF RMSE: '
 + str(rmse(user_prediction,
test_data_matrix))
print 'Item-based
CF RMSE: '
 + str(rmse(item_prediction,
test_data_matrix))

  

1
2
User-based
CF RMSE: 
3.1236202241
Item-based
CF RMSE: 
3.44983070639

  

Memory-based算法容易实施并产生合理的预测质量。memory-based CF的缺点是它不能扩展到现实世界的场景和没有处理众所周知的冷启动问题(面对新用户或者新项目进去系统时)。Model-based CF方法可伸缩并且能处理 比memory-based方法更高等级的稀疏度,面对新用户或者没有任何评价的新项目进入系统时也会变差。我想感谢Ethan Rosenthal关于Memory-Based Collaborative Filtering的博客

Model-based Collaborative Filtering


基于模型的协同过滤是基于已收到更大的曝光,主要是作为潜变量分解和降维无监督的学习方法矩阵分解(MF)

Model-based Collaborative Filtering基于已收到很多曝光的矩阵因式分解 (MF),主要是作为潜在变量分解和降维无监督学习方法。矩阵因式分解因其能比Memory-based CF更好解决可扩展性和稀疏问题而被广泛用于推荐系统。MF的目标是学习用户潜在的喜好和从已知评分的项目的潜在属性(学习描述评分特征的特点),以随后通过用户和项目的潜在特征点积预测未知的评分。

当你有一个多维度稀疏矩阵,通过矩阵因式分解你能够将用户-项目矩阵(user-item matrix)重构成低评分结构(low-rank structure),并且你能够通过两个低评分( low-rank)矩阵相乘得出这个矩阵,其中矩阵的行包含潜在向量。

通过低评价矩阵乘积尽可能调整这个矩阵近似原始矩阵,以填充原始矩阵中缺失的项。

现在开始计算MovieLens 数据集的稀疏等级:

1
2
sparsity=round(1.0-len(df)/float(n_users*n_items),3)
print 'The
sparsity level of MovieLens100K is '
 +  str(sparsity*100+ '%'

  

1
The
sparsity level of MovieLens100K 
is 93.7%

  举个例子说明学习用户和项目的潜在喜好:就拿MovieLens数据集来说你有一下信息:(用户ID,年龄,地理位置,性别,电影ID,导演,演员,语言,年份,评分)。通过运用矩阵因式分解这个模型学习到重要的用户特征是年龄段(10岁以下、10-18岁、18-30岁、30-90岁)、地理位置和 性别,对电影特征它学习到最重要的是年代、导演和演员。现在如果你回过头来看你已经存储的信息,没有诸如年代等的特征,但是这个模型可以自己学习到。重要的方面是CF模型仅需使用数据(用户ID,电影ID,评分)来学习这些潜在的特征。如果没有数据可用CF模型性能将会很差,因为这样它更困难学习这些潜在的特征。

评分和特征都要使用的模型称为混合推荐系统(Hybrid Recommender Systems),它是Collaborative Filtering 和Content-based 模型两者的结合。混合推荐系统通常比Collaborative Filtering 或者Content-based模型独立地表现出更高的精度:它们能够更好地处理冷启动问题(因为如果你没有可用于数据集的对于用户或项目的任何评价你就很难做出预测)。混合推荐系统将在下一篇介绍中介绍。

SVD

一个知名的矩阵因式分解方法是Singular value decomposition (SVD)。Collaborative Filtering

协同过滤可以通过使用奇异值分解近似矩阵X被配制

				<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>

Python实现个性化推荐一的更多相关文章

  1. Python实现个性化推荐二

    基于内容的推荐引擎是怎么工作的 基于内容的推荐系统,正如你的朋友和同事预期的那样,会考虑商品的实际属性,比如商品描述,商品名,价格等等.如果你以前从没接触过推荐系统,然后现在有人拿枪指着你的头,强迫你 ...

  2. Python个人项目--豆瓣图书个性化推荐

    项目名称: 豆瓣图书个性化推荐 需求简述:从给定的豆瓣用户名中,获取该用户所有豆瓣好友列表,从豆瓣好友中找出他们读过的且评分5星的图书,如果同一本书被不同的好友评5星,评分人数越多推荐度越高. 输入: ...

  3. 个性化推荐调优:重写spark推荐api

    最近用spark的mlib模块中的协同过滤库做个性化推荐.spark里面用的是als算法,本质上是矩阵分解svd降维,把一个M*N的用户商品评分矩阵分解为M*K的userFeature(用户特征矩阵) ...

  4. 使用Python3.7配合协同过滤算法(base on user,基于人)构建一套简单的精准推荐系统(个性化推荐)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_136 时至2020年,个性化推荐可谓风生水起,Youtube,Netflix,甚至于Pornhub,这些在互联网上叱咤风云的流媒体 ...

  5. CSDDN特约专稿:个性化推荐技术漫谈

    本文引自http://i.cnblogs.com/EditPosts.aspx?opt=1 如果说过去的十年是搜索技术大行其道的十年,那么个性化推荐技术将成为未来十年中最重要的革新之一.目前几乎所有大 ...

  6. 为什么要用深度学习来做个性化推荐 CTR 预估

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:苏博览 深度学习应该这一两年计算机圈子里最热的一个词了.基于深度学习,工程师们在图像,语音,NLP等领域都取得了令人振奋的进展.而深 ...

  7. 从0开始做垂直O2O个性化推荐-以58到家美甲为例

    从0开始做垂直O2O个性化推荐 上次以58转转为例,介绍了如何从0开始如何做互联网推荐产品(回复"推荐"阅读),58转转的宝贝为闲置物品,品类多种多样,要做统一的宝贝画像比较难,而 ...

  8. python 人工智能资源推荐

    原创 2017-06-05 玄魂工作室 玄魂工作室 我翻了翻我自己曾经看过的书,还是放弃了推荐.原因很简单,我对这个领域并不是很熟悉,我来推荐资源有点误人子弟.so,简单推点其他人建议给我的内容,希望 ...

  9. 利用python实现电影推荐

    "协同过滤"是推荐系统中的常用技术,按照分析维度的不同可实现"基于用户"和"基于产品"的推荐. 以下是利用python实现电影推荐的具体方法 ...

随机推荐

  1. Unity 游戏框架搭建 (二十三) 重构小工具 Platform

    在日常开发中,我们经常遇到或者写出这样的代码 var sTrAngeNamingVariable = "a variable"; #if UNITY_IOS || UNITY_AN ...

  2. CF1066CBooks Queries(数组的特殊处理)

    题意描述 您需要维护一个数据结构,支持以下三种操作: L id:在现在序列的左边插一个编号为id的物品 R id:在现在序列的右边插一个编号为id的物品 ? id:查询该点左面有几个元素,右面有几个元 ...

  3. uva_11806_Cheerleaders

    In most professional sporting events, cheerleaders play a major role in entertaining the spectators. ...

  4. 分布式网上商城项目- BeanDefinitionStoreException

    BeanDefinitionStoreException: 严重: StandardWrapper.Throwable org.springframework.beans.factory.BeanDe ...

  5. DOM节点操作阶段性总结

    HTML中能看到的所有东西都是dom树中的一个节点,注意是“所有”,使用childNodes()可以看到,回车(换行)也是一个节点. 从上图可以看到,select中有四个option,但是有9个节点. ...

  6. js实现所有异步请求全部加载完毕后,loading效果消失

    在实际开发中,一定有情况是这样的,一个页面我们有多个地方请求了ajax,在这种情况下,我们要实现数据没来之前出现我们炫酷的loading效果,而且要等到所有的ajax都请求完毕后,才让我们的loadi ...

  7. mysql8.0新增用户及密码加密规则修改

    MySQL8.0已经发布GA版,当前最新GA版本为8.0.12.虽然相对于之前版本,MySQL8.0没有加入新元素,但是,经过代码重构,MySQL8.0的优化器更加强大,同时也有一些新特性,如支持索引 ...

  8. CI框架视图继承

    CI(CodeIgniter)框架 视图继承 这个代码不是我撸的 ... 当时在哪儿找的忘了 ... 如果有侵权什么的 ... 联系我删了 ... 需要去core里面创建一个MY_loader.php ...

  9. 定义一个大数组时,出现错误,程序进入HardFault_Handler中断

    在原子的串口程序前加了几个数组定义,加了个对数组处理的函数,出现了HardFault_Handler的错误,不知道怎么解决!!! 因为局部变量是存放在栈区的,而全局变量在全局区(静态区),如果栈区较小 ...

  10. 关于485通信不稳定问题解决方案[STM32产品问题]

    485通讯不稳定的问题(具体表现为有时能通讯上,有时通讯不上) RS485在连接设备过多.通讯距离过长.双绞线质量差,接线不规范等,都会导致通讯不稳定的问题. 解决方案: 一.关于485总线的几个概念 ...