在我看来,作为一位中国人的我们不管做什么决定都在面临多种选择。例如,如果我这个时候想要买一本书,但是我却不知道我想看什么书、不知道类型、不知道方向,那么这个时候打开各种进行软件搜索可能会出现各种各样的结果。我可能会浪费大量时间在互联网上浏览各种并在各个希望淘金的站点中进行拖曳。我可能会寻求其他人的建议。
但是,如果有一个网站或应用程序可以根据我之前阅读的内容向我推荐书,那么会很好的帮助到我,不用浪费时间在各种网站上自己去找书,我只需登录网站或者应用程序就好了!它会根据我的口味量身定制的10本书推荐给我
这就是推荐引擎所做的事情,现如今,大多数企业正在利用它的力量。从亚马逊到网飞(Netflix),从谷歌到Goodreads,毫不夸张的说推荐引擎是机器学习技术中使用最广泛的应用之一。
在本文中,我们将介绍各种类型的推荐引擎算法以及在Python中创建推荐引擎的基础知识。我们还将看到这些算法工作背后的数学原理。最后,我们将使用矩阵分解来创建自己的推荐引擎。
在买东西的时候,如果对产品有任何疑问的时候,人们通常倾向于购买他们的朋友或信任的人推荐给他们的产品。这在曾经是人们主要的购买方式。但是随着数字时代的到来,这个圈子已经扩大到包括利用某种推荐引擎的网站。
推荐引擎使用不同的算法过滤数据,并向用户推荐最相关的物品。它首先记录了客户的过去行为,并在此基础上推荐了用户可能购买的产品。
如果是一个全新的用户访问了电子商务网站,则该网站将没有该用户的任何历史记录。那么在这种情况下,网站如何向用户推荐产品呢?一种可能的解决方案是推荐网站内最畅销的产品,即需求量大的产品。另一个可能的解决方案是推荐可以为企业带来最大利润的产品。
如果我们可以根据客户的需求和兴趣向他们推荐一些商品,那么它将对用户的体验产生积极影响并可能会导致用户的频繁访问。因此,当今的企业正在通过研究用户的过去行为来构建智能的推荐引擎。
现在,我们对推荐引擎有了一个大体的了解,现在让我们看一下它是怎么工作的。
在深入探讨这个主题之前,首先我们先考虑一下如何向用户推荐商品:
以上的两种方法都有其缺点。在第一种情况下,每个用户最受欢迎的商品都是相同的,因此每个人都会看到相同的推荐。在第二种情况下,随着用户数量的增加,用户特性的数量也会增加。因此,将用户划分为不同的部分将是一项非常困难的任务。
这里的主要问题是我们无法根据用户的特定兴趣来定制建议。就像亚马逊推荐你购买笔记本电脑,只是因为它被大多数购物者购买了。但值得庆幸的是,亚马逊(或任何其他大公司)都不推荐使用上述方法的产品。他们使用一些个性化的方法来帮助他们更准确地推荐产品。
现在,通过执行以下的步骤来重点介绍推荐引擎的工作方式。
这是构建推荐引擎的第一步,也是最关键的一步。可以通过两种方式收集数据:显式和隐式。 显式数据是有意提供的信息,即来自用户的输入,例如电影分级。隐式数据是不是有意提供的信息,而是从可用数据流(例如搜索历史,点击次数,订单历史记录等)中收集的信息。
在上图中,Netflix正在以用户对不同电影给出的评分的形式明确地收集数据。
在这里,用户的订单历史记录是由Amazon记录的,这是隐式数据收集模式的一个例子。
数据量决定了模型推荐的质量。例如,在电影推荐系统中,用户对电影的评分越高,对其他用户的推荐就越好。数据类型在决定必须使用的存储类型方面起着重要作用。这种类型的存储可以包括标准SQL数据库,NoSQL数据库或某种对象存储。
在收集和存储数据之后,我们必须对其进行过滤,以提取出最终推荐所需的相关信息。
有各种各样的算法可以帮助我们简化过滤的过程。在下一节中,我们将详细介绍每种算法。
该算法推荐与用户过去喜欢的产品相似的产品。
例如,如果某人喜欢电影“盗梦空间”,那么这个算法将推荐给他属于同一类型的电影。但是,该算法如何理解从哪个类型中挑选电影并推荐呢?
**以Netflix为例。**他们以向量的形式保存与每个用户有关的所有信息。该向量包含用户过去的行为,即用户喜欢/不喜欢的电影以及他们给出的评分。这个向量称为轮廓向量。与电影有关的所有信息都存储在另一个称为物品向量的向量中。物品向量包含每部电影的详细信息,例如类型,演员,导演等。
基于内容的过滤算法找到轮廓向量和物品向量之间的角度的余弦值,即余弦相似度。假设A是轮廓向量,B是物品向量,则它们之间的相似度可以计算为:\operatorname{sim}(A, B)=\cos (\theta)=\frac{A \cdot B}{\|A\||| B \|}sim(A,B)=cos(θ)=∥A∥∣∣B∥A⋅B基于介于-1到1之间的余弦值,电影以降序排列,推荐使用以下两种方法之一:
其他可用于计算相似度的方法是:
\text { Euclidean Distance }=\sqrt{\left(x_{1}-y_{1}\right)^{2}+\ldots+\left(x_{N}-y_{N}\right)^{2}} Euclidean Distance =(x1−y1)2+…+(xN−yN)2
\operatorname{sim}(u, v)=\frac{\sum\left(r_{u i}-\bar{r}_{u}\right)\left(r_{v i}-\bar{r}_{v}\right)}{\sqrt{\sum\left(r_{u i}-\bar{r}_{u}\right)^{2}} \sqrt{\sum\left(r_{v i}-\bar{r}_{v}\right)^{2}}}sim(u,v)=∑(rui−rˉu)2∑(rvi−rˉv)2∑(rui−rˉu)(rvi−rˉv)
该算法的主要缺点是它仅限于推荐相同类型的项目。绝不会推荐用户过去从未购买或不喜欢的产品。因此,如果用户过去仅观看或喜欢动作电影,则系统将仅推荐动作电影。这是构建引擎的一种非常狭窄的方法。
为了改进这种类型的系统,我们需要一种算法,该算法不仅可以根据内容来推荐商品,还可以根据用户的行为来推荐商品。
让我们通过一个例子来理解这一点。如果A喜欢《星际穿越》,《盗梦空间》和《前目的地》等三部电影,而B人喜欢《盗梦空间》,《前目的地》和《致命魔术》,那么他们的兴趣几乎相同。我们可以肯定地说,A应该喜欢《致命魔术》,B应该喜欢《星际穿越》。协同过滤算法使用“用户行为”来推荐项目。这是业界最常用的算法之一,因为它不依赖于任何其他信息。协同过滤技术有多种类型,我们将在下面详细介绍它们。
该算法首先找到用户之间的相似度得分。然后,根据相似度评分,挑选出最相似的用户,并推荐这些相似的用户之前喜欢或购买的产品。
就我们之前的电影例子来说,该算法根据每个用户先前对不同电影给予的评分来找到每个用户之间的相似性。通过计算其他用户对项目i给出的用户评分的加权总和,可以计算出用户u对某个项目的预测。
预测Pu,i由下式给出:P_{u, i}=\frac{\sum_{v}\left(r_{v, i} * s_{u, v}\right)}{\sum_{v} s_{u, v}}Pu,i=∑vsu,v∑v(rv,i∗su,v)公式解读,
现在,我们在配置文件向量中具有用户的评分,并基于此我们必须预测其他用户的评分。为此我们将要采取以下的步骤:
考虑用户电影评分矩阵:
用户/电影X1X2X3X4X5平均用户评分A41–4–3B–4–233C–1–443
这里我们有一个用户电影分级矩阵。为了更实际地理解这一点,让我们在上表中找到用户(A,C)和(B,C)之间的相似性。由A和C评级的电影是电影x2和x4,由B和C评级的电影是x2,x4和x5。\begin{aligned} &\mathrm{r}_{\mathrm{AC}}=\left[(1-3)^{*}(1-3)+(4-3)^{*}(4-3)\right]\left[\left(1(1-3)^{2}+(4-3)^{2}\right)^{32+}\left((1-3)^{2}+(4-3)^{2}\right)^{3 / 3}\right]=1\\ &\mathrm{r}_{\mathrm{BC}}=\left[(4-3)^{*}(1-3)+(2-3)^{*}(4-3)+(3-3)^{*}(4-3) M\left((4-3)^{2}+(2 \cdot 3)^{2}+(3-3)^{2}\right)^{3 / 2}+\left((1-3)^{2}+(4-3)^{2}+(4-3)^{2}\right)^{1 / 2}\right]=-0.866 \end{aligned}rAC=[(1−3)∗(1−3)+(4−3)∗(4−3)][(1(1−3)2+(4−3)2)32+((1−3)2+(4−3)2)3/3]=1rBC=[(4−3)∗(1−3)+(2−3)∗(4−3)+(3−3)∗(4−3)M((4−3)2+(2⋅3)2+(3−3)2)3/2+((1−3)2+(4−3)2+(4−3)2)1/2]=−0.866用户A和C之间的相关性大于B和C之间的相关性。因此,用户A和C具有更高的相似性,并且将向用户C推荐用户A喜欢的电影,反之亦然。
该算法非常耗时,因为它涉及为每个用户计算相似度,然后为每个相似度分数计算预测。处理此问题的一种方法是仅选择几个用户(邻居)而不是全部进行预测,也就是我们不选择对所有相似性值进行预测,而是仅选择几个相似性值。选择邻居的方法有很多:
当用户数较少时,此算法很有用。当有大量用户时,此方法无效,因为计算所有用户对之间的相似度将花费大量时间。这导致我们进行物品-物品协同过滤,当用户数量超过建议的物品数时,这种方法是有效的。
在该算法中,我们计算每对项目之间的相似度。
因此,在我们的案例中,我们将发现每个电影对之间的相似性,并以此为基础,推荐过去用户喜欢的相似电影。该算法的工作原理与基于用户的协同过滤类似,只是有一点点变化–我们计算“项目-邻居”的加权总和,而不是计算“用户-邻居”的加权总和。预测如下:P_{u, i}=\frac{\sum_{N}\left(s_{i, N} * R_{u, N}\right)}{\sum_{N}\left(\left|s_{i, N}\right|\right)}Pu,i=∑N(∣si,N∣)∑N(si,N∗Ru,N)现在我们将发现项目之间的相似性。\operatorname{sim}(i, j)=\cos (\vec{i}, \vec{j})=\frac{\vec{i} \cdot \vec{j}}{\|\vec{i}\|_{2} *\|\vec{j}\|_{2}}sim(i,j)=cos(i,j)=∥i∥2∗∥j∥2i⋅j现在,由于我们有了每部电影和评分之间的相似性,因此进行了预测,并根据这些预测推荐了类似的电影。让我们通过一个例子来理解它。
用户/电影x1X2X3X4X5A41244B24421C–1–34平均物品评分32333
这里的平均物品评分是对特定物品给予的所有评分的平均值(将其与我们在基于用户的协同过滤中看到的表进行比较)。与我们之前看到的基于用户的相似度不同,我们查找到的基于项目的相似度。\begin{aligned} &\mathrm{C}_{14}=\left[(4-3)^{*}(4-3)+(2-3)^{*}(2-3)\right] /\left[\left((4-3)^{2}+(2-3)^{2}\right)^{1/2} *\left((4-3)^{2}+(2-3)^{2}\right)^{1 / 2}\right]=1\\ &\mathrm{C}_{15}=\left[(4-3)^{*}(4-3)+(2-3)^{*}(1-3)\right] /\left[\left((4-3)^{2}+(2-3)^{2}\right)^{1/2} *\left((4-3)^{2}+(1-3)^{2}\right)^{1/2}\right]=0.94 \end{aligned}C14=[(4−3)∗(4−3)+(2−3)∗(2−3)]/[((4−3)2+(2−3)2)1/2∗((4−3)2+(2−3)2)1/2]=1C15=[(4−3)∗(4−3)+(2−3)∗(1−3)]/[((4−3)2+(2−3)2)1/2∗((4−3)2+(1−3)2)1/2]=0.94电影x1和x4之间的相似度大于电影x1和x5之间的相似度。因此,基于这些相似值,如果有任何用户搜索电影x1,那么将会向他们推荐电影X4,反之亦然。在进一步实施这些概念之前,我们必须知道一个问题的答案–如果在数据集中添加新用户或新物品,将会发生什么?这被称为 冷启动。冷启动可以有两种类型:
用户冷启动意味着在数据集中引入了一个新用户。由于没有该用户的历史记录,因此系统不知道该用户的首选项。向该用户推荐物品变得越来越困难。那么,如何解决这个问题呢?一种基本方法是应用基于流行度的策略,即推荐最受欢迎的物品。这些可以通过最近整体或区域流行的内容来确定。一旦我们了解了用户的喜好,推荐物品就会更加容易。
另一方面,物品冷启动意味着将新产品投放市场或添加到系统中。用户行为是对于确定任何产品的价值的最重要的因素。物品获得的互动越多,我们的模型就越容易将物品推荐给合适的用户。我们可以利用基于内容的过滤来解决此问题。系统首先将新产品的内容用于推荐,然后最终用户对该产品执行操作。
现在,使用Python中的一个案例研究来巩固对这些概念的理解。准备好你的电脑,因为这将会很有趣!
我们将处理MovieLens数据集,并建立一个模型来向最终用户推荐电影。这些数据是由明尼苏达大学的GroupLens研究项目收集的。该数据集包括:
首先,我们将导入标准库并使用Python读取数据集。你可以通过下方的代码,帮助你进行入门。你可以在自己的电脑上运行代码并获取输出:
# importing libraries import pandas as pd import numpy as np # 传递每个CSV的列名,因为该文件没有给出列名,使用Pandas进行读取他们 #你可以从readme文件中检查列名 #阅读用户文件 u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code'] users = pd.read_csv('ml-100k/u.user', sep='|', names=u_cols,encoding='latin-1') # 阅读评级文件: 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') # 阅读物品文件: 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("\nUser Data :") print("shape : ", users.shape) print(users.head()) #数据集中有943个用户,每个用户有5个特征,也就是用户ID,年龄,性别,职业,和编码 # 评分数据 print("\nRatings Data :") print("shape : ", ratings.shape) print(ratings.head()) # 我们有不同的用户和电影的组合的10万行数据量的评分,现在最后检查物品文件 # Item Data print("\nItem Data :") print("shape : ", items.shape) print(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
现在是构建我们推荐的引擎的时候了!
我们将根据基于用户相似度和基于物品相似度进行推荐电影。为此,首先我们需要计算唯一身份用户和电影的数量。
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中的pairwi se_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) #我们用np.newaxis使得mean_user_rating具有与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并将其安装在你的计算机上,请上GitHub上搜索turicreate。
安装turicreate之后,首先让我们导入它,并在我们的环境中读取训练和测试数据集。由于我们将使用turicreate,因此需要在SFrame中转换数据集。
import turicreate train_data = turicreate.SFrame(ratings_train) test_data = turicreate.Sframe(ratings_test)
我们具有用户行为以及用户和电影的属性,因此我们可以制作基于内容的内容协同过滤算法。我们将从一个简单的流行度模型开始,然后构建一个协同过滤模型。
首先,我们将建立一个模型,该模型将根据最受欢迎的选择来推荐电影,即所有用户都收到相同推荐的模型。我们将使用turicreate推荐功能的 popularity_recommender函数。
popularity_model = turicreate.popularity_recommender.create(train_data, user_id='user_id', item_id='movie_id', target='rating')
我们使用的各种参数:
现在是预测时间!我们将为数据集中的前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个建议。
#训练模型 item_sim_model = turicreate.item_similarity_recommender.create(train_data, user_id='user_id', item_id='movie_id', target='rating', similarity_type='cosine') #提出推荐 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)是不同的。因此个性化是存在的,即对于不同的用户,我们有不同的推荐集。
在此模型中,我们没有每个用户给出的每部电影的评分。我们必须找到一种方法来预测所有这些缺失的评分。为此,我们必须找到一组可以定义用户如何评价电影的特征。这些称为潜在特征。我们需要找到一种从现有特征中提取最重要的潜在特征的方法。下一部分将介绍的矩阵分解是一种这样的技术,它使用较低维度的密集矩阵并有助于提取重要的潜在特征。
让我们用一个例子来了解矩阵分解。考虑由不同用户给不同电影的用户电影评级矩阵(1-5)。
这里的user_id是不同用户的唯一ID,每部电影也都分配了唯一的ID。评分为0.0表示用户尚未对特定电影评分(1是用户可以给予的最低评分)。我们要预测这些缺失的评分。使用矩阵分解,我们可以找到一些潜在的特征,这些这些特征可以确定用户如何评价电影。我们将矩阵分解为组成部分,使这些部分的乘积将生成原始矩阵。
假设我们必须找到k个潜在特征。因此,我们可以将评级矩阵R(MxN)分为P(MxK)和Q(NxK),以使P x QT(此处QT是Q矩阵的转置)近似于R矩阵:\mathrm{R}=\mathrm{P} \Sigma \mathrm{Q}^{\mathrm{T}}R=PΣQT公式内容:
通过矩阵分解选择潜在特征可消除数据中的噪声。怎么样?好吧,它删除了那些无法确定用户如何评价电影的特征。要获得用户puk对一部电影qik的所有潜在特征k的评分,我们可以计算这两个向量的点积,并将它们相加,得到基于所有潜在特征的评分。r_{u i}=\Sigma^{K}_{k=1} p_{u k} \sigma_{k} q_{k i}rui=Σk=1Kpukσkqki这就是矩阵分解为我们提供未由用户评级的电影的评级的方式。但是,如何将新数据添加到我们的用户-电影评分矩阵中呢?也就是说新用户加入并对电影进行评分,我们如何将这些数据添加到现有矩阵中?
让我用矩阵分解方法使你更轻松的理解。如果有新用户加入系统,则对角特征权重矩阵Σ以及项目特征相关性矩阵Q都将保持不变。唯一的变化将发生在用户特征相似度矩阵P中。我们可以应用一些矩阵乘法方法可以做到这一点。
我们有,\mathrm{R}=\mathrm{P} \Sigma \mathrm{Q}^{\mathrm{T}}R=PΣQT让我们在两边都乘以Q。\mathrm{RQ}=\mathrm{P} \Sigma \mathrm{Q}^{\mathrm{T}} \mathrm{Q}RQ=PΣQTQ现在,我们有\mathrm{Q}^{\top} \mathrm{Q}=1Q⊤Q=1所以,
\mathrm{RQ}=\mathrm{P} \SigmaRQ=PΣ进一步简化,我们可以得到P矩阵:
\mathrm{RQ\Sigma}^{-1}=\mathrm{P}RQΣ−1=P
这是更新后的用户特征相似性矩阵。类似地,如果将新电影添加到系统中,我们可以遵循类似的步骤来获取更新的物品特征相关性矩阵Q。
记住,我们将R矩阵分解为P和Q。但是我们如何确定哪个P和Q矩阵将逼近R矩阵呢?我们可以使用梯度下降算法来做到这一点。此处的目的是实际等级与使用P和Q估算的评分之间的平方误差最小。该平方误差由下式给出:
\mathrm{e}_{\mathrm{ui}^{2}}=\left(\mathrm{r}_{\mathrm{ui}}-\check{\mathrm{r}}_{\mathrm{ui}}\right)^{2}=\left(\mathrm{r}_{\mathrm{ui}}-\Sigma_{\mathrm{k}=1}^{\mathrm{k}} \mathrm{p}_{\mathrm{uk}} \sigma_{\mathrm{k}} \mathrm{q}_{\mathrm{ki}}\right)^{2}eui2=(rui−rˇui)2=(rui−Σk=1kpukσkqki)2
这里,
我们的目标是确定p和q的值,使得误差最小化。我们需要更新p和q值,以便获得这些矩阵的优化值,从而使误差最小。现在,我们将为puk和qki定义一个更新规则。梯度下降中的更新规则由要最小化的误差的梯度定义。\frac{\partial}{\partial p u k}\left(e_{u i}^{2}\right)=-2\left(r_{u i}-\check{r}_{u i}\right) q_{k i}=-2 e_{u i} q_{k i}∂puk∂(eui2)=−2(rui−rˇui)qki=−2euiqki
\frac{\partial}{\partial q k i}\left(e_{u i}^{2}\right)=-2\left(r_{u i}-\tilde{r}_{u i}\right) p_{u k}=-2 e_{u i} p_{u k}∂qki∂(eui2)=−2(rui−r~ui)puk=−2euipuk
由于现在我们有了梯度,我们可以为puk和qki应用更新规则。\mathrm{p}_{\mathrm{uk}}^{\prime}=\mathrm{p}_{\mathrm{uk}}-\alpha^{*} \frac{\partial}{\partial p u k}\left(\mathrm{e}_{u \mathrm{l}}^{2}\right)=\mathrm{p}_{\mathrm{uk}}+2 \mathrm{e}_{\mathrm{ui}} \mathrm{q}_{\mathrm{k}}puk′=puk−α∗∂puk∂(eul2)=puk+2euiqk
q_{k j}^{\prime}=q_{k i}-\alpha^{*} \frac{\partial}{\partial q k i}\left(e_{u i}^{2}\right)=q_{k i}+2 e_{u i} p_{u k}qkj′=qki−α∗∂qki∂(eui2)=qki+2euipuk
α是学习速率决定每个更新的大小。可以重复上述的更新,直到将错误最小化为止。完成之后,我们将获得可用于预测收视率的最佳P和Q矩阵。让我们快速回顾一下该算法的工作原理,然后我们将构建推荐引擎来预测未评分电影的评分。
以下是矩阵分解如何用于预测收视率的方法:
# for f = 1,2,....,k : # for rui ε R : # predict rui # update puk and qki
因此,基于每个潜在特征,将使用预测的rui值填充R矩阵中所有缺失的评分。然后使用梯度下降对puk和qki进行更新,并获得它们的最佳值。可以如下显示:
现在,我们已经了解了该算法的内部工作原理,我们将举一个例子,看看如何将矩阵分解为它的组成部分。
考虑一个2 X 3矩阵A 2X3,如下所示:
在这里,我们有2个用户和3个电影的相应评分。现在,我们将把这个矩阵分解为子部分,像这样:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nO23UsOj-1589942971148)(.\图片\14.png)]
AAT的特征值将给我们P矩阵,而ATA的特征值将给我们Q矩阵。Σ是AAT或ATA的特征值的平方根。
计算AAT的特征值。
\begin{aligned} &\operatorname{det}\left(A A^{\top}-\lambda l\right)=0\\ &\lambda^{2}-34 \lambda+225=(\lambda-25)(\lambda-9)=0 \end{aligned}det(AA⊤−λl)=0λ2−34λ+225=(λ−25)(λ−9)=0因此,AAT的特征值是25、9。类似地,我们可以计算ATA的特征值。这些值将分别为25、9、0。现在,我们必须为AAT和ATA计算相应的特征向量。
对于λ= 25,我们有:
可以将其简化为:
该矩阵中的单位长度向量为:
同样,λ= 9我们有:
我们可以将行简化为
该矩阵中的单位长度向量为:
该矩阵的内核中的单位长度向量为:
同样,对于λ= 9,我们有:
可以将其减少为:
该矩阵的内核中的单位长度向量为:
对于最后一个特征向量,我们可以找到一个垂直于q1和q2的单位向量。所以,
Σ 2X3矩阵是矩阵特征值的平方根AAT或 ATA,即,25和9。
最后,我们可以通过公式σpi= Aqi或pi = 1 /σ(Aqi)来计算P 2X2。给出:
因此,A矩阵的分解形式为:
由于我们拥有P和Q矩阵,因此我们可以使用梯度下降方法来获得它们的优化版本。让我们使用矩阵分解来构建推荐引擎。
我们定义一个函数来预测用户对所有未由他/她评分的电影的评分。
class MF(): # 初始化用户电影评级矩阵, no.潜在的特征,α和β。 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 #初始化用户特征和电影矩阵 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)) #初始化偏差项 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)]) #训练样本名单 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 ] #给定迭代次数的随机梯度下降 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 # 计算总平均平方误差 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) # 随机梯度下降得到优化的P和Q矩阵 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,:]) # 用户 i 和 电影 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 # 完整的用户电影评分矩阵 def full_matrix(self): return mf.b + mf.b_u[:,np.newaxis] + mf.b_i[np.newaxis:,] + mf.P.dot(mf.Q.T)
现在我们有了一个可以预测评分的函数。此函数的输入是:
我们必须将用户项目评分转换为矩阵形式。可以使用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和iterations = 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次迭代相对应的误差值,最后是得到完整的用户电影评分矩阵。输出看起来像这样:
我们已经创建了推荐引擎。在下一节中,我们将重点介绍如何评估推荐引擎。
为了评估推荐引擎,我们可以使用以下指标
\text { Recall }=\frac{t p}{t p+f n} Recall =tp+fntp
上面的指标告诉我们我们的建议有多准确,但是它们不关注建议的顺序,即它们不关注首先推荐的产品以及之后推荐的产品。我们需要一些指标,也应考虑推荐产品的顺序。因此,让我们看一些排名指标:
到目前为止,我们已经了解了什么是推荐引擎,它的不同类型及其工作方式。基于内容的过滤和基于物品的过滤算法都有其优点和缺点。
在某些领域,生成有用的内容描述可能非常困难。如果用户的先前行为没有为此提供相关证据,则基于内容的过滤模型将不会选择项目。必须使用其他技术,以便系统可以在用户已经表现出兴趣的范围之外提出建议。
基于物品的过滤模型没有这些缺点。因为不需要描述所建议的项目,所以系统可以处理任何类型的信息。此外,它可以推荐用户以前不感兴趣的产品。但是,如果没有基于用户评分的预测,则基于物品的过滤无法为新项目提供建议。即使用户开始对该商品进行评分,该商品也需要花费一些时间才能获得足够的评分,以便做出准确的推荐。
结合了基于内容的过滤和基于物品的过滤的系统可能会从内容的表示形式以及用户之间的相似性中受益。结合基于物品的协作过滤和基于内容的过滤的一种方法是基于基于内容的推荐和基于物品的推荐的加权平均值进行预测。这样做的各种方法是:
基于物品的协同过滤
电影排名A1B0.8C0.6D0.4E0.2
基于内容的过滤:
电影排名B1D0.8A0.6C0.4E0.2
因此,混合推荐引擎将合并这些排名,并根据合并后的排名做出最终推荐。合并排名为:
电影新排名A1 + 0.6 = 1.6B0.8 + 1 = 1.8C0.6 + 0.4 = 1D0.4 + 0.8 = 1.2E0.2 + 0.2 = 0.4
推荐将根据这些排名进行。因此,最终建议将如下所示:B,A,D,C,E。
通过这种方式,可以将两种或更多种技术组合起来以构建混合推荐引擎并提高它们的总体推荐准确性和能力。
这是一篇有关推荐引擎的非常全面的文章。本教程应该足够好,可以帮助你开始学习推荐引擎这个主题。我们不仅介绍了基本的推荐技术,还介绍了如何实施当今行业中可用的一些更先进的技术。
我们还介绍了与每种技术相关的一些关键事实。作为想学习如何创建推荐引擎的人,我建议你学习本教程中讨论的技术,然后在模型中实现它们。
原文链接:https://www.analyticsvidhya.com/blog/2018/06/comprehensive-guide-recommendation-engine-python/?utm_source=blog&utm_medium=comprehensive-guide-k-means-cluster
数据分析咨询请扫描二维码
作为数据分析领域的探险家,我们常常面临着选择正确工具和技能的挑战。在这个数字化时代,学会并精通适合行业需求的工具显得尤为 ...
2024-12-03在数据分析领域,掌握多种软件和编程语言至关重要,选择合适的工具取决于个人需求和背景。让我们一起探索常用的数据分析工具及其 ...
2024-12-03在数据驱动的时代,数据分析成为了关键的技能。选择合适的数据分析工具至关重要,因为它们直接影响着你对数据的理解和分析效果。 ...
2024-12-03在当今数字化时代,数据分析已经成为各行各业中至关重要的角色。随着技术的迅猛发展和数据量的爆炸增长,数据分析师需要不断提升 ...
2024-12-03在当今数据驱动的世界中,数据分析已成为企业决策制定和战略规划的关键。其中,数据可视化是将复杂数据转化为简洁、易懂图形的重 ...
2024-12-03在当今信息爆炸的时代,数据扮演着至关重要的角色。学会利用数据进行分析不仅是一种技能,更是一种战略性决策工具。本文将探讨学 ...
2024-12-03揭示数据的无限价值 学习数据分析不仅仅是一种技能,更是探索信息海洋中宝藏的钥匙。数据分析的实用性体现在多个领域,如企业决 ...
2024-12-03在当今信息爆炸的时代,数据扮演着至关重要的角色。成为一名优秀的数据分析师,不仅需要具备技术实力,更需要拥有跨学科的知识储 ...
2024-12-03在当今数据驱动的世界中,成为一名优秀的数据分析师需要具备多方面的技能和知识。从统计学基础到机器学习算法,再到沟通能力和业 ...
2024-12-03在当今信息爆炸的时代,数据分析扮演着至关重要的角色。从商业决策到科学研究,数据分析为我们提供了深刻的洞察力和指导方向。然 ...
2024-12-03数据分析的基础知识 数据分析是一个多步骤且复杂的过程,旨在从数据中提取有价值信息以支持决策。这涉及数据的收集、清洗、转换 ...
2024-12-03数据分析是一门引人入胜且充满挑战的领域,它串联着数据的意义与我们的决策需求。无论你是初学者还是经验丰富的专家,掌握数据分 ...
2024-12-03数据分析培训的就业前景展现出令人振奋的态势。随着大数据、人工智能等前沿技术的快速发展,数据分析在各行各业中的应用愈发广泛 ...
2024-12-03在当今数字化时代,数据分析技能的重要性日益凸显。随着大数据、人工智能等领域的迅速发展,数据分析已经成为各行各业中备受瞩目 ...
2024-12-03作为一名数据分析师,除了扎实的数学基础外,掌握软技能同样至关重要。本文将深入探讨数据分析领域中不可或缺的软技能,并结合个 ...
2024-12-03市场需求与技术驱动 数据分析师的职业前景广阔,市场需求旺盛。在金融、医疗、零售、科技等领域,企业对数据分析师的需求不断攀 ...
2024-12-03市场需求与前景 数据分析师的职业前景广阔,伴随着多元化技能要求和清晰的职业发展路径。 在金融、医疗、零售、科技等领域, ...
2024-12-03作为数据分析师,掌握正确的工具和技能至关重要。在当今数据驱动的世界中,Python作为一种多才多艺的编程语言,在数据分析领域扮 ...
2024-12-03在当今数据驱动的世界中,数据分析师扮演着至关重要的角色。他们需要掌握各种工具和技能来从海量数据中提炼出有价值的信息。其中 ...
2024-12-03数据分析实践是一门引人入胜的艺术,融合了技术与创意,为各行业带来前所未有的洞察力与决策支持。本文将探讨数据分析实战案例的 ...
2024-12-03