阅读 548

用Python进行奇异值分解(SVD)实战指南

原文链接: mp.weixin.qq.com
编写:Bing 来源:论智

你是否经常沉迷于各大视频网站,连续不断地追剧?或者在某些音乐软件的推荐列表中发现十分合自己口味的歌曲?事实上,这些视频网站和音乐软件能如此“智能”、私人化的背后,是一系列推荐机制。

本文来源于机器学习工程师Daniel Pyrathon的一次演讲,他是一款名为Coffee meets Bagel的社交APP的工程师。在这次演讲中,他向大家讲解了Python在推荐引擎的学习算法中的应用。

什么是推荐引擎

很多人都听说过“搜索引擎”,推荐引擎与搜索引擎类似,是主动发现用户当前或潜在的需求定律,并主动推送信息给用户的信息网络,相当于在每个用户上都安装了一个搜索引擎。推荐引擎的优势在于,它可以实时学习,不断更新,随着用户使用某项应用或与其交互进行学习,并不断优化结果。总的来说,推荐引擎的优点有两个:

  • 增强用户粘性:如果用了推荐系统,用户粘性会比传统的搜索引擎效果更佳

  • 多样化的推荐:如果用户以个人为单位,大量的数据会生成多样化的推荐结果

目前,许多大公司都将推荐机制作为开发的重点。零售业巨头亚马逊35%的收益来自于它的推荐引擎,视频网站Netflix中75%的用户都是基于推荐算法选择影片。本文将针对推荐算法的一个通用策略——协同过滤(collaborative filtering)进行讲解,这是推荐引擎的一个细分领域,为了更好地理解这一策略,我们先从它的组成部分说起。

协同过滤有三大要素:用户、评分和产品。首先,用户是系统的重要组成因素,他们可以是博客的读者,或者是网上商城的顾客。其次,产品就很容易理解了,可以是歌曲或者电影。最后,评分是连接用户和产品之间的桥梁,它可以用数字表示,对用户和产品之间的关系进行量化,也可以是点赞或反对等等可以让用户表达自己意见的方式。下文将以电影为例子,具体讲解推荐机制。

什么是协同过滤?

协同过滤是利用来自相似用户的评分进行内容推荐的一种方法,具体可以用以下矩阵表示:

这里有五位用户和四部电影,每个格子中代表用户对某部电影的意见。现在,推荐机制想要猜测用户5对蓝色电影的意见,即

协同过滤的第一步就是寻找与目标用户相似的用户。经过对比我们发现,用户2和用户5都支持绿色电影,都反对黄色电影;用户3和用户5都支持红色电影和绿色电影;用户2和3都对绿色和蓝色电影给出了一致意见。所以我们可以很容易地进行初步推测,用户5可能也不喜欢蓝色电影。

这就是用现有的用户评分,对目标用户行为进行协同推测。除此之外,协同过滤还有很多形式,这里,我们着重要讲的是其中一种方法——奇异值分解(Singular Value Decomposition)。

奇异值分解

奇异值分解(SVD)是目前推荐引擎中一种常用的算法,Spotify曾在文章中表示他们利用SVD进行推荐。Netflix还曾在2009年举办过一场竞赛,希望找到能提高Netflix推荐算法准确度的方法,最终获胜的团队正是利用SVD的一种变体,将推荐准确度提升了10%,并获得了一百万美元奖金。下面就是SVD的主要组成要素。

什么是特征(features)

特征是机器学习算法中与用户和产品有关的元数据,在电影领域,用户的特征包括年龄、国家、性别等,产品特征包括上映日期、导演、时长等。事实上我们认为,用户对产品的评价都来自于这些特征,我们将这些特征输入到学习算法中,之后对各个特征的权重进行定义。

然而这些特征都是由人类定义的,并且是可以看到的。除此之外还有许多看不见的特征,它们在预测评分时非常重要。类似SVD这类的算法可以在数据库中,基于已知的特征,学习生成抽象的、新的特征——隐性特征(latent feature)。隐性特征没有具体的形式,但是可以用于高度信息化的语境中对用户行为进行预测。

