从头开始构建推荐引擎的综合指南
Introduction
在当今世界,每个客户都面临着多种选择。 例如,如果我正在寻找一本书而没有任何具体的想法,那么我的搜索可能会有很多可能性。 我可能会浪费大量时间在互联网上浏览并浏览各种希望获得金牌的网站。 我可能会寻找其他人的推荐。
但如果有一个网站或应用程序可以根据我之前阅读的内容推荐我的书籍,那将是一个巨大的帮助。 而不是在各种网站上浪费时间,我可以登录,瞧! 根据我的口味量身定制10本推荐书籍
这就是推荐引擎所做的事情,如今大多数企业都在利用它们的力量。 从亚马逊到Netflix,从谷歌到Goodreads,推荐引擎是最广泛使用的机器学习技术应用之一。
在本文中,我们将介绍各种类型的推荐引擎算法以及在Python中创建它们的基础知识。 我们还将看到这些算法运作背后的数学。 最后,我们将使用矩阵分解创建我们自己的推荐引擎。
1. What are recommendation engines?
直到最近,人们通常倾向于购买他们的朋友或他们信任的人推荐给他们的产品。 当对产品有任何疑问时,这曾是购买的主要方法。 但随着数字时代的到来,该圈子已经扩展到包括利用某种推荐引擎的在线网站。
推荐引擎使用不同的算法过滤数据,并向用户推荐最相关的项目。 它首先捕获客户的过去行为,并在此基础上推荐用户可能购买的产品。
如果全新用户访问电子商务网站,该网站将不具有该用户的任何过去历史记录。 那么在这种情况下,网站如何向用户推荐产品呢? 一种可能的解决方案可以是推荐最畅销的产品,即需求量高的产品。 另一种可能的解决方案是推荐能够为企业带来最大利润的产品。
如果我们可以根据客户的需求和兴趣向客户推荐一些项目,它将对用户体验产生积极影响并导致频繁访问。 因此,现在的企业通过研究其用户的过去行为来构建智能和智能推荐引擎。
现在我们对推荐引擎有了直觉,现在让我们来看看它们是如何工作的。
2. How does a recommendation engine work?
在深入探讨此主题之前,首先我们将考虑如何向用户推荐项目:
- 我们可以向用户推荐最受所有用户欢迎的商品
- 我们可以根据用户的偏好(用户功能)将用户划分为多个细分,并根据用户所属的细分为他们推荐相应的细分
上述两种方法都有其缺点。在第一种情况下,每个用户最受欢迎的项目是相同的,因此每个人都会看到相同的建议。而在第二种情况下,随着用户数量的增加,功能的数量也将增加。因此,将用户分为不同的部分将是一项非常困难的任务。
这里的主要问题是我们无法根据用户的特定兴趣定制建议。这就像亚马逊推荐你买一台笔记本电脑只是因为它被大多数购物者买了。但幸运的是,亚马逊(或任何其他大公司)不推荐使用上述方法的产品。他们使用一些个性化的方法,帮助他们更准确地推荐产品。
现在让我们通过以下步骤关注推荐引擎的工作原理。
2.1 Data collection
这是构建推荐引擎的第一步也是最关键的一步。 可以通过两种方式收集数据:显式和隐式。 显式数据是有意提供的信息,即来自用户的输入,例如电影评级。 隐含数据是有意提供但从可用数据流(如搜索历史记录,点击次数,订单历史记录等)收集的信息。
在上图中,Netflix以用户给予不同电影的评级形式明确地收集数据。
这里,亚马逊记录了用户的订单历史,这是隐式数据收集模式的一个例子。
2.2 Data storage
数据量决定了模型的建议有多好。 例如,在电影推荐系统中,用户给予电影的评分越多,推荐对其他用户越好。 数据类型在决定必须使用的存储类型方面起着重要作用。 这种类型的存储可以包括标准SQL数据库,NoSQL数据库或某种对象存储。
2.3 Filtering the data
在收集和存储数据之后,我们必须对其进行过滤,以便提取做出最终建议所需的相关信息。
有各种算法可以帮助我们简化过滤过程。 在下一节中,我们将详细介绍每种算法。
2.3.1 Content based filtering
该算法推荐的产品类似于用户过去喜欢的产品。
例如,如果某人喜欢电影“初始”,则该算法将推荐属于同一类型的电影。 但是算法如何理解从哪个类型中挑选和推荐电影呢?
考虑一下Netflix的例子:它们以矢量形式保存与每个用户相关的所有信息。 该向量包含用户的过去行为,即用户喜欢/不喜欢的电影以及他们给出的评级。 该向量称为轮廓向量。 与电影相关的所有信息都存储在称为项目矢量的另一个矢量中。 项目向量包含每部电影的详细信息,如流派,演员,导演等。
基于内容的过滤算法找到轮廓矢量和项目矢量之间的角度的余弦,即余弦相似度。 假设A是轮廓向量而B是项向量,那么它们之间的相似度可以计算为:
根据余弦值(范围在-1到1之间),电影按降序排列,下面两种方法之一用于推荐:
- Top-n方法:推荐前n部电影(这里n可由业务决定)
- 评级量表方法:设置阈值并建议超过该阈值的所有电影
可用于计算相似性的其他方法是:
-
欧几里德距离:如果在n维空间中绘制,相似项目将彼此靠近。 因此,我们可以计算项目之间的距离,并根据该距离向用户推荐项目。 欧氏距离的公式由下式给出:
-
Pearson的相关性:它告诉我们两个项目有多少相关。 相关性越高,相似性就越高。 Pearson的相关性可以使用以下公式计算:
该算法的主要缺点是它仅限于推荐相同类型的项目。它永远不会推荐用户过去没有购买或喜欢过的产品。因此,如果用户过去只观看或喜欢动作片,系统将仅推荐动作片。这是构建引擎的一种非常狭窄的方式。
为了改进这种类型的系统,我们需要一种算法,它不仅可以根据内容推荐项目,还可以推荐用户的行为。
2.3.2协同过滤
让我们通过一个例子来理解这一点。如果A人喜欢3部电影,比如Interstellar,Inception和Predestination,而B人喜欢Inception,Predestination和The Prestige,那么他们的兴趣几乎相似。我们可以肯定地说A应该像Prestige和B应该喜欢Interstellar。协同过滤算法使用“用户行为”来推荐项目。这是业界最常用的算法之一,因为它不依赖于任何其他信息。有不同类型的协作过滤技术,我们将在下面详细介绍它们。
用户 - 用户协同过滤
该算法首先找到用户之间的相似性得分。然后,根据此相似性得分,它会挑选出最相似的用户,并推荐这些类似用户之前喜欢或购买过的产品。
就我们之前的电影示例而言,该算法基于先前给予不同电影的评级来找到每个用户之间的相似性。 通过计算由其他用户给予项目i的用户评级的加权和来计算用户u的项目的预测。
预测Pu,i由下式给出:
这里,
- Pu,我是一个项目的预测
- Rv,i是用户对电影i给出的评级
- Su,v是用户之间的相似性
现在,我们在配置文件向量中对用户进行评级,并且基于此我们必须预测其他用户的评级。 遵循以下步骤:
- 1对于预测,我们需要用户u和v之间的相似性。我们可以使用Pearson相关性。
- 2首先,我们找到用户评价的项目,并根据评级,计算用户之间的相关性。
- 3可以使用相似度值计算预测。 该算法首先计算每个用户之间的相似度,然后基于每个相似度计算预测。 具有较高相关性的用户往往是相似的。
- 4根据这些预测值,提出建议。 让我们用一个例子来理解它:
考虑用户电影评级矩阵:
这里我们有一个用户电影评级矩阵。 为了更实际地理解这一点,让我们在上表中找到用户(A,C)和(B,C)之间的相似性。 由A / [和C评级的公共电影是电影x2和x4以及由B和C评定的是电影x2,x4和x5。
用户A和C之间的相关性大于B和C之间的相关性。因此,用户A和C具有更多相似性,并且用户A喜欢的电影将被推荐给用户C,反之亦然。
该算法非常耗时,因为它涉及计算每个用户的相似性,然后计算每个相似性得分的预测。处理该问题的一种方法是仅选择少数用户(邻居)而不是全部来进行预测,即,不是对所有相似度值进行预测,而是仅选择很少的相似度值。有多种方法可以选择邻居:
- 选择阈值相似度并选择高于该值的所有用户
- 随机选择用户
- 按照相似度值的降序排列邻居,并选择前N个用户
- 使用群集选择邻居
当用户数量较少时,此算法很有用。当存在大量用户时它不起作用,因为计算所有用户对之间的相似性将花费大量时间。这导致我们进行项目项协同过滤,这在用户数量超过推荐项目时有效。
Item-Item协同过滤
在此算法中,我们计算每对项目之间的相似性。
因此,在我们的情况下,我们将找到每个电影对之间的相似性,并基于此,我们将推荐用户过去喜欢的类似电影。 该算法的工作方式类似于用户 - 用户协同过滤,只需稍加改动 - 而不是采用“用户邻居”评级的加权和,我们采用“项目邻居”的评级的加权和。 预测由下式给出:
Now we will find the similarity between items.
现在,由于我们在每部电影和收视率之间存在相似性,因此会做出预测,并根据这些预测,推荐类似的电影。 让我们用一个例子来理解它。
这里的平均项目评级是给予特定项目的所有评级的平均值(将其与我们在用户 - 用户过滤中看到的表格进行比较)。 我们没有找到前面看到的用户 - 用户相似度,而是找到了项目 - 项目的相似性。
为此,首先我们需要找到对这些项目进行评级的用户,并根据评级,计算项目之间的相似性。 让我们找到电影(x1,x4)和(x1,x5)之间的相似性。 评级电影x1和x4的普通用户是A和B,而评级电影x1和x5的用户也是A和B.
电影x1和x4之间的相似度大于电影x1和x5之间的相似度。因此,基于这些相似度值,如果任何用户搜索电影x1,则将推荐电影x4,反之亦然。在进一步实现这些概念之前,有一个问题我们必须知道答案 - 如果在数据集中添加新用户或新项目会发生什么?它被称为冷启动。可以有两种类型的冷启动:
- 1名访客冷启动
- 2产品冷启动
访客冷启动意味着在数据集中引入了新用户。由于该用户没有历史记录,因此系统不知道该用户的偏好。向该用户推荐产品变得更加困难。那么,我们怎样才能解决这个问题呢?一种基本方法可以是应用基于流行度的策略,即推荐最受欢迎的产品。这些可以通过最近整体或区域流行的内容来确定。一旦我们了解了用户的偏好,推荐产品就会更容易。
另一方面,产品冷启动意味着新产品在市场上推出或添加到系统中。用户操作对于确定任何产品的价值至关重要。产品接收的交互越多,我们的模型就越容易将产品推荐给正确的用户。我们可以利用基于内容的过滤来解决这个问题。系统首先使用新产品的内容作为建议,然后最终使用该产品上的用户操作。
现在让我们使用Python中的案例研究巩固我们对这些概念的理解。让你的机器准备就绪,因为这将是有趣的!
3. Case study in Python using the MovieLens Dataset
我们将处理MovieLens数据集并构建模型以向最终用户推荐电影。 该数据已由明尼苏达大学的GroupLens研究项目收集。 数据集可以从[这里](https://grouplens.org/datasets/movielens/100k/)下载。 该数据集包括:
- 1682部电影中943名用户的100,000评级(1-5)
- 用户的人口统计信息(年龄,性别,职业等)
首先,我们将导入我们的标准库并在Python中读取数据集。
import pandas as pd
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# pass in column names for each CSV as the column name is not given in the file and read them using pandas.
# You can check the column names from the readme file
#Reading users file:
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('ml-100k/u.user', sep='|', names=u_cols,encoding='latin-1')
#Reading ratings file:
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=r_cols,encoding='latin-1')
#Reading items file:
i_cols = ['movie id', 'movie title' ,'release date','video release date', 'IMDb URL', 'unknown', 'Action', 'Adventure',
'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy',
'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western']
items = pd.read_csv('ml-100k/u.item', sep='|', names=i_cols,
encoding='latin-1')
加载数据集后,我们应该查看每个文件的内容(用户,评级,项目)。
- 用户
print(users.shape)
users.head()
因此,我们在数据集中有943个用户,每个用户有5个功能,即user_ID,年龄,性别,职业和zip_code。 现在让我们看一下评级文件。
Ratings
print(ratings.shape)
ratings.head()
我们有不同用户和电影组合的100k评级。 现在终于检查items文件。
项目
print(items.shape)
items.head()
此数据集包含1682部电影的属性。 有24列,其中最后19列指定特定电影的类型。 这些是二进制列,即值1表示电影属于该类型,否则为0。
数据集已经被GroupLens划分为训练和测试,其中测试数据对每个用户具有10个评级,即总共9,430行。 我们将把这两个文件都读到我们的Python环境中。
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
ratings_train = pd.read_csv('ml-100k/ua.base', sep='\t', names=r_cols, encoding='latin-1')
ratings_test = pd.read_csv('ml-100k/ua.test', sep='\t', names=r_cols, encoding='latin-1')
ratings_train.shape, ratings_test.shape
现在是时候构建我们推荐的引擎了!
4.从头开始构建协同过滤模型
我们将根据用户 - 用户相似度和项目 - 项目相似性推荐电影。 为此,首先我们需要计算唯一用户和电影的数量。
n_users = ratings.user_id.unique().shape[0]
n_items = ratings.movie_id.unique().shape[0]
现在,我们将创建一个用户项矩阵,可用于计算用户和项之间的相似性。
data_matrix = np.zeros((n_users, n_items))
for line in ratings.itertuples():
data_matrix[line[1]-1, line[2]-1] = line[3]
现在,我们将计算相似度。 我们可以使用sklearn中的pairwise_distance函数来计算余弦相似度。
from sklearn.metrics.pairwise import pairwise_distances
user_similarity = pairwise_distances(data_matrix, metric='cosine')
item_similarity = pairwise_distances(data_matrix.T, metric='cosine')
这为我们提供了数组形式的项目项和用户 - 用户相似性。 下一步是根据这些相似性进行预测。 让我们定义一个函数来做到这一点。
def predict(ratings, similarity, type='user'):
if type == 'user':
mean_user_rating = ratings.mean(axis=1)
#We 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
最后,我们将根据用户相似性和项目相似性进行预测。
user_prediction = predict(data_matrix, user_similarity, type='user')
item_prediction = predict(data_matrix, item_similarity, type='item')
事实证明,我们还有一个库,可以自动生成所有这些建议。 现在让我们学习如何在Python中使用turicreate创建推荐引擎。 要熟悉turicreate并将其安装到您的计算机上,请参阅此处。
5. Building a simple popularity and collaborative filtering model using Turicreate
安装turicreate之后,首先让我们导入它并在我们的环境中读取训练和测试数据集。 由于我们将使用turicreate,因此我们需要在SFrame中转换数据集。
import turicreate
train_data = turicreate.SFrame(ratings_train)
test_data = turicreate.Sframe(ratings_test)
我们有用户行为以及用户和电影的属性,因此我们可以制作基于内容的协作过滤算法。 我们将从一个简单的流行模型开始,然后构建一个协作过滤模型。
首先,我们将构建一个模型,该模型将根据最流行的选择推荐电影,即所有用户都收到相同推荐的模型。 为此,我们将使用turicreate推荐函数popular_recommender。
popularity_model = turicreate.popularity_recommender.create(train_data, user_id='user_id', item_id='movie_id', target='rating')
我们使用的各种论据是:
- train_data:包含所需训练数据的SFrame
- user_id:表示每个用户ID的列名
- item_id:表示要推荐的每个项目的列名(movie_id)
-
target:表示用户给出的分数/等级的列名
这是预测时间! 我们将为数据集中的前5个用户推荐前5项。
popularity_recomm = popularity_model.recommend(users=[1,2,3,4,5],k=5)
popularity_recomm.print_rows(num_rows=25)
请注意,所有用户的建议都是相同的–1467,1201,1189,1122,814。它们都是相同的顺序! 这证实了所有推荐的电影的平均评分为5,即观看电影的所有用户都给出了最高评级。 因此我们的流行度系统按预期工作。
在构建流行度模型之后,我们现在将构建协作过滤模型。 让我们训练项目相似性模型,并为前5个用户提供前5个推荐。
#Training the model
item_sim_model = turicreate.item_similarity_recommender.create(train_data, user_id='user_id', item_id='movie_id', target='rating', similarity_type='cosine')
#Making recommendations
item_sim_recomm = item_sim_model.recommend(users=[1,2,3,4,5],k=5)
item_sim_recomm.print_rows(num_rows=25)
在这里我们可以看到每个用户的建议(movie_id)是不同的。 因此存在个性化,即对于不同的用户,我们有不同的推荐集。
在此模型中,我们没有每个用户给出的每部电影的评级。 我们必须找到一种方法来预测所有这些缺失的评级。 为此,我们必须找到一组功能,可以定义用户如何评价电影。 这些被称为潜在特征。 我们需要找到一种从现有功能中提取最重要的潜在功能的方法。 在下一节中介绍的矩阵分解是一种这样的技术,它使用较低维密集矩阵并有助于提取重要的潜在特征。
6. Introduction to matrix factorization
让我们通过一个例子来理解矩阵分解。 考虑由不同用户给予不同电影的用户电影评级矩阵(1-5)。
这里user_id是不同用户的唯一ID,并且每个电影也被分配了唯一ID。 等级0.0表示用户没有评定该特定电影(1是用户可以给出的最低评级)。 我们想预测这些缺失的评级。 使用矩阵分解,我们可以找到一些潜在的功能,可以确定用户如何评价电影。 我们将矩阵分解为组成部分,使得这些部分的乘积产生原始矩阵。
让我们假设我们必须找到k个潜在特征。 因此我们可以将我们的评级矩阵R(MxN)分成P(MxK)和Q(NxK),使得P x QT(这里QT是Q矩阵的转置)近似于R矩阵:
, where:
- M是用户总数
- N是电影的总数
- K是潜在的总体特征
- R是MxN用户电影评级矩阵
- P是MxK用户特征亲和度矩阵,表示用户和特征之间的关联
- Q是NxK项目 - 特征相关性矩阵,表示电影和特征之间的关联
- Σ是KxK对角线特征权重矩阵,表示特征的基本权重
通过矩阵分解选择潜在特征可消除数据中的噪声。 怎么样? 好吧,它删除了不确定用户如何评价电影的功能。 现在,为了获得用户puk在所有潜在特征k上评定的电影qik的评级rui,我们可以计算2个向量的点积并添加它们以获得基于所有潜在特征的评级。
这就是矩阵分解为我们提供未被用户评价的电影评级的方式。 但是,我们如何才能将新数据添加到用户电影评级矩阵中,即如果新用户加入并评价电影,我们如何将这些数据添加到我们预先存在的矩阵中?
让我通过矩阵分解方法让您更轻松。 如果新用户加入系统,则对角线特征权重矩阵Σ以及项目特征相关性矩阵Q将不会发生变化。唯一的变化将发生在用户特征亲和度矩阵P中。我们可以应用一些 矩阵乘法方法来做到这一点。
我们有,
两边同时乘以Q
现在,我们有:
因此,
进一步简化它,我们可以得到P矩阵:
这是更新的用户特征亲和度矩阵。 类似地,如果将新电影添加到系统中,我们可以遵循类似的步骤来获得更新的项目 - 特征相关性矩阵Q.
记住,我们将R矩阵分解为P和Q.但是我们如何确定哪个P和Q矩阵将近似于R矩阵? 我们可以使用梯度下降算法来做到这一点。 这里的目标是最小化实际评级与使用P和Q估计的评级之间的平方误差。平方误差由下式给出:
这里,
- eui是错误
- rui是用户u给电影i的实际评分
- řui是用户u对电影i的预测评分
我们的目标是以这种误差最小化的方式决定p和q值。 我们需要更新p和q值,以便获得这些矩阵的优化值,这将给出最小的误差。 现在我们将为puk和qki定义更新规则。 梯度下降中的更新规则由要最小化的误差的梯度定义。
由于我们现在有渐变,我们可以应用puk和qki的更新规则。
这里α是学习率,它决定每次更新的大小。 可以重复上述更新,直到错误最小化。 完成后,我们得到最佳P和Q矩阵,可用于预测评级。 让我们快速回顾一下这个算法是如何工作的,然后我们将构建推荐引擎来预测未评级电影的评级。
以下是矩阵分解如何用于预测评级:
# for f = 1,2,....,k :
# for rui ε R :
# predict rui
# update puk and qki
因此,基于每个潜在特征,将使用预测的rui值来填充R矩阵中的所有缺失的等级。 然后使用梯度下降更新puk和qki,并获得它们的最佳值。 它可以显示如下:
现在我们已经理解了这个算法的内部工作原理,我们将举例说明矩阵如何分解为其成分。
考虑一个2×3矩阵,A2X3,如下所示:
这里我们有2个用户及其相应的3部电影评级。 现在,我们将这个矩阵分解为子部分,这样:
AAT的特征值将给出P矩阵,ATA的特征值将给出Q矩阵。 Σ是来自AAT或ATA的特征值的平方根。
计算AAT的特征值。
因此,AAT的特征值是25,9。同样,我们可以计算ATA的特征值。 这些值将是25,9,0。现在我们必须计算AAT和ATA的相应特征向量。
对于λ= 25,我们有:
它可以减少为:
该矩阵内核中的单位长度向量是:
同样,对于λ= 9,我们有:
它可以减少为:
该矩阵内核中的单位长度向量是:
对于最后一个特征向量,我们可以找到垂直于q1和q2的单位向量。 所以,
Σ2X3矩阵是AAT或ATA的特征值的平方根,即25和9。
最后,我们可以通过公式σpi= Aqi或pi = 1 /σ(Aqi)计算P2X2。 这给出了:
因此,A矩阵的分解形式由下式给出:
由于我们有P和Q矩阵,我们可以使用梯度下降方法来获得它们的优化版本。 让我们使用矩阵分解来构建我们的推荐引擎。
7. Building a recommendation engine using matrix factorization
让我们定义一个函数来预测用户给予他/她未评级的所有电影的评级。
class MF():
# Initializing the user-movie rating matrix, no. of latent features, alpha and beta.
def __init__(self, R, K, alpha, beta, iterations):
self.R = R
self.num_users, self.num_items = R.shape
self.K = K
self.alpha = alpha
self.beta = beta
self.iterations = iterations
# Initializing user-feature and movie-feature matrix
def train(self):
self.P = np.random.normal(scale=1./self.K, size=(self.num_users, self.K))
self.Q = np.random.normal(scale=1./self.K, size=(self.num_items, self.K))
# Initializing the bias terms
self.b_u = np.zeros(self.num_users)
self.b_i = np.zeros(self.num_items)
self.b = np.mean(self.R[np.where(self.R != 0)])
# List of training samples
self.samples = [
(i, j, self.R[i, j])
for i in range(self.num_users)
for j in range(self.num_items)
if self.R[i, j] > 0
]
# Stochastic gradient descent for given number of iterations
training_process = []
for i in range(self.iterations):
np.random.shuffle(self.samples)
self.sgd()
mse = self.mse()
training_process.append((i, mse))
if (i+1) % 20 == 0:
print("Iteration: %d ; error = %.4f" % (i+1, mse))
return training_process
# Computing total mean squared error
def mse(self):
xs, ys = self.R.nonzero()
predicted = self.full_matrix()
error = 0
for x, y in zip(xs, ys):
error += pow(self.R[x, y] - predicted[x, y], 2)
return np.sqrt(error)
# Stochastic gradient descent to get optimized P and Q matrix
def sgd(self):
for i, j, r in self.samples:
prediction = self.get_rating(i, j)
e = (r - prediction)
self.b_u[i] += self.alpha * (e - self.beta * self.b_u[i])
self.b_i[j] += self.alpha * (e - self.beta * self.b_i[j])
self.P[i, :] += self.alpha * (e * self.Q[j, :] - self.beta * self.P[i,:])
self.Q[j, :] += self.alpha * (e * self.P[i, :] - self.beta * self.Q[j,:])
# Ratings for user i and moive j
def get_rating(self, i, j):
prediction = self.b + self.b_u[i] + self.b_i[j] + self.P[i, :].dot(self.Q[j, :].T)
return prediction
# Full user-movie rating matrix
def full_matrix(self):
return mf.b + mf.b_u[:,np.newaxis] + mf.b_i[np.newaxis:,] + mf.P.dot(mf.Q.T)
现在我们有一个可以预测评级的功能。 此功能的输入是:
- R - 用户电影评级矩阵
- K - 潜在特征的数量
- alpha - 随机梯度下降的学习率
- beta - 偏差的正则化参数
- iterations - 执行随机梯度下降的迭代次数
我们必须将用户项目评级转换为矩阵形式。 它可以使用python中的pivot函数完成。
R= np.array(ratings.pivot(index = 'user_id', columns ='movie_id', values = 'rating').fillna(0))
fillna(0)将用0填充所有缺失的等级。现在我们有R矩阵。 我们可以初始化潜在要素的数量,但这些要素的数量必须小于或等于原始要素的数量。
现在让我们预测所有缺失的评级。 我们取K = 20,alpha = 0.001,beta = 0.01,迭代= 100。
mf = MF(R, K=20, alpha=0.001, beta=0.01, iterations=100)
training_process = mf.train()
print()
print("P x Q:")
print(mf.full_matrix())
print()
这将为我们提供与每20次迭代相对应的错误值,最后是完整的用户电影评级矩阵。 输出如下所示:
我们已经创建了推荐引擎。 让我们关注如何在下一节中评估推荐引擎。
8.推荐引擎的评估指标
为了评估推荐引擎,我们可以使用以下指标
- 8.1召回:
实际上建议用户喜欢的项目比例是多少
它由下式给出:
这里tp表示他/她喜欢的向用户推荐的项目数量,tp + fn表示用户喜欢的项目总数
如果用户喜欢5个项目并且推荐引擎决定显示3个项目,则召回将为0.6
召回越大,建议越好
8.2精度:
在所有推荐项目中,用户实际喜欢了多少?
它由下式给出:
这里tp表示他/她喜欢的推荐给用户的项目数量,tp + fp表示推荐给用户的总项目数量
如果向用户推荐了5个项目,他喜欢4个,那么精度将为0.8
精度越高,推荐的越好
但请考虑这种情况:如果我们只是推荐所有项目,它们肯定会涵盖用户喜欢的项目。 所以我们100%回忆! 但是考虑一下精度。 如果我们建议说1000个项目而用户只喜欢其中的10个,则精度为0.1%。 这真的很低。 因此,我们的目标应该是最大限度地提高精确度和召回率。
8.3 RMSE(均方根误差):
-
它测量预测评级中的误差:
-
这里,Predicted是模型预测的评级,Actual是原始评级
如果用户对电影给出了5的评分,并且我们将评级预测为4,则RMSE为1
RMSE值越小,建议越好
上述指标告诉我们我们的建议有多准确,但他们并不关注建议的顺序,即他们不关注首先推荐的产品以及之后的产品。 我们需要一些指标,也会考虑推荐产品的顺序。 那么,让我们看看一些排名指标:8.4平均倒数排名:
评估建议列表
假设我们向用户推荐了3部电影,比如给定顺序的A,B,C,但是用户只喜欢电影C.当电影C的等级为3时,倒数等级为1/3
平均互惠等级越大,建议越好
8.5 k处的MAP(截止k处的平均平均精度):
Precision和Recall不关心建议中的排序
截止k处的精度是通过仅考虑从1级到k级的推荐子集计算的精度
假设我们提出了三个建议[0,1,1]。 这里0表示推荐不正确,1表示推荐正确。 那么k处的精度将是[0,1 / 2,2 / 3],平均精度将是(1/3)*(0 + 1/2 + 2/3)= 0.38
平均精度越大,建议越正确
8.6 NDCG(标准化折扣累积增益):
- MAP和NDCG之间的主要区别在于MAP假设某个项目是感兴趣的(或不是),而NDCG给出相关性分数
- 让我们用一个例子来理解它:假设有10部电影–A到J,我们可以推荐前五部电影,即A,B,C,D和E,而我们不能推荐其他5部电影,即F, G,H,I和J.建议是[A,B,C,D]。 因此,在这种情况下,NDCG将为1,因为推荐的产品与用户相关
- NDCG值越高,建议越好
9.还有什么可以尝试的?
到目前为止,我们已经了解了什么是推荐引擎,它的不同类型和工作方式。基于内容的过滤和协同过滤算法都有其优点和缺点。
在某些域中,生成有用的内容描述可能非常困难。如果用户之前的行为未提供相关证据,则基于内容的过滤模型将不会选择项目。必须使用其他技术,以便系统可以在用户已经表现出兴趣的范围之外提出建议。
协同过滤模型没有这些缺点。由于不需要对推荐的项目进行描述,因此系统可以处理任何类型的信息。此外,它可以推荐用户之前未表现出兴趣的产品。但是,如果没有基于预测的用户评级,则协同过滤不能提供对新项目的推荐。即使用户开始对该项目进行评级,在该项目收到足够的评级之前还需要一些时间才能提出准确的建议。
组合基于内容的过滤和协同过滤的系统可以潜在地利用内容的表示以及用户之间的相似性。将协作和基于内容的过滤相结合的一种方法是基于基于内容的推荐和协作推荐的加权平均来进行预测。这样做的各种方法是:
结合项目分数
- 在这种方法中,我们结合从两种过滤方法获得的评级。 最简单的方法是取平均值
- 假设一种方法建议电影的评级为4,而另一种方法建议同一电影的评级为5。 因此,最终建议将是两个评级的平均值,即4.5
- 我们也可以为不同的方法分配不同的权重
结合项目排名:
- 假设协同过滤按以下顺序推荐5部电影A,B,C,D和E:A,B,C,D,E,而基于内容的过滤按以下顺序推荐它们:B,D,A,C,E
- 电影的排名将是:
协同过滤
Content Based Filtering:基于内容的过滤
因此,混合推荐引擎将组合这些等级并基于组合排名做出最终推荐。 合并排名将是:
建议将根据这些排名进行。 因此,最终建议如下:B,A,D,C,E。
以这种方式,可以组合两种或更多种技术以构建混合推荐引擎并提高它们的整体推荐准确度和功率。
结束笔记
这是一篇关于推荐引擎的非常全面的文章。 本教程应该足以让您开始使用此主题。 我们不仅介绍了基本的推荐技术,还了解了如何实现当今业界可用的一些更先进的技术。
我们还介绍了与每种技术相关的一些关键事实。 作为想要学习如何制作推荐引擎的人,我建议您学习本教程中讨论的技术,然后在模型中实现它们。
上一篇: 亚马逊最便宜平板 499元Fire平板强势登陆中国
下一篇: 普通类获取Spring容器中的Bean
推荐阅读