足够详细、足够简单的 Python 版推荐系统入门级—理论篇(上)|Python 主题月

1,514 阅读10分钟

本文正在参加「Python主题月」,详情查看活动链接

什么是推荐引擎

获取客户历史的行为作为数据,推荐引擎使用不同的算法来过滤大量商品数据,向用户推荐适合该用户的商品。并利用这些数据带来信息推荐用户可能会购买的产品。

009.png

如果能猜出用户需求和偏好,然后这些信息给用户推荐商品,恰到好处推荐势必增强用户体验,从而增加对用户的粘性。那么是如何猜出用户的需求和偏好,这些就是一个推荐引擎要做的工作。推荐引擎通过分析用户历史行为数据来推测用户需求和偏好。

创建推荐引擎的基本流程

在展开今天分享前,我们先来想一想通常是如何将商品推荐给用户的这个问题

  • 简单的想法就是将大众都喜欢商品推荐一个用户,大概率这个用户也会喜欢这个商品
  • 进一步做法,就是根据用户特征将用户划分一个一个群,然后将大众范围细化到群范围来推荐群中比较受欢迎的商品给这个用户

上述两种方法都有其各自的缺点。在第一种情况下,最受欢迎的商品对每个用户来说都是一样的,所以每个人都会看到相同的推荐。而在第二种情况下,随着用户数量的增加,用户特征的数量也会增加。因此,将用户分为不同的部分将是一个相对比较困难的任务。

这里的主要问题是,我们无法根据用户的具体兴趣来进行定制推荐。这就像亚马逊推荐你买一台笔记本电脑,相信亚马逊不是因为这个商品被大多数购物者买过。才推荐给你。他们使用一些个性化推荐的方法,这样帮助他们更准确地推荐产品。

008.jpeg

收集数据

建立一个推荐引擎的第一步,也是最关键的一步就是收集数据,数据是关键这一点我深有感触。数据可以通过两种方式收集,显式的和隐式的,这里显式和隐式是相对用户而言。

  • 显式数据是有意提供的信息,即来自用户的输入,如电影评分,用户注册时用户提供填入基本信息,大多数应用不会强制,通过某种方式激励用户填写更多用户信息
  • 隐式数据是指不是有意提供的信息,而是从可用的数据流中收集的信息,如搜索历史、点击率、订单历史等。

数据存储

数据量是前提,数据数量和质量是模型的推荐可以得到多好的结果的上限。例如,在一个电影推荐系统中,用户对电影的评分越多,对其他用户的推荐就越好。所以我们需要将收集到数据存储起来。可以选择适合数据类型的数据库,可以包括标准的 SQL 数据库、NoSQL 数据库或某种对象存储。

数据过滤

在收集和存储数据后,对其进行过滤,根据算法从数据提取用于推荐信息,基于这些信息我们就可以容易给用户进行推荐。

006.png

基于内容的过滤

所谓基于内容的过滤,一句话就可以说清楚。也就是根据用户喜欢的商品,然后找到与这些商品相似的商品推荐给用户。例如一个用户看了很多喜剧片,我们就会为这个用户推荐更多喜剧片。显然这种推荐是存在问题,首先我们每个人爱好不是一层不变的,爱好通常会随着时间而发生变化。

上面解释比较抽象,不好理解,我们还是以 Netflix的例子。用于一个向量表表示一个用户,向量中保存了用户相关的信息。包含用户过去的行为,即用户喜欢/不喜欢的电影和他们给出的评分。这个向量被称为用户向量。项目向量这里项目是电影,项目向量中保存了所有项目相关信息,称为项目向量。项目向量包含每部电影的细节,如类型、演员、导演等。

有了这两向量,用户向量和项目向量,我们通过计算向量间相似度来推测该用户对该物品的喜好程度。

基于内容的过滤算法可以找到用户向量和项目向量之间的余弦,即余弦相似度。A 表示用户向量,B 表示项目向量,通过计算他们之间的余弦来近似他们之间相似度:

sim(A,B)=cos(θ)=ABABsim(A,B) = \cos(\theta) = \frac{AB}{||A|| ||B||}

还有其他方式方式来计算两个向量的相似度,这里列举一些常用也是典型的向量相似性计算的算法

  • Top-n方法:推荐前 n 部电影(这里 n 可以由业务而定)

  • 评分标准法: 设定一个阈值,所有高于该阈值的电影都被推荐

  • 欧式距离(Euclidean Distance): 在 n 维空间计算两个向量的欧式距离

    (x1y1)2++(xnyn)2\sqrt{(x_1 - y_1)^2 + \cdots + (x_n - y_n)^2 }
  • 皮尔逊相关系数(Pearson’s Correlation): 告诉我们两个项目向量的相关性有多大,相关性越高,相似性就越大。皮尔逊相关系数可以用以下公式计算。

sim(u,v)=(ruirˉu)(rvirˉv)(ruirˉu)2(rvirˉv)2sim(u,v) = \frac{\sum (r_{ui} - \bar{r}_u)(r_{vi} - \bar{r}_v)}{ \sqrt{\sum (r_{ui} - \bar{r}_u)^2} \sqrt{\sum(r_{vi} - \bar{r}_v)^2}}

007.jpeg

协同过滤

协同过滤算法使用 "用户行为 "来推荐项目。这是工业中最常用的算法之一,因为不依赖于任何额外的信息,仅需要用户历史行为就可以进行推荐,大致有两种推荐系统分别是用户协同过滤和基于项目的协同过滤,所以接下来重点介绍这两协同过滤。

基于用户的协同过滤