如何生成隐性特征?

这里,我们继续用电影作为案例。下面是三位用户和四部电影,每位用户对其中几部电影进行了评分,数字越大表示用户越喜爱这部电影。

SVD中用到的方法称为矩阵分解(matrix factorization),也就是将上面的矩阵分解为两个小矩阵。将SVD运行到上面的矩阵中后,我们得到以下结果:

我们在用户和电影中分别得到了两个隐性特征,如果将这两个小矩阵重新结合,会得到与中间矩阵相似的结果。为了方便讲解,这里只用到了两个隐性特征,事实上,隐性特征可以根据需要生成,隐性特征越多,就表示你从原始矩阵中提取到的信息越多。

隐性特征的用途主要有两种:预测新分数和进行对比。当我们有了隐性特征,就能随意组合进行预测。例如我们想预测用户1对蓝色电影的看法,就可以进行数量积运算:

最终得到的结果为3.52,表明用户1对蓝色电影的评价较好。

除此之外,有了隐性特征,我们还能对各元素进行对比,即在各用户之间或各部电影之间进行对比,从而找到用户之间或电影之间的相似度。这里我用的是余弦相似性进行表示。

从图中可以看出,用户1和3之间的夹角更小(0.046),也就是说二者的相似度比用户3和用户2之间的更高。

Demo

接下来,让我们看看SVD的具体操作过程。首先作者介绍了如何训练SVD模型,接着会讲到如何生成推荐内容。

训练一个SVD模型

首先,我们要下载一个名为MovieLens的数据集,这个数据集非常有名,内含2.7万部电影和13.8万用户,总共有2000万个评分。我们这里列出了五组电影评分数据:

接着,我们要用到一个名为Surprise的库训练SVD,这一过程只需要四步。

第一步,创建一个读取器。读取器是Surprise库中的一个元素,它可以定义评分中的高低值。

第二步,数据集初始化。在这一案例中,我们将数据分为三部分:用户编号、产品编号(电影名称)、评分。

第三步,保留一部分数据用于测试。这里留下了25%的数据。

第四步,将SVD运行到数据集上。

训练SVD算法后会生成两个矩阵,分别是用户矩阵和产品矩阵。在模型之上还有一个名为qi的属性,在这个案例中,qi的值如下所示:

(596,100)表示我们共研究了596部电影的评分,每部电影有100个隐性特征。那么我们该如何将这些隐性特征与电影对应起来呢?这里我们用到了一种隐藏特征——raw2inner_items,这是一个词典,可以将隐性特征与电影的另一个特征row_idx对应起来。

预测评分

用模型预测电影评非常简单,只需要用到Surprise库中的predict() API就可以实现。

est分数就是预测的评分

相似性

我们知道,如果两个对象之间的余弦距离越接近0,表明二者越相似。这里,我们要评估三部电影之间的相似性——《星球大战》(1977)、《星球大战VI:绝地归来》(1983)和《阿拉丁)(1992)。首先,我们先比较《星球大战》和《星球大战VI:绝地归来》之间的余弦距离,结果是0.296。接着,我们比较《星球大战》和《阿拉丁》之间的余弦距离,结果是0.859。表明《星球大战》和《星球大战VI:绝地归来》之间的相似度更高。这一过程只用到了评分,没有其他任何训练数据。

接着,我们还可以搜索与某一影片相关的其他电影,并且按相似度进行排名:

结语

在此次演讲中,Daniel Pyrathon向我们展示了SVD在推荐算法中强大的功能。同时,生成的隐性特征不仅仅能用于推荐算法,还可以用在分类算法中。最重要的是,即使对分类算法没有过多地了解,也可以尝试SVD的应用,并使用Surprise库,因为Python真的非常简洁,大大降低了SVD算法的准入门槛。

视频地址:www.youtube.com/watch?v=d7iIb_XVkZs

GitHub地址:github.com/PirosB3/PyConUs2018

文章分类
后端