这种算法首先找到用户之间的相似度,基于这个相似度的得分,选择相似的用户,然后并推荐这些相似用户以前喜欢或购买过的产品,比较直观。还是以前面的电影例子,这个算法是根据每个用户对看过的电影的评分,来发现他们之间的相似性。然后用户 u 的对电影 i 喜欢程度就是,和该用户类似用户对电影 i 的评分的加权和来计算的。

Pu,i=v(rv,isu,v)vsu,v P_{u,i} =\frac{\sum_v (r_{v,i} * s_{u,v})}{\sum_v s_{u,v}}

其中 Pu,iP_{u,i} 表示用户 u 对 i 项目评分的预估,rv,ir_{v,i} 则表示用户 v 对商品 i 的评分,su,vs_{u,v} 表示两个用户的相似性

现在,现在将用户对商品评分组成一个向量来作为该用户的向量

  • 采用皮尔逊相关来计算用户 u 和 v 之间的相似性
  • 首先找到两个用户的评价项目,并根据这些项目评价来计算用户之间的相似性
  • 预估评分会用到用户间的相似度值来计算,计算该就有相关度高用户我们认为这样用户比较接近
  • 计算好预估评分值后,根据这些预估评分来进行推荐

还是通过实际例子给大家演示一下应该如何计算

用户/项目X1X2X3X4X5用户均值评分
用户 A41None4None3
用户 BNone4None233
用户 CNone1None443

这是用户对电影的评分矩阵,接下来就来演示一下如何利用该评分矩阵来计算用户 (A,C) 和用 (B,C) 的相似性。这里用户 A 和 C 都看了 x2x_2x4x_4 这两部电影,通过他们对这两部电影评分来计算他们相似度。

rA,C=(13)(13)+(43)(43)(13)2+(43)2(13)2+(43)2=55=1r_{A,C} = \frac{(1-3)(1-3) + (4 - 3)(4 - 3)}{\sqrt{(1-3)^2 + (4 -3 )^2} \sqrt{(1-3)^2 + (4 -3 )^2} } = \frac{5}{5} = 1
rB,C=(43)(13)+(23)(43)+(33)(43)(43)2+(23)2+(33)2(13)2+(43)2+(43)2=0.866r_{B,C} = \frac{(4-3)(1-3) + (2 - 3)(4 - 3) + (3-3)(4 -3)}{\sqrt{(4-3)^2 + (2 -3)^2 + (3-3)^2} \sqrt{(1-3)^2 + (4 -3 )^2} + (4 - 3)^2} = -0.866

用户 A 和 C 之间的相关性大于 B 和 C 之间的相关性,从而得到用户 A 和 C 比较相似,用户 A 喜欢的电影会被推荐给用户 C,反之亦然。

这种算法相当耗时,因为需要计算该用户与其他所有用户的相似度,然后计算出每个相似度分数。解决这个问题的一个方法是只选择几个用户(邻居),而不是对所有的用户来进行计算相似度,也就是说,不对所有的相似度值进行计算,而只选择几个相似度值。有各种方法来选择邻居。

  • 选择一个相似度阈值,并选择所有高于该值的用户
  • 随机选择用户
  • 按照相似度值的降序排列,并选择前 N 个用户
  • 聚类来选择邻近用户
  • 当用户数量较少时,这种算法是有用的。当有大量的用户时,效果并不好,因为计算所有用户对之间的相似度需要大量的时间。这样可以考虑一下用基于项目过滤
基于项目的协同过滤

在基于项目的协同过滤,计算电影两两之间的相似性,在此基础上,将推荐用户过去喜欢电影类似的电影。这个算法的原理类似于用户-用户协同过滤。

Pu,i=N(si,NRu,N)N(si,N)P_{u,i} = \frac{\sum_N(s_{i,N} * R_{u,N})}{\sum_N (s_{i,N})}

计算两个项目之间的相似性

sim(i,j)=cosi,j=i,ji2j2sim(i,j) = \cos {\vec{i},\vec{j}} = \frac{\vec{i},\vec{j}}{||\vec{i}||_2*||\vec{j}||_2}
用户/商品X1X2X3X4X5
用户 A41244
用户 B24421
用户 CNone1None34
平均评分32333

电影 X1 和 X4 之间的相似度比电影 X1 和 X5 之间的相似度要高。有关如何计算相似度和用户间相似度计算方式相同,不过也需要考虑

C1,4=(23)(23)+(43)(43)(23)2+(43)2(23)2+(43)2=1C_{1,4} = \frac{(2-3)(2-3) + (4 - 3)(4 - 3)}{\sqrt{(2-3)^2 + (4 -3 )^2} \sqrt{(2-3)^2 + (4 -3 )^2} } = 1

不过现在有一个问题,,就是增加了一个新的用户或新的项目,会发生什么?这就是所谓的冷启动。

  • 访客冷启动
  • 产品冷启动

访客冷启动,一个新的用户访客或者从其他平台导入的用户,这些用户是没有数据的。由于没有该用户的历史数据,系统不知道该用户的偏好。向该用户推荐项目变得更加困难。解决这个问题方案就是基于统计,将销量排名靠前的商品推荐给用户。

另一方面,商品说产品也行,产品的冷启动是指在市场上推出一个新的商品或将其加入系统。用户的行动信息让我们了解项目之间关系。一个项目被访问或者点击这样互动越多,我们的模型就对项目把握越好,也容易将项目推荐给对的用户,但是对于新项目,是没有用户交互数据的,所以这是冷启动难点,没有交互我们就了解这个商品。不过我们可以利用基于内容的过滤来解决这个问题。推荐系统首先使用新产品的内容进行推荐,然后最终使用用户对该产品的操作。

现在让我们用 Python 来时基于上面介绍内容来时实现简单推荐系统,偏于推荐引擎。