推荐系统
推荐系统是指能够预测用户对一组项目的未来偏好并推荐最佳项目的系统。现代社会需要推荐系统的一个重要原因是,由于互联网的普及,人们有太多的选择。过去,人们习惯在实体店购物,实体店的商品有限。例如,可以放在大片商店的电影数量取决于商店的大小。相比之下,如今,互联网允许人们在线访问丰富的资源。例如,网飞收藏了大量的电影。虽然可获得的信息量增加了,但新的问题出现了,因为人们很难选择他们真正想看的项目。这就是推荐系统的用武之地。本文将简要介绍构建推荐系统的两种典型方法,协同过滤和奇异值分解。
构建推荐系统的方法:
有两种方法可以构建推荐系统:
**1。基于内容的推荐:**推荐系统的目标是预测用户未评级项目的得分。内容过滤背后的基本思想是每个项目都有一些特征 x。例如,电影“爱情在最后”是一部爱情电影,其特征𝑥₁得分高,但特征𝑥₂.得分低
Movie Ratings Data
每个人都有一个参数θ,表示他们有多喜欢爱情电影,有多喜欢动作片。如果θ是[1,0.1],说明这个人爱看言情片,不爱看动作片。那么对于每个人,我们可以用线性回归找到最优的θ。
(Notation)
r(i,j): 1 if user j has rated movie i (0 otherwise)
y(i,j): rating by user j on movie i (if defined)
θ(j): parameter vector for user
x(i): feature vector for movie i
predicted rating [user j, movie i]: (θ(j))ᵀx(i)
m(j): # of movies rated by user j
nᵤ: # of users
n: # of features of a movie
给定上面的符号,用户 j 的优化目标可以写成如下:
Optimization Objective for user j
因为我们想为所有用户找到最佳参数,所以我们有很多这样的参数。
Optimization Objectives for All Users
我们希望对这些目标有一个单一的表述。注意 m(j)只是一个不影响优化的常数。因此,忽略 m(j)个因素,我们可以将所有目标相加,得到一个单一的表达式。
Optimization Objective
因此,梯度下降可以用下面的表达式来执行:
Cost Updating Function
**2。协作过滤:**内容过滤的缺点是它需要每个项目的辅助信息。比如言情、动作之类的体裁就是电影的边信息。让某人观看电影并为每部电影和未来的每部电影添加补充信息是非常昂贵的。此外,一个人怎么可能列出一部电影的所有特征?如果想增加一个新功能,该怎么办?我们要给所有的电影增加新的功能吗?协同过滤解决了这个问题。首先,让我们考虑内容过滤的相反方法。也就是说,我们能根据用户偏好参数预测电影的特征吗?
Predict the features of movies
我们将再次使用线性回归来预测特征。
Optimization Objective for movie i
请注意,这一次我们将最小化特征 x 的成本,而不是参数θ。我们想预测所有电影的特征。
Optimization Objectives for All Movies
与我们之前所做的类似,我们希望用一个表达式来表达这些目标。
Optimization Objective
现在,我们有两个优化表达式,一个用于查找最佳参数θ,另一个用于查找最佳特征 x。
Two Optimization Objectives
我们可以同时找到最优参数θ和最优特征 x。我们可以将两个优化目标合二为一。请注意,两次双重求和都是遍历 r(i,j)=1 的所有数据。因此,我们可以将两种优化相加。
Collaborative Filtering Optimization Objective
我们用 1/2 代替 1,因为这样做在数学上更方便。这里要注意一个很有意思的事情,就是我们不需要把截距项 1 加到 x 上,为什么呢?因为如果算法需要截距项 1,它可以通过将 x 的第一项设置为 1 来实现。(现实中,我们不知道 x1,x2,…代表什么。所以我们设置了任意数量的特征。第一个特征可以代表偏差。)因此,成本更新函数如下所示:
Cost Updating Functions
交替最小二乘法:
我们之前讨论过协同过滤不需要任何关于用户或项目的信息。那么,有没有另一种方法可以让我们弄清楚用户和商品之间的关系呢?
事实证明,如果我们应用矩阵分解,我们就能做到。通常,矩阵分解应用于降维领域,我们试图在保持相关信息的同时减少特征的数量。主成分分析(PCA)和非常相似的奇异值分解(SVD)就是这种情况。
从本质上讲,我们是否可以获得一个用户/物品交互的大矩阵,并在一个更小的用户特征和物品特征矩阵中找出将它们相互关联的潜在(或隐藏)特征?这正是 ALS 试图通过矩阵分解实现的。
如下图所示,假设我们有一个大小为 MxNMxN 的原始评分矩阵 RR,其中 MM 是用户数量,NN 是项目数量。这个矩阵非常稀疏,因为大多数用户每个人只与几个项目交互。我们可以将该矩阵分解成两个独立的更小的矩阵:一个具有维度 MxKMxK,这将是我们对于每个用户(U)(U)的潜在用户特征向量,而第二个具有维度 KxNKxN,这将具有我们对于每个项目(V)(V)的潜在项目特征向量。将这两个特征矩阵相乘接近原始矩阵,但是现在我们有两个密集的矩阵,包括我们的每个项目和用户的许多潜在特征 KK。
为了求解 UU 和 VV,我们可以利用 SVD(这将需要对可能非常大的矩阵求逆,并且计算量很大)来更精确地求解因式分解,或者应用 ALS 来近似它。在 ALS 的情况下,我们一次只需要求解一个特征向量,这意味着它可以并行运行!(这一巨大优势可能是它成为 Spark 首选方法的原因)。为此,我们可以随机初始化 UU 并求解 VV。然后我们可以回过头来,用我们的 VV 解来求解 UU。像这样反复迭代,直到我们得到一个尽可能接近 RR 的收敛点。
随机梯度下降优化;
随机梯度下降(SGD)优化是一种并行算法,可以解决推荐系统的相同问题。该算法以随机顺序遍历训练数据中的所有评级,对于每个已知评级 r ,它做出预测 r* (基于向量 x 和 y 的点积)并计算预测误差 e 。然后,我们通过在梯度的相反方向上移动它们来修改 x 和 y ,为 x 和 y 的每个特征产生某些更新公式。
推荐系统应用开发
余弦相似度、等级阈值和其他定制技术
在本文中,我们将使用余弦相似度(CS)和 Python 编程语言的其他自定义公式开发一个推荐系统(RS)。这个应用程序将是我在硕士论文期间从事的项目的一部分。
有许多方法可以建立一个 RS。在这里,我们将开发特别解决 RSs 冷启动问题的方法。冷启动问题是在没有关于用户(新注册用户)的大量信息的情况下为用户做出推荐的困难。在这个项目中,我们将研究仅使用少量用户信息进行推荐的方法(允许用户选择他们感兴趣的类别)。
要求:
- Python 3
- numpy
- 熊猫
- nltk
我假设您在这些文章的整个开发过程中都了解 Python。我不会把重点放在也不会详细描述 Python 代码,因为这些文章的主要目的是讲授如何使用 CS 和其他技术来构建 RS。同样值得一提的是,我可能会写一些更好的代码,因为我不是 Python 大师。如果你意识到了这样的部分,请在评论中告诉我,这样我可以在以后重构它:)
我们将开发 4 个不同的版本来研究不同的方法来改进我们的系统。首先,我们将从具有余弦相似度的推荐系统开始。
我们将要建立的 RS 将根据所选的类别推荐 5 个不同的旅游城市。当然,这些技术和方法以后可以应用于不同环境的应用程序。
请在此下载我们的 RS 将基于的数据集。
该数据集的一些要素(列)是我之前从猫途鹰网站获得的真实信息,而其中一些只是我添加的随机要素,以便稍后实现和显示不同的技术。我们的数据集由 25 个城市组成,具有以下特征:**城市,受欢迎程度,描述,图像,评级,评级计数,正面评论,负面评论。**您可以在下面看到前 5 个城市的数据集预览。
City dataset preview
我从猫途鹰身上获得的特征是:城市、知名度、描述和形象。除此之外的功能都是我随机制作的。我们不会在 RS 的第一个版本中使用这些特性,但是它们会在这个系列的其他部分中用于不同的技术。
让我们回顾一下每项功能的含义:
- 城市:城市名称
- 受欢迎程度:为城市保存评论计数。
- 描述:关于城市的博客帖子
- 图像:城市的背景图像
- 评分:城市的平均评分值(0-10)
- rating_count:从用户处收到的评级数量
- 正面评论:正面评论的数量。
- 负面评论:负面评论的数量。
现在我们已经下载了数据集并了解了特性,我们可以开始开发了。如前所述,在第一个版本中,我们将只使用城市和描述特性。
版本 1
RS 的第一个版本将根据我们数据集中城市的描述特征给出建议。RS 将使用余弦相似度计算城市描述和与用户可能选择的旅行类别相关的关键字之间的相似度,然后返回具有最高相似度得分的前 5 个城市。
余弦相似性
余弦相似性是两个向量之间的相似性的度量,通过计算投影到多维空间中的两个向量之间的角度的余弦。它可以应用于数据集上可用的项目,以通过关键字或其他指标计算彼此的相似性。两个向量(A 和 B)之间的相似性通过取两个向量的点积并除以幅度值来计算,如下式所示。我们可以简单地说,两个向量的 CS 分数随着它们之间的角度减小而增加。
Cosine Similarity Calculation for vectors A and B
Similarity between vectors A and B on 3-dimensional space
预处理
首先,我们需要对我们的数据集做一些预处理,使其可以用于我们的 CS 计算方法。让我们在包含数据集的文件夹中创建一个名为 pre_processing.py 的 python 文件。
我们将只清除数据集的描述要素。我们需要从描述中删除停用词。停用词是没有任何上下文意义的词,例如;the,for,an,a,or,what 等。移除这些单词的动机是确保相似性分数不会因为非上下文单词而降低。这将对分数产生负面影响,因为每个单词在空间中创建了不同的维度,并且这些维度的对应值将总是零,因为我们的关键字中没有一个将包括非上下文相关的单词。
import numpy as np
import pandas as pd
from nltk.corpus import stopwordsdef clear(city):
city = city.lower()
city = city.split()
city_keywords = [word for word in city if word not in stopwords.words('english')] merged_city = " ".join(city_keywords)
return merged_city
我们将使用上面的清除(城市)方法来清除城市描述。它的工作原理如下:
- 它接受一个名为 city 的字符串参数
- 降低字符串中的每个字符。lower()方法。
- 用创建单词列表。split()方法。
- 通过删除英语的停用词来初始化 city _ keywords(nltk 框架)
- 从清除的单词中合并一个字符串并返回它
现在,让我们将此方法应用于数据集中的每个条目,如下所示:
for index, row in df.iterrows():
clear_desc = clear(row['description'])
df.at[index, 'description'] = clear_descupdated_dataset = df.to_csv('city_data_cleared.csv')
该代码块将清除我们数据集中所有城市的所有描述,然后将更新后的描述保存为 city_data_cleared.csv 文件。从现在开始,我们将使用这个清除的数据集。
pre_processing.py 要点:
用余弦相似度计算相似度得分
现在我们已经清除了城市描述,我们可以开始实现负责计算相似性得分的类了。让我们创建一个名为余弦相似性. py. 的 python 文件
正如我前面提到的,该方法将根据两个字符串包含的单词来计算它们的相似度。首先,这两个字符串将被转换成向量,然后向量中的每个单词将在单词空间上创建一个维度。如果一个向量中存在的任何单词在另一个向量中不存在,则另一个向量的相应维度的值将为零。
**不是:**余弦相似度是尺度不变的,意义;一个单词在给定的字符串中出现的次数对它没有太大的影响。不管怎样,我们使用余弦相似度,因为我们只关心一个单词是否在两个字符串中都存在,我们不关心一个单词出现了多少次。但是,如果你对这种计数差异感兴趣,并希望你的推荐者考虑到这一点(这意味着分数将受到单词出现次数的极大影响),那么我会建议你去看看皮尔森相关性。
即使只有一种计算方法,让我们在一个类下创建它,以提高以后的可用性。
import re, math
from collections import Counterclass CosineSimilarity:
def __init__(self):
print("Cosine Similarity initialized")
[@staticmethod](http://twitter.com/staticmethod)
def cosine_similarity_of(text1, text2):
first = re.compile(r"[\w']+").findall(text1)
second = re.compile(r"[\w']+").findall(text2)
vector1 = Counter(first)
vector2 = Counter(second) common = set(vector1.keys()).intersection(set(vector2.keys())) dot_product = 0.0 for i in common:
dot_product += vector1[i] * vector2[i] squared_sum_vector1 = 0.0
squared_sum_vector2 = 0.0 for i in vector1.keys():
squared_sum_vector1 += vector1[i]**2 for i in vector2.keys():
squared_sum_vector2 += vector2[i]**2 magnitude = math.sqrt(squared_sum_vector1) * math.sqrt(squared_sum_vector2) if not magnitude:
return 0.0
else:
return float(dot_product) / magnitude
余弦相似度方法的工作原理如下:
- 接受两个字符串参数
- 借助正则表达式获取两个字符串的单词
- 用 Counter (words,word count)初始化字典,其中键对应于一个单词,值对应于该特定单词的计数。
- 获取在两个向量中都存在的常用单词
- 按照余弦相似性一节中介绍的公式计算余弦相似性,并返回值。
cosine_similarity.py 要点:
cosine_similarity.py
推荐引擎
接下来,我们将编写负责推荐的引擎。
engine 类将会很小,因为在版本 1 中,我们将只通过比较关键字和城市描述来提供建议,但是我们将把它作为一个单独的类,因为在本系列的下一部分中,我们将在其他版本中对它进行迭代和开发。
recommender_engine.py:
recommender_engine.py for Version-1
get_recommendations(keywords)方法的工作方式如下:
- 接受字符串参数来计算城市描述的余弦相似性
- 用给定的参数计算每个城市的 CS,并将其作为字典保存为
- 创建一个包含城市、受欢迎程度、描述和分数要素的空数据框。
- 将得分最高的 5 个城市添加到此数据框中
- 将数据帧转换为 JSON 并返回。
请求代码
现在我们将测试我们的引擎(以及 CS 计算功能)。让我们创建一个 request.py python 文件。
我们将在三个不同的类别下测试我们的推荐引擎:
- 文化、艺术和历史
- 沙滩和阳光
- 夜生活和派对
我调查了数据集中所有城市的描述,并手动确定了每个类别的关键字,如下所示:
- [历史历史艺术建筑城市文化]
- 【沙滩沙滩公园自然度假海海边沙滩阳光阳光明媚】
- [夜总会夜总会夜生活酒吧酒吧酒吧酒馆派对啤酒]
让我们添加以下代码,该代码将发送一个请求,以获取给定关键字的前 5 个相似城市,以及预定义的关键字:
from recommender_engine import RecommenderEngineculture_keywords = "history historical art architecture city culture"
beach_n_sun_keywords = "beach beaches park nature holiday sea seaside sand sunshine sun sunny"
nightlife_keywords = "nightclub nightclubs nightlife bar bars pub pubs party beer"def get_recommendations(keywords):
result = RecommenderEngine.get_recommendations(keywords)
return result
然后让我们编写一个 helper 方法来从 JSON 中获取城市名称和分数,如下所示:
def get_top_5_city_names_out_of_json(json_string):
list = json.loads(json_string)
result = []
max = len(list)
i = 0
while i < max:
result.append(list[i]['city'])
i += 1 return result
现在,我们将针对 3 个类别向推荐者发出 3 个请求,然后打印前 5 个城市及其每个类别的相似性得分:
top_5_cultural_cities = get_recommendations(culture_keywords)
city_names_for_cultural = get_top_5_city_names_out_of_json(top_5_cultural_cities)
print(city_names_for_cultural)
print("#################")top_5_summer_cities = get_recommendations(beach_n_sun_keywords)
city_names_for_summer = get_top_5_city_names_out_of_json(top_5_summer_cities)
print(city_names_for_summer)
print("#################")top_5_party_cities = get_recommendations(nightlife_keywords)
city_names_for_party = get_top_5_city_names_out_of_json(top_5_party_cities)
print(city_names_for_party)
print("#################")
当我们运行代码时,我们将获得所有 3 个类别的建议,但让我们只调查文化、艺术和历史类别的结果:
[('Athens', 0.21629522817435007),
('St. Petersburg', 0.16666666666666666),
('Stockholm', 0.14962640041614492),
('Milan', 0.140028008402801),
('Rome', 0.12171612389003691)]
如上所示,雅典的相似性得分为 21.6%,而罗马为 12.17%。分数可能比你预期的要低。得分较低是因为,每个城市的描述自然比我们提供的用于比较的关键词有更多的词。不同的词在空间上创建不同的维度,并且由于我们的关键词没有这些词,这些维度的相应值将为零,这导致较低的相似性得分。如果你从关键词中增加或减少单词,你会发现结果也会改变。
request.py 要点:
request.py
版本 1 的结论
在这个版本中,我们开发了一个推荐应用程序,通过计算城市描述与给定类别关键字的余弦相似性,为三个不同类别的旅行提供城市推荐。
即使相似性得分很低,当您调查每个类别返回的前 5 个城市时;你可以看到我们的推荐系统,推荐有意义和合适的城市。不妨看看城市描述验证一下:)
我们已经到了第一版的末尾。你可以从这里访问所有为第一版写的代码。
在下面的下一个版本中,我们将实现一个不同的方法来计算分数,包括余弦相似性和城市的评级信息。
版本 2(评级贡献)
在这个版本中,我们将利用数据集的评级功能,并改进我们的推荐应用程序,使其更加动态,并提供更好的推荐。我们不想建立一个推荐低评级内容的系统,对吗?至少大多数情况下不会:)
使用 CS 和评级贡献生成最终得分
首先,我们将省略评级数量。我们仍然会计算余弦相似度,但现在除此之外,我们还会对最终得分进行评分。我们将创建一个新的方法来确定评分对最终得分的贡献。我们将有两个参数,Q 和 r。其中 r 代表评级,Q 代表重要性(最终分数计算的评级权重)。通过使用 Q 参数,我们将能够增加或减少评分值对最终得分生成的影响。
新函数将根据与给定 Q 参数成比例的评分是大于还是小于 5 来增加或减少余弦相似性的输出(假设平均评分小于 5 的城市不喜欢并且应该被劝阻,大于 5 的城市喜欢并且应该被鼓励推荐)。如前一章所述,评级范围在 0-10 之间,评级贡献输出范围在-Q 和+Q 之间。
例如:如果 Q 给定为 10,则最大评分值可以通过将 CS 分数的 10%加到 CS 分数上来产生最终推荐分数,对于最小评分,最终分数可以通过从 CS 分数中减去 CS 分数的 10%来产生。
我们将在方法中使用的公式将找出给定评级的准确输出(找到蓝线上的准确点)。对于 Q = 10,这种评级贡献生成器方法的直观表示如下图所示:
Rating Contribution computer function for Q = 10
让我们创建一个名为 rating_extractor.py 的新文件,并添加以下代码
from math import eclass RatingExtractor:
def __init__(self):
print("initialized")#Returns value between -q and q. for rating input between 0 and 10.
#Parameters:
#rating: indicates the rating for the destination
#q: indicates the percentage of rating for general score. (default is 10.)
[@staticmethod](http://twitter.com/staticmethod)
def get_rating_weight(rating, q=10):
if rating > 10 or rating < 0:
return None
else:
m = (2*q) / 10 #10 because rating varies between 0 and 10
b = -q
return (m*rating) + b
get_rating_weight()方法进行一些计算,以确定给定等级和 Q 参数的贡献输出,然后返回值。如前所述,也如上图所示,这种方法可以产生负值和正值。意义;这种方法将对最终分数的计算产生积极或消极的影响。(请注意 Q 参数的默认值设置为 10)。
一种新方法在推荐引擎中的实现
现在,我们将添加一个新的方法来推荐一个使用余弦相似性分数和评级贡献来计算最终分数的工程类。在 RecommenderEngine 类中添加下面的方法。(我已经在 init 后面添加了)。
def calculate_final_score(cs, r):
amount = (cs / 100) * r return cs + amount
方法的工作方式如下:
- 接受 CS 分数和评级贡献 r 参数。
- 计算金额变量中 CS 分数的±r 百分比
- 将金额加到 CS 分数上并返回。
由于金额可以是正数,也可以是负数,最终得分将根据贡献值增加或减少。
值得一提的是,这种方法对 CS 分数有很大的偏见。因为它的操作是取 CS 的 r 个百分比,并将其加回原始 CS 值。CS 值较高的城市将受到这一新的最终得分计算的极大影响,特别是如果为 get_rating_weight() 方法提供较高的 Q 值。
现在让我们添加另一个方法到 RecommenderEngine 来使用这个新方法进行评分计算(我们将保留旧的推荐方法)。
New method for recommender_engine in Version-2
get _ re commendations _ include _ rating(keywords)方法的工作方式与第一章中实现的 get_recommendations(keywords)方法类似。但现在它将使用 CS 得分和评分贡献值计算最终得分,让我们来看看该方法是如何工作的:
- 接受 keywords 参数,并对数据集中的每个城市执行以下操作
- 计算 cs 分数
- 计算 Q=10 的评分贡献分数
- 通过使用 calculate_final_score 方法中的两个分数来计算最终分数
- 获得最终得分最高的前 5 个城市,并以 JSON 的形式返回
请求
现在我们有了方法,我们可以请求获得推荐。首先,让我们打开 request.py 文件,并添加一个从 RecommenderEngine 类中检索建议的方法:
def get_recommendations_include_rating(keywords):
return RecommenderEngine.get_recommendations_include_rating(keywords)
现在让我们添加新的请求,用新的方法获得 3 个类别的推荐。
# Version 2 requests are below:top_5_cultural_with_rating = get_recommendations_include_rating(culture_keywords)
city_names_for_cultural_rating = get_top_5_city_names_out_of_json(top_5_cultural_with_rating)
print(city_names_for_cultural_rating)
print("#################")
top_5_summer_with_rating = get_recommendations_include_rating(beach_n_sun_keywords)
city_names_for_summer_rating = get_top_5_city_names_out_of_json(top_5_summer_with_rating)
print(city_names_for_summer_rating)
print("#################")
top_5_party_with_rating = get_recommendations_include_rating(nightlife_keywords)
city_names_for_party_rating = get_top_5_city_names_out_of_json(top_5_party_with_rating)
print(city_names_for_party_rating)
print("#################")
上面的代码将获取带有最终分数的推荐,您可以运行它并查看您得到的结果。
在本文中,我们将只从文化、艺术和历史这两个不同的角度来考察结果。首先,我们将比较在第一个版本中实现的唯一 CS 评分方法和我们刚刚实现的新方法得到的结果。
get_recommendations 和 get _ re commendations _ include _ rating 方法的比较:
下面的代码是出于实验目的,所以它们不再包含在 request.py 中,因为这两个请求已经存在。
top_5_cultural_cities = get_recommendations(culture_keywords)
city_names_for_cultural = get_top_5_city_names_out_of_json(top_5_cultural_cities)
print(city_names_for_cultural)
print("#################")top_5_cultural_with_rating = get_recommendations_include_rating(culture_keywords)
city_names_for_cultural_rating = get_top_5_city_names_out_of_json(top_5_cultural_with_rating)
print(city_names_for_cultural_rating)
print("#################")
这里我们观察两种不同方法的输出:
[('Athens', 0.21629522817435007),
('St. Petersburg', 0.16666666666666666),
('Stockholm', 0.14962640041614492),
('Milan', 0.140028008402801),
('Rome', 0.12171612389003691)]#################[('Athens', 0.22927294186481106),
('Stockholm', 0.1556114564327907),
('St. Petersburg', 0.15333333333333332),
('Milan', 0.15123024907502508),
('Rome', 0.13145341380123987)]
在这里,我们有两种方法的不同得分,你可以看到,当评级考虑在内时,斯德哥尔摩上升到第二位,而圣彼得堡下降到第三位。让我们看看为什么:
正如您在我们的数据集中看到的,斯德哥尔摩的评分为 7,而圣彼得堡为 1。然后,如前所述,我们的算法降低了圣彼得堡的最终得分,并提高了斯德哥尔摩的最终得分,这导致斯德哥尔摩升至第二名。在这里,我们可以看到,使用实现的方法和公式,我们的推荐系统鼓励具有良好评级的内容,同时阻止具有不良评级的内容。您还可以观察其他城市排名的数据集,以了解为什么它们的最终得分与仅余弦相似性得分相比有所增加。
Q = 10 和 Q = 100 时 get _ recommendations _ include _ rating 方法的比较:
现在我们将使用不同的 Q 参数来比较我们的新方法。较低的 Q 表示对最终分数的评分贡献较小,而较高的 Q 表示贡献较大。正如我们之前打印出来的,以下是我们在 Q = 10 时得到的文化、艺术和历史类别的建议:
[('Athens', 0.22927294186481106),
('Stockholm', 0.1556114564327907),
('St. Petersburg', 0.15333333333333332),
('Milan', 0.15123024907502508),
('Rome', 0.13145341380123987)]
您可以转到 recommender_engine.py,将 10 替换为 100,以增加 get _ recommendations _ include _ rating 方法中的 Q 参数:
rating_contribution = RatingExtractor.get_rating_weight(rating,100)
现在让我们看看结果是如何变化的:
[('Athens', 0.3460723650789601),
('Milan', 0.2520504151250418),
('Rome', 0.21908902300206645),
('Stockholm', 0.2094769605826029),
('Venice', 0.17777777777777776)]
我们可以观察到我们现在的结果非常不同。
- 圣彼得堡已经不在前 5 名了,因为它的评分是 1,Q 值越高,这个城市就越不值得推荐
- 米兰和罗马分别升至第二和第三位,而斯德哥尔摩则跌至第四位,因为米兰和罗马的排名高于斯德哥尔摩。
Rating comparison for Stockholm, Rome and Milan
我建议你检查其他类别的结果,以及它们如何随着不同的 Q 值而变化。
版本 2 的结论
在版本 2 中,我们实现了一种方法,通过基于描述特征的余弦相似性得分和基于评级特征的评级贡献得分计算最终得分来推荐城市。因为在推荐系统中,我们经常想要向用户推荐好的内容,所以利用诸如评级之类的信息是很重要的。
你可以在这里访问所有为第二版编写的代码。
在下面的下一个版本中,我们将实现另一种方法,通过使用数据集中的评级计数功能来改进我们的推荐应用程序。
版本 3(评级阈值)
一个内容有好的评级,不代表评级就可靠。假设我们有两个内容 A 和 B,A 在 500,000 个用户中的平均评分为 4.7,而 B 仅在 10 个用户中的平均评分为 5。你想向你的朋友推荐哪一个?只有 10 个用户提供评级,你认为 B 有多可靠?在 rating_count 特性的帮助下,我们将提出一个阈值参数,这样我们的推荐系统将能够处理评级计数低的内容(在我们的例子中是城市),因为评级贡献并不太重要。
具有评级和计数功能的评级权重生成
在这个版本中,我们将开发几个新的方法来改进我们的推荐系统,以便它将有一个用于评级贡献计算的阈值。现在给大家介绍一个我写论文时想出来的公式:
Multiplier formula
该公式得出 M,它是一个乘数值,将与我们得到的评分贡献值相乘,然后用于最终推荐分数计算。这里 T 代表阈值,c 代表评级计数。该公式以具有以下属性的方式构建:
- 输出的范围在 0.0 和 1.0 之间
- 如果 T 和 c 参数相等,则公式始终得出 0.5
这个公式中的数字 e 没有什么特别的,它可以是任何数字(那么 0,68 也必须改变)。我只是用 e 让它看起来很酷:P
因此,该方法的主要重要性在于,当 T = c 时,它产生 0.50,这就是阈值处理的工作方式。我们将为评级计数设置一个阈值 T,这样,如果评级计数小于阈值,输出将在 0.0–0.50 的范围内(取决于有多低。)并且如果评级计数大于阈值,则输出将在 0.50 和 1.0 之间,但是永远不会超过 1.0。
如前所述,该乘数将仅应用于评级贡献值,因此我们不会太在意没有提供大量评级的评级,并且输出将降低评级贡献。因此,推荐将主要落入 CS 分数。但是,如果一个地方有更多的评级,那么评级贡献值也将会很高,最终的总体推荐分数也会更高。
现在让我们转到 rating_extractor.py 文件并创建一个新方法。我们只是将评分贡献值乘以乘数,但让我们创建一个新的方法,这样您仍可以有其他方法并按原样使用它。
首先我们需要从 math 中导入 e:
from math import e
然后在 RatingExtractor 类中,添加新方法:
[@staticmethod](http://twitter.com/staticmethod)
def get_rating_weight_with_quantity(rating, c, T, q=10):
if rating > 10 or rating < 0:
return None
else:
m = (2*q) / 10 #10 because rating varies between 0 and 10
b = -q
val = (m*rating) + b M = e**((-T*0.68)/c) return val * M
方法的工作原理如下:
- 它需要 rating、c (rating_count)、T (threshold)和 q 参数。
- 从上一章我们已经知道了评级和 q 参数。
- c 指用户提供评级的数量
- t 指的是上面介绍的阈值
- 计算评分贡献值
- 计算乘数 M 值
- 通过将贡献值乘以 M 返回评级权重
一种新方法在推荐引擎中的实现
让我们打开 recommender_engine.py,为 RecommenderEngine 类添加一个新方法(我们将保留我们在以前版本中实现的方法),它实际上与我们在前一章中添加到 RecommenderEngine 的方法几乎完全相同,但这次我们将传递评级计数和阈值以及城市描述和评级功能:
get_recommendations_include_rating_threshold method
该方法的工作原理如下:
- 接受 keywords 参数,并对数据集中的每个城市执行以下操作
- 计算 CS 分数
- 通过将城市评级、评级计数、阈值作为 100 万(数据集中的城市的评级计数在 100k 到 5M 之间,我最初选择了 100 万,但我们将对此进行调整)和 Q=10 来获取评级贡献权重
- 通过使用 CS 分数和评级权重,使用 calculate_final_score 方法(在上一章中实施)计算最终分数。
- 获得最终得分最高的前 5 个城市,并以 JSON 的形式返回
请求
我们将向 request.py 文件中添加新的请求,以便使用新方法获得 3 个类别的建议
首先,让我们添加一个方法来从 RecommenderEngine 类中检索具有新实现的建议:
def get_recommendations_include_rating_count_threshold(keywords):
return RecommenderEngine.get_recommendations_include_rating_count_threshold(keywords)
现在让我们添加新的请求,用新的方法获得 3 个类别的推荐。
# Version 3 requests are below:top_5_cultural_with_rating_count_threshold = get_recommendations_include_rating_count_threshold(culture_keywords)
city_names_for_cultural_rating_count_threshold = get_top_5_city_names_out_of_json(top_5_cultural_with_rating_count_threshold)
print(city_names_for_cultural_rating_count_threshold)
print("#################")top_5_summer_with_rating_count_threshold = get_recommendations_include_rating_count_threshold(beach_n_sun_keywords)
city_names_for_summer_rating_count_threshold = get_top_5_city_names_out_of_json(top_5_summer_with_rating_count_threshold)
print(city_names_for_summer_rating_count_threshold)
print("#################")top_5_party_with_rating_count_threshold = get_recommendations_include_rating_count_threshold(nightlife_keywords)
city_names_for_party_rating_count_threshold = get_top_5_city_names_out_of_json(top_5_party_with_rating_count_threshold)
print(city_names_for_party_rating_count_threshold)
print("#################")
上面的代码将获取推荐以及它们的最终分数,你可以运行它并查看你得到的所有类别的结果。但我们将只调查文化、艺术和历史类别的结果。
不同阈值的结果比较
让我们对文化、艺术和历史类别提出不同阈值(T)的实验请求。您可以在 RecommenderEngine 类的 get _ recommendations _ include _ rating _ count _ threshold 方法中更改 threshold。同样,这次我们将 Q 参数(前一章中介绍的评级贡献重要性参数)更改为 100,这样我们可以更好地看到阈值效果。
阈值= 100.000 的结果:
[('Athens', 0.33318171469723395),
('Milan', 0.24587898720843948),
('Rome', 0.21192640793273687),
('Stockholm', 0.18358642633975064),
('Venice', 0.17262307588744202)]
阈值= 1.000.000 的结果:
[('Athens', 0.26188415260156817),
('Milan', 0.2035910531885378),
('Rome', 0.16707033294390228),
('Stockholm', 0.14983344608755947),
('Barcelona', 0.14757848986361075)]
阈值= 2.500.000 的结果:
[('Athens', 0.2257870828894539),
('Milan', 0.16719580286435054),
('St. Petersburg', 0.158824470447676),
('Stockholm', 0.14962644254339),
('Rome', 0.13613352041126298)]
如你所见,阈值为 100K 和 1M;第 5 名就不一样了,门槛值低一点的时候我们有威尼斯在第 5 名,值高一点的时候我们有巴塞罗那。让我们看看为什么:
Rating and Rating count for Barcelona and Venice
他们都有 8 分,但巴塞罗那有 120 万分,而威尼斯有 845.000 分,威尼斯的 CS 分数也比巴塞罗那高。因此,当阈值为 100.000 时,两个城市都可以提供良好的评级贡献,因为威尼斯的 CS 得分较高,所以我们看到它位于第 5 位。
但是当阈值为 1.000.000 时,贡献分数如下(Q=100):
- 巴塞罗那:34
- 威尼斯:26.8
由于巴塞罗那现在具有更高的输出,并且由于 Q 也很高,巴塞罗那的最终得分计算将大于威尼斯,因此巴塞罗那位于第 5 位。
当阈值为 2.500.000 时,您可以看到圣彼得堡排名第三,而当阈值更低时,我们甚至没有排名第四或第五的圣彼得堡。我会把调查工作交给你。查看圣彼得堡的数据集,了解我们的实现是如何工作的,看看您是否能理解为什么我们让圣彼得堡拥有更高的阈值。如果你对评论有任何问题,请告诉我:)
此外,我鼓励你尝试所有这些参数,检查数据集的特征(应该没问题,因为我们只有 25 个城市),并尝试理解这些方法如何对推荐系统有效。
版本 3 的结论
在第 3 版中,我们实现了一种推荐城市的方法,首先计算余弦相似性得分,然后使用评级和评级计数功能计算评级权重输出,最后使用两种结果计算最终得分。使用可靠的信息是很重要的,因此通过这些实现,我们已经看到了如何改进我们的推荐系统,以便它可以更多地依赖于具有更高(高度取决于应用的上下文)反馈的内容。
你可以在这里访问所有为第三版编写的代码。
在下面的下一个版本中,我们将通过研究如何利用不同形式的反馈来进一步改进我们的推荐系统。
版本 4
在这个版本中,我们将通过使用数据集的正面 _ 评论和负面 _ 评论特征来进一步改进我们的系统。
这一章将比前几章更多地关注该方法的理论和实验结果(这里不是动手执行,而是在结果表上),所以如果你只是对代码实现感兴趣,你可以直接进入 实现 部分。
有时,我们可能会有不同类型的内容反馈。例如评论和评级。正如您所猜测的,它们并不是完全相同的反馈类型,评级反馈是以给定的尺度提供的(对于我们的情况是 0-10),而评估通常以文本格式给出。假设我们已经将评论分为正面和负面反馈(也许我们可以调查另一篇文章的评论分类),那么评论反馈可以被分析为二元反馈(0 或 1);意义,负面或正面评论。
我们的数据集中已经有两个可用的特征正面 _ 评论和负面 _ 评论。这些特征代表了一个城市收到的正面和负面评论的数量。
推荐系统的挑战之一是以不同的形式整合反馈。有许多不同的方法可以做到这一点,在这一章中,我们将尝试使用两种反馈形式,通过一种定制的方法将评论转换为评分形式。
将评论转换为评级标准
这样做的基本方法是为负面和正面反馈选择两个评分值,然后将每个评审反馈视为一个评分,并重新计算项目的平均评分。但是这种方法并不理想。例如,如果对于负面和正面评论,评级被选择为 0 和 10,则评论的效果将大于实际评级数据,尤其是当项目的评级接近 0 或 10 时。可以选择不同的评级值来减轻评论对评级的影响。例如,如果评级被选择为 2.5 和 7.5,那么将会出现另一个问题,其中对于平均评级大于 7.5 的项目的正面反馈仍然会有助于降低评级,而对于平均评级小于 2.5 的项目的负面反馈将有助于提高评级。因此,需要另一种方法来更好地结合这两种形式。
对于正面和负面的评价,我们的方法将相应地表现如下:
- 对于任何正面评价,通过计算项目的平均评分和最大评分值之间的距离(在我们的例子中为 10),然后将计算的距离的一半添加到平均评分,以确定评价值,从而将新的评分值添加到评分中。
- 对于任何负面评价,通过计算项目的平均评分和最低评分值(在我们的例子中为 0)之间的距离,然后从平均评分中减去计算的距离的一半来确定评价值,从而将新的评分值添加到评分中。
下面给出了将正面和负面评论分别转换为平均评级为 r 的给定项目的评级值 Rp 和 Rn 的公式:
Rating value conversion for a positive review
Rating value conversion for a negative review
例如,对于平均评分为 6(范围 0-10)的项目,对于每个负面评价,值为 3 的新评分将被添加到评分中,而对于每个正面评价,值为 8 的新评分将被添加到评分中。然后,在反馈到评分功能之前,使用新评级再次计算平均评级。对于不同的评级、评级计数和审核计数,审核反馈转换为评级反馈的结果如下表所示。
Rating calculation results with average rating and reviews
最终评级结果表明,在当前实施情况下,当评级值接近最大值或最小值时,计算出的评级倾向于支持相反的评级值。例如,对于评级为 7.2 且正面和负面评论计数相等的情况,结果为 6.65,因为它从原始值越来越接近最低评级。这是因为,0 和 7,2 之间的距离大于 7,2 和 10 之间的距离,当原始评级为 2,8 且正负评级值相等时,也观察到类似的行为。此外,评论的影响是最小的,因为测试案例比商业推荐系统通常情况下的评论包括更多的评级值。可以通过引入一个额外的参数来改变评论的重要性,以使这种方法更有效(例如,对于每个评论,我们可以用计算的值生成 10 个评级值),从而增加效果。
履行
现在我们已经研究了它的工作方式和它可以生成的结果,让我们继续在 RatingExtractor 类中实现一个新方法:
[@staticmethod](http://twitter.com/staticmethod)
def get_rating_with_count_and_reviews(r, rc, pf, bf):
if r > 10 or r < 0:
return None
else:
positive_diff = (10 - r) / 2
positive_rating = r + positive_diff negative_diff = r / 2
negative_rating = r - negative_diff updated_rating = ((r * rc) + (pf * positive_rating) + (bf * negative_rating)) / (rc + pf + bf)return RatingExtractor.get_rating_weight_with_quantity(updated_rating,rc,1000000,10)
方法的工作方式如下:
- 采用 r(评分)、rc(评分计数)、pf(正面评论计数)和 bf(负面评论计数)参数
- 计算正面评价的换算评分值
- 计算负面评价的换算评分值
- 然后用每个正面和负面反馈的旧平均评分和新评分值计算更新后的平均评分
- 然后使用更新的平均评级、评级计数、T = 1.000.000(阈值)和 Q=100(评级重要性参数)调用在先前版本中实现的方法,并将结果作为评级贡献返回
一种新方法在推荐引擎中的实现
让我们打开 recommender_engine.py,添加一个新方法来推荐 engine 类。这将与我们在前面章节中实施的方法类似,但这次我们将通过正面评价和负面评价计数以及描述、评级、评级计数、阈值:
get_recommendations_include_rating_count_threshold_positive_negative_reviews method
该方法的工作原理如下:
- 接受 keywords 参数,并对数据集中的每个城市执行以下操作
- 计算 CS 分数
- 通过传递城市评分、评分计数、正面评价计数和负面评价计数来获取评分贡献权重。这次(T 和 Q 参数直接从 RatingExtractor 类中的 new 方法传递。
- 通过使用 CS 分数和评级权重,使用 calculate_final_score 方法(在前面章节中实现)计算最终分数。
- 获得最终得分最高的前 5 个城市,并以 JSON 的形式返回
请求
我们将向 request.py 文件中添加新的请求,以便使用新方法获得 3 个类别的建议
首先,让我们添加一个方法来从 RecommenderEngine 类中检索具有新实现的建议:
def get_recommendations_include_rating_count_threshold_positive_negative_reviews(keywords):
return RecommenderEngine.get_recommendations_include_rating_count_threshold_positive_negative_reviews(keywords)
现在让我们添加新的请求,用新的方法获得 3 个类别的推荐。
# Version 4 requests are below:top_5_cultural_with_rating_count_threshold_reviews = get_recommendations_include_rating_count_threshold_positive_negative_reviews(culture_keywords)
city_names_for_cultural_rating_count_threshold_reviews = get_top_5_city_names_out_of_json(top_5_cultural_with_rating_count_threshold_reviews)
print(city_names_for_cultural_rating_count_threshold_reviews)
print("#################")top_5_summer_with_rating_count_threshold_reviews = get_recommendations_include_rating_count_threshold_positive_negative_reviews(beach_n_sun_keywords)
city_names_for_summer_rating_count_threshold_reviews = get_top_5_city_names_out_of_json(top_5_summer_with_rating_count_threshold_reviews)
print(city_names_for_summer_rating_count_threshold_reviews)
print("#################")top_5_party_with_rating_count_threshold_reviews = get_recommendations_include_rating_count_threshold_positive_negative_reviews(nightlife_keywords)
city_names_for_party_rating_count_threshold_reviews = get_top_5_city_names_out_of_json(top_5_party_with_rating_count_threshold_reviews)
print(city_names_for_party_rating_count_threshold_reviews)
print("#################")
上面的代码将获取推荐以及它们的最终分数,你可以运行它并查看你得到的所有类别的结果。我将省略最后一章的结果调查,因为这些实现的影响在本文开始时已经讨论过了。我会把文化、艺术和历史的结果留给你们:
[('Athens', 0.2622560540924768),
('Milan', 0.2040068651858985),
('Rome', 0.16752794267650856),
('Stockholm', 0.14984473241175314),
('Barcelona', 0.14831614523091158)]
但我强烈建议您调查所有类别的结果,转到第 3 章并在这里比较结果,有什么不同,为什么?检查数据集以找到答案,如果您有任何问题,请告诉我:)
结论
在这个版本中,我们实现了一种方法,将不同形式的反馈整合到推荐系统中。我们的方法是用一些定制的技术将评审反馈转换成评级反馈。
通过这一章,我们已经结束了推荐系统的实现。总的来说,我们已经实现了一个系统,在我们对用户几乎一无所知的情况下提出建议,只让他们选择一个类别(冷启动问题),并在每章的基础上采用迭代方法。我希望你喜欢这篇文章,如果你有任何问题,请告诉我。此外,由于所有这些实现都是我自己的想法(自定义函数,公式和技术),它们当然不是完美的,正如我们所看到的,有一些权衡。因此,如果您能在评论中告诉我如何改进,我会很高兴:)
你可以在这里下载项目的最终版本。
干杯!
额外的
您可能想知道为什么数据集中没有使用某些要素。正如我前面提到的,这些实现来自我的 MSc 项目,当我通过 Flutter 为移动设备开发 UI 时,我使用了其中的一些特性。您可以在下面看到应用程序的截图:
Images from the application
请让我知道你是否有兴趣通过 Flutter 为这里实现的推荐系统建立一个 UI。也许我也可以发布构建应用程序的帖子:)
保重!
Python 中的推荐系统第一部分(准备和分析)
就像我几天前做的 Kickstart 活动分析项目一样,今天我将分析电影评级。如果你错过了上一篇文章,这里有它的链接:
让我们探讨一下 Kickstarter 活动的一些注意事项
towardsdatascience.com](/analyzing-380k-kickstarter-campaigns-10649bbf4e91)
推荐系统是大多数较大的(和较小的)网上商店、像【网飞】这样的电影/电视节目网站以及许多其他网站的核心。根据维基百科,这是“官方”的定义:
推荐系统是信息过滤系统的一个子类,它试图预测用户对一个项目的“评分”或“偏好”。它们主要用于商业应用。[1]
存在两种主要类型的推荐系统:
- 协作过滤(Collaborative Filtering)——基于这样的假设:过去同意的人将来也会同意,并且他们会像过去一样喜欢相似种类的项目
- 基于内容的 —基于项目的描述和用户偏好的配置文件。他们将推荐视为特定于用户的分类问题,并根据产品特征学习用户喜欢和不喜欢的分类器。
当然,这两者之间存在一些派生,但目前这已经足够了。让我们把重点放在这篇文章要讲的内容上。
为什么要看这篇文章?
有两个主要好处:
- 你将深入到推荐系统的世界中——有很多有趣的事情要做,也是添加到简历中的一件好事
- 您将经历另一个探索性的数据分析过程,进一步提高您在该领域的技能
听起来像是对你有益的事情? 好,我们开始吧。
这篇文章的结构是怎样的?
这是我将要写的关于推荐系统的两篇文章中的第一篇。它涵盖了数据收集、探索性数据分析和数据可视化的过程。虽然这篇文章不会完全涵盖创建推荐系统的过程,但是每个数据科学项目都必须首先熟悉数据本身。
如果你想知道,本系列的第二篇文章将介绍如何用 Python 从头开始构建推荐系统,所以那篇文章将是本系列的核心,而这篇文章将会让你感到温暖。
帖子内容如下:
- 数据收集和导入
- 基础数据准备
- 探索电影发行年份
- 评级探索
- 电影类型探索
- 按流派计算评分
- 可视化评级数量
- 结论
是的,我知道你在想什么,我也知道有很多事情要谈。但我会尽量简短,尽可能切题。
数据收集和导入
数据集可以在官方 GroupLens 网站上找到。所以去那里选一个你喜欢的吧。它们分为几种尺寸:
由于较大的内存问题,我下载了第一个。如果你的电脑比我的更强(I5–8300h,8GB 内存),请随意下载任何更大的。但是话说回来,如果你不想等待计算完成太久,下载 100K 数据集,结果一般不会有太大变化。
好了,数据集下载了吗? 我们用 Python 导入吧。这里是您需要的所有库,以及 CSV 读取和合并过程:
Imports — https://gist.github.com/dradecic/61ceda3fcf0c2619f2b62774f88439e7
完成后,数据集将如下所示:
基础数据准备
我必须向你承认,我在整个数据清理过程中撒了谎。这个数据集不会有,因为它已经尽可能干净了:
一个价值都没有丢失,这种情况很少见。上帝保佑教育数据集!
从数据集标题可以推断,有 100K 个条目。但是电影有多少?
在 10K 周围。很好,实际上,我认为这将足以对电影市场得出一些一般性的结论。
探索电影发行年份
这一步需要做一些准备。我们的目标是分析电影发行年份的分布,但是这些信息还没有以预期的形式出现。
出版年份在标题栏中,在标题的末尾用括号括起来。然而,对于一些电影来说,情况并非如此,这使得提取过程有点困难。所以,逻辑如下:
- 如果存在出版年份,请删除括号并保留年份的整数表示
- 否则,将 9999 作为年份,这是缺少年份的明显标志
该代码块实现了所描述的逻辑:
Years — https://gist.github.com/dradecic/d3224dfd866d8444fd03cc3cfd4cb526
事实证明,只有 30 个实例没有年份信息,这并不可怕(因为我们有 100K 行)。现在让我们绘制一个这些年(不包括 9999 年)的柱状图。代码如下:
Histogram — https://gist.github.com/dradecic/f6c28a9cb3f0f04b74c2bccf35b811a5
一旦这个单元的代码被执行,下面是结果图表:
看起来,大多数电影都是在 1995 年到 2005 年之间上映的。
评级探索
此处可以使用来自 make_histogram 函数的逻辑,无需任何其他准备或数据操作,即可绘制电影评级的直方图。只要确保将 评级 作为属性传递,而不是 电影年份 。
看起来平均评分会在 3.5 左右,而且看起来用户更倾向于给满分而不是 0.5。
电影类型探索
与出版年份一样,需要做一些准备。看看流派栏是什么样子的:
没有办法像现在这样分析它。我想完成以下任务:
- 拆分竖线(|)字符上的字符串
- 为每个流派创建一个新条目
所以,1 行冒险|动画|儿童|喜剧|奇幻应该变成 5 行,其他信息保持不变。熊猫提供了一个很好的方式来实现这一点:
Genres — https://gist.github.com/dradecic/179d68a33510f8f25291e27c0b86eca1
这样就创建了一个新的数据帧,前几行如下所示:
这 5 行现在代表原始数据集中的 1 行,所以,是的,这就是我的笔记本电脑在大型数据集上失败的地方— 它无法在内存中容纳 1 亿行。
类似地,我现在可以声明一个绘制条形图的函数:
Bar Chart — https://gist.github.com/dradecic/1f1d1519e55e3875942c927136161603
我知道为一张图表做了很多准备,但这是值得的:
大多数电影都属于 剧情类 或 喜剧类 类别——这里没什么稀奇的。
按流派计算评分
获得这些信息可能是这篇文章中最困难的任务。这主要是因为它涉及到一些准备工作,背后的逻辑可能不像前面那样直观。您需要:
- 计算每部电影在单个流派级别上的评级(流派字符串由| 分割)
- 将每种类型的分级列表添加到词典中
- 计算平均评分,作为字典中列表的平均值
听起来让人迷惑?
Rating by Genre — https://gist.github.com/dradecic/7a65cac23c59c8206417ec26a6411641
在这里,您可以轻松地按流派划分等级:
似乎黑色电影做得最好,但是,这种类型的电影数量最少。 恐怖 电影做得更糟,这是有道理的,有一吨只是可怕的恐怖。纪录片和战争电影往往比大多数电影都要好,这也是有道理的——每个人都喜欢一部好的二战电影,如果它以纪录片的形式呈现,我会给它打五星!
可视化评级数量
你已经完成了最后一部分,干得好!现在让我们深入了解一下评级可视化的数量。它也将涉及一些准备工作,但没有什么要求。您必须:
- 创建一个数据帧,将 movieId 列分组,并对实例进行计数
- 将其与原始数据集合并
- 重命名合并时出错的列
Num Ratings — https://gist.github.com/dradecic/ef33ad4c942c2d013def6ed0c4945bc8
在进入可视化之前,我们先来看看根据收视率排名的前 10 部电影:
Top 10 — https://gist.github.com/dradecic/a5a6a669de0d6b380cad745d57a231f0
我对结果相当满意。这些顶级的都是经典之作,值得拥有。
为什么按收视率数量而不是纯收视率排序?
啊,问得好。原因是,我想避免被评为 5 星的电影,但只有一个或几个用户。如果这些电影足够受欢迎,会有更多的用户对它们进行评级,那么它们就是不相关的。
你现在可以绘制一个直方图的 列和 列:
这是意料之中的。大多数电影没有很好的预算,总的来说,这导致了一部不太受欢迎的电影。如果电影不流行,大多数人不会看,因此,不会评价它。爱它或恨它,这就是它的工作方式。
最后,让我们用一个很好的评分与评分数量散点图来结束这一部分。代码如下:
Scatter Plot — https://gist.github.com/dradecic/874c6f56bc1d92d3de45f6c170a5837f
下面是我的图表的样子:
你可以在这里看到一个趋势——随着电影获得更多的评级,其平均评级往往会增加。如果你仔细想想,这也很有道理。如果越来越多的人在看一部特定的电影,它可能有很好的预算和很好的营销,这将意味着它是某种类型的大片,他们通常评价很高。
结论
这是一个很长的帖子,我知道。然而,它涵盖了探索性数据分析的每一个重要部分。现在你对数据本身更熟悉了,这意味着你在进一步的分析中不太可能犯一些愚蠢的错误。
下一篇文章将在几天后发布,在这篇文章中,你将创建你的第一个(可能是)推荐系统。它将被链接到这里,所以请把这篇文章放在你身边(这听起来很奇怪)。
[## Python 中的推荐系统——第二部分(基于内容的系统)
深入推荐系统的神奇世界,并自己构建一个(第 2 部分)
towardsdatascience.com](/recommender-system-in-python-part-2-content-based-system-693a0e4bb306)
你有什么想法?你的分析中还包括了其他内容吗?如果有,请在评论区分享。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
资源
[1]https://en.wikipedia.org/wiki/Recommender_system
Python 中的推荐系统——第二部分(基于内容的系统)
欢迎来到 2 部分系列的第二部分。这篇文章将着重于从以前探索过的电影数据集中开发一个简单的、基于内容的推荐系统。整个数据探索和分析已在第一部分完成,如果您错过了,请点击以下链接:
深入推荐系统的神奇世界,自己构建一个(第 1 部分)
towardsdatascience.com](/recommender-system-in-python-part-1-preparation-and-analysis-d6bb7939091e)
我不得不说,今天的帖子会比上一篇短得多。最主要的原因是,没有太多的推荐系统(在这个基础层面至少有)。话虽如此,今天的帖子将向您解释一个简单的基于内容的推荐系统背后的直觉和逻辑(如果您不知道什么是基于内容的系统,请参见第 1 部分),您将看到这里没有实际的机器学习,只有高级的(类似于)过滤。
你为什么要读这篇文章?
与前一篇文章一样,它有两个主要好处:
- 您将深入推荐系统的世界,并构建您的第一个(可能是)
- 你会发现它们比看起来要简单
这篇文章是如何组织的?
前面我说了,这一部分会比上一部分短很多,上一部分涵盖了数据收集、准备和探索的过程。阅读那篇文章是的先决条件,因为如果你不阅读它(或者至少复制其中的代码,你的数据将不会与我的数据格式相同,因此你将无法继续。
帖子内容如下:
- 矩阵创建
- 创建获取推荐的函数
- 获取和验证结果
在开始之前,数据集应该是这样的:
弄成这个形状?你可以继续了。
矩阵创建
对于矩阵,我的意思是您应该以某种方式创建具有以下内容的表:
- 每个用户 ID 作为一行
- 每个电影标题作为一个专栏
- 将每个用户对每部电影的评价定为行和列的交集
这很容易通过熊猫***pivot _ table()***函数获得:
Movie Matrix — https://gist.github.com/dradecic/339da863583482ef8fc67770e1a40bd7
这个矩阵本质上是一个熊猫 DataFrame 对象,通过知道你知道你可以调用 ***。*头()**在上面:
是啊,很多 男 ,我都知道。花一分钟思考为什么这么多的值丢失了,然后继续阅读。
你拿到了吗?
原因是,并不是每个人都看过每部电影并对其进行评级。这个表里面有 9700 多部电影,你自己想想吧。你看了多少部电影?在你看过的人中,你公开评价了多少?没那么多吧?
现在你有了矩阵,你可以进行下一步了。
创建获取推荐的函数
这是邮报的主要内容。如果这是你的第一个推荐系统,你会惊讶地发现做一个是多么容易,至少在初级水平上是这样。
下面是你必须实现的逻辑:
- 计算所需电影与其他电影的相关性(使用 ***)。*corrwith()**法)
- 将具有相关性的电影标题存储在单独的数据帧
- 将数据帧与原数据帧合并,删除重复数据,保留 标题 、 相关 系数、编号列
- 按相关性降序排序(从最大相关性到最小相关性
- 过滤掉收视率低的电影(那些电影是不相关的,因为它们只被少数人看过
- 返回 top n 相关电影
听起来工作量很大,但实际上只有 10 行代码。
The Function — https://gist.github.com/dradecic/322359d1bf36de305c55a8fc539fec75
如您所见,我已经设置了作为默认函数参数返回的过滤器数量和电影推荐数量,因此它们更容易调整。
简而言之,这就是你需要实现的全部逻辑。
容易吧?
获取和验证结果
获得推荐的过程现在就像函数调用一样简单。你需要传入的唯一参数是电影标题,并且它必须与数据集中存在的那个相同,每个小小的拼写错误都会破坏一切。请随意使用这个函数来解决这个问题。
如果我现在拿到低俗小说电影的推荐:
第一个显而易见,低俗小说与低俗小说完美关联,但看看之后的几个。
看看 IMDB 给了这部电影什么推荐。很酷,对吧?
Obtained from IMDB on 29th September 2019 — https://www.imdb.com/title/tt0110912/?ref_=tt_sims_tt
我现在可以对电影玩具总动员做同样的事情:
很明显这些建议是有效的,但是让我们确认一下以防万一:
Obtained from IMDB on 29th September 2019 — https://www.imdb.com/title/tt0114709/?ref_=nv_sr_3?ref_=nv_sr_3
《怪兽电力公司》和《海底总动员》是 IMDB 上的前 6 个推荐,而《超人总动员》在下一页。
结论
推荐系统做起来很有趣,也很容易验证(至少在这种情况下)。我希望在读完这篇文章后,你不会把它们看作是黑盒,因为它们基本上可以归结为用 Python ( 或你选择的语言)进行一些数据操作。
你考了哪些电影?你对结果满意吗?请让我知道。
使用贝叶斯个性化排序的推荐系统
用矩阵分解直观理解贝叶斯个性化排序优化准则
在这篇文章中,我将讨论贝叶斯个性化排序(BPR),这是推荐系统中使用的著名的学习排序算法之一。在深入 BPR 算法的细节之前,我将概述一下推荐系统是如何工作的,以及我的音乐推荐系统项目。这将有助于一些第一次阅读推荐系统的人,并作为其他人的复习资料。
内容:
- 概观
- 学习推荐系统
- 使用交替最小二乘法的矩阵分解
- 使用贝叶斯个性化排序的矩阵分解
1。概述
在网飞奖诞生的早期,大多数推荐系统都是基于显式数据(评分数据)的,用户明确地给出评分来表达他们的观点。从那以后,很多事情都变了。随着数据收集技术的增强和在客户中给出明确评级的趋势的减少,隐式反馈数据在学术界和工业界都变得更加流行,以构建健壮的推荐系统。
隐含数据
隐式数据就是我们从客户那里收集的反馈,包括点击量、购买量、浏览量等。隐式数据的主要特征是
- **无负面反馈:**在显性数据中,客户明确表达了他们的正面和负面反馈。其余没有值的数据点被视为缺失值。但在隐性数据中,我们只有正面反馈,如点击、购买等,没有办法判断缺失的数据是因为客户不喜欢该商品还是没有意识到这一点
- **固有噪声:**尽管隐式数据固有噪声,但其庞大的数据量弥补了这一缺陷,有助于构建健壮的推荐系统。
- **偏好与信心:**在显性数据中,评级专指客户的偏好,用数值表示偏好的大小。在隐含数据的情况下,数值通常指的是频率,它不一定反映客户偏好的大小。因此,需要推导出显示客户信心的信心度量
潜在因素模型
对于隐式数据,潜在因素模型提供了邻居模型(基于相似性度量的模型)的替代方法,有助于揭示用户和项目的潜在特征。这种模型的例子是矩阵分解、潜在语义模型、潜在狄利克雷分配等。其中,矩阵分解由于其吸引人的准确性和可扩展性而变得更加流行。
虽然一个简单的奇异值分解为此目的工作,但它遭受过拟合,这将我们带到下一组涉及正则化的模型。
2。学习推荐系统
学习推荐系统就是这样一种方法,其中矩阵分解可以转化为一个带有损失函数和约束的优化问题。在这种方法中,我们在优化过程中从一系列推荐器中选择最佳推荐器。这种方法的最终结果是一个潜在因素模型,它帮助我们使用参数估计方法来揭示用户和项目的潜在特征。
为了详细说明这一点,让我们看看学习推荐系统的结构
Figure 1
如上图所示,学习推荐系统有 3 个组成部分:
1。型号:
模型可以是矩阵分解模型或线性回归模型。它有一些参数,如矩阵分解中的矩阵,我们将在此过程中进行优化。在我们的例子中,模型和参数一起构成了推荐系统
2。效用函数或损失函数:
这就像我们在机器学习算法中的任何其他损失函数一样,将被最小化以达到最优解
Equation 1
θ:推荐模型的参数,如矩阵分解中的用户矩阵和项目矩阵。
g(θ):我们试图最小化的损失函数
3。优化算法:
我们可以选择任何符合我们目的的优化算法。对于隐式数据,最好的优化算法之一是交替最小二乘法
3.使用交替最小二乘法的矩阵分解
这些推荐系统的性能通常取决于所使用的优化算法。
你猜对了。下一部分是关于优化算法,我们越来越接近贝叶斯个性化排名。
交替最小二乘法
交替最小二乘法(ALS)就是这样一种算法,由胡一帆、耶胡达·科伦和克里斯·沃林斯基在针对隐式反馈的协作过滤中提出。如果你不知道这个算法,我强烈建议你阅读这篇由 Victor 撰写的文章,以详细了解 ALS。然而,为了保持贝叶斯个性化排序方法的逻辑连续性,我将简要概述 ALS 模型。
ALS 是一种算法,通过在特定迭代期间保持一个向量不变来迭代地优化用户和项目潜在向量。
在他们的论文中,胡一帆和其他人提出了这样一个概念:在执行一个动作时,把自信归因于用户的选择。他们制定了一个新的平方损失函数,其中包括偏好和信心指标,反过来将使用 ALS 方法进行优化。
损失函数:
Equation 2
徐和易分别是用户潜在向量和项目潜在向量。
**崔:**置信度度量
pui : 偏好指标
实施 ALS 创建音乐推荐系统
为了更好地理解使用 ALS 的推荐系统,我实现了这些概念来创建一个使用开源音乐数据集(lastfm 数据集)的音乐推荐系统。在构建这个音乐推荐系统时,我从 Ben Frederickson 和 Jesse Steinweg-Woods 的作品中获得了灵感和一些代码帮助。
您可以在我的 github 资源库中找到该项目的代码。
[## akhilesh-Reddy/基于隐含数据的推荐系统
基于用户所听歌曲的数量和类型的音乐推荐系统|实现了约 90%的 AUC
github.com](https://github.com/akhilesh-reddy/Implicit-data-based-recommendation-system)
结果
我使用 AUC 度量作为这个推荐系统的评估标准。值得注意的是,这个数据集非常稀疏,当我对 40000 名用户和 100000 名艺术家进行采样时,稀疏度为 99.9%。尽管数据集中有很大的稀疏性,推荐系统给出了大约 90%的 AUC 值。
尽管该算法在查找相似艺术家方面表现更好,但在向特定用户推荐艺术家方面,我并没有获得令人满意的结果。这就把我带到了这篇文章的最后一部分。
为什么要贝叶斯个性化排名?
尽管胡一帆的 ALS 方法使用置信度和偏好度量减少了缺失数据的影响,但它并不直接优化其用于排名的模型参数。相反,它优化预测一个项目是否被用户选中。贝叶斯个性化排名优化标准涉及成对的项目(两个项目的用户特定顺序),以便为每个用户提供更个性化的排名。
首先,很明显这种优化是在实例级(一项)而不是像 BPR 那样在对级(两项)。除此之外,它们的优化是最小二乘法,已知对应于正态分布随机变量的最大似然估计。然而,项目预测的任务实际上不是回归(定量),而是分类(定性),因此逻辑优化更合适。—
Steffen Rendle,Christoph Freudenthaler,Zeno Gantner 和 Lars Schmidt-Thieme 在 BPR:根据隐式反馈进行贝叶斯个性化排序
使用贝叶斯个性化排序的矩阵分解
个性化排序的主要任务是向用户提供排序后的项目列表。在下一节中,我总结了这种方法,尽量减少数学方程的数量,以方便第一次阅读的读者。关于数学的详细理解可以参考原文。
数据准备:
设 U 是所有用户的集合,I 是所有项目的集合。下图显示了在一般项目推荐者的情况下,隐式数据是如何处理的。
Figure 2
通常的方法是预测项目的个性化得分 xui,该得分反映了用户对该项目的偏好。之后,项目将根据该分数进行排名。如上图所示,用户和项目之间的所有现有交互被标记为正类(1),其余交互被标记为负类(0)。
这意味着,如果我们的模型与训练数据完全吻合,它将以同样的方式对待训练数据中不存在的所有相互作用,因为它们都被标记为 0。这种方法在将来的推荐中不一定考虑排名。
在 BPR 方法中,项目对将被视为训练数据,而不是取一个项目。将基于这些用户-项目对的排名来执行优化,而不是仅仅根据用户-项目交互来评分。将被考虑的数据集被公式化如下
Equation 3
(u,I,j) ∈ DS 的语义是假设用户 u 更喜欢 I 而不是 j。
Figure 3
这里,为训练数据生成的三元组是一对项目之间的用户特定的成对偏好。
在上图中,用户 u1 已经查看了项目 i2,但没有查看项目 i1,因此该算法假设该用户更喜欢项目 i2 而不是 i1( i2 > i1 ),并给出一个正号。无法推断用户对既已看到又显示为**的项目的偏好。**马克。对于用户还没有看到的两个项目也是如此(例如,用户 u1 的项目 i1 和 i4)。相反,您可以观察到(i1,j2)的负号,因为用户更喜欢 item2 而不是 item1。
业务流程重组选项
像在任何贝叶斯方法,我们有一个似然函数,先验概率和后验概率。
为所有项目 i ∈ I 找到正确的个性化排序的贝叶斯公式是最大化以下后验概率,其中θ表示任意模型类的参数向量(例如,矩阵分解)。
似然函数
Equation 4
这里,> u 是用户 u 的期望但潜在的偏好结构。同样重要的是要注意,p( >u | θ)是用户特定的似然函数。
假设用户将独立行动,并且特定用户的每对项目(I,j)的排序独立于每对其他项目的排序,我们可以将用户更喜欢项目 I 而不是项目 j 的个体概率公式化如下:
Equation 5
上述等式中的 x^uij(θ)是表示用户 u、项目 I 和项目 j 之间的关系的实值函数,并且通常通过使用矩阵分解模型来计算。换句话说,捕捉用户 u、项目 I 和项目 j 之间的关系的分数将使用三元组训练数据和矩阵分解来计算,并且被包装在 sigmoid 函数中。该 sigmoid 函数给出了在该过程中将被优化的个体概率。
先验概率
p(θ)是先验概率,它是具有零均值和方差-协方差矩阵的正态分布
Equation 6
BPR 标准
以下等式是最终的 BPR-OPT 标准,必须进行优化
Equation 7
其中λθ是模型特定的正则化参数
为什么要记录可能性?
现在我们有了概率函数,评估它的一个常用方法是对数似然函数。
使用对数函数的原因是数值稳定性。事实证明,对于非常大的数据集,我们有可能获得非常低的概率,而系统很难记录这些概率。通过取概率的对数,我们得到一个总和,而不是每个点的概率的乘积,这将有效地存储在计算机存储器中。
类比 AUC 优化
对于不了解 AUC 的人来说,它是 ROC 曲线下的面积,该曲线以真阳性率作为 y 轴,假阳性率作为 x 轴,用于所考虑的模型的各种阈值。换句话说,对于一组项目推荐,我们可以通过计算每个阈值的好项目推荐百分比和坏项目推荐百分比来绘制 ROC 曲线。
有趣的是,AUC 指标是一个基于排名的指标,也可以被视为正确排名点的百分比。
从数学上来说,分类器的 AUC 等于该分类器将随机选择的正例排序高于随机选择的负例的概率。
为我们的用例实现 AUC 定义为我们提供了以下等式:
Equation 8
s(I;u)> S(j;u)是我们之前讨论过的 x^uij 分数。
函数 1{foo}是一个不可微的 Heaviside 函数。优化 AUC(基于秩的度量)的一般做法是用类似 sigmoid 函数的可微分函数代替 Heaviside 函数。在我们的例子中,我们选择了对数(sigmoid)。这个概念总结在下面的 论文 。
Heaviside function
Figure 4
AUC 与 BPR-OPT 的比较
Equation 10
针对 BPR-OPT 标准的优化将类似于针对 AUC 的优化,AUC 是一种基于排名的指标,我们可以从上面的等式中看出。
使用自举的梯度下降
在这种情况下,当标准是可微的时,明显的选择是在优化标准上使用梯度下降。但在这种情况下,模型遍历训练对的顺序至关重要。遵循一般的随机梯度方法将导致较差的收敛性,因为在相同的用户-项目对上有如此多的连续更新,即对于一个用户-项目对(u,I),有许多具有(u,I,j) ∈ DS 的 j。
为了解决这个问题,在该算法中采用了自举方法。不是以连续的顺序获取数据点,即对于特定用户的所有项目(I)和项目(j ),而是随机获取数据点导致更快的收敛。BPR 方法的作者已经从经验上证实了这一点。
通过使用梯度下降优化 BPR-OPT 标准计算 xuij
这篇文章的最后一步是了解矩阵分解模型如何计算 x^uij 分数。矩阵分解通常试图模拟用户对某个项目的隐藏偏好。它是每个用户项目对(u,I)的实数 x^ui。
由于我们的数据中有三个一组,估计量 x^uij 将分解如下:
Equation 11
我们可以使用任何标准的协同过滤模型代替矩阵分解来预测 x^ui 和 x^uj.BPR-OPT 标准是对任务进行排序的最佳标准,因为我们正在对两个预测的差异进行分类(x^ui -x^uj).
Ben Frederickson 的隐式打包有一个用于 BPR 的模块,对于任何数据集都很容易实现。您可能想看看如何用 python 为您的推荐系统实现这种方法。
这是所有的乡亲。我希望你现在对贝叶斯个性化排序方法有了很好的理解。我将把这作为我的音乐推荐系统的下一步来实现,并检查它在我的推荐排名方面的表现。
请继续关注未来几周关于数据科学和数据可视化统计的更多帖子!
参考
[1]http://citeseerx.ist.psu.edu/viewdoc/download?doi = 10 . 1 . 1 . 2 . 3727&rep = rep 1&type = pdf
[2]https://www . ka ggle . com/otmanesakhi/the-rank-statistic-differentiable-AUC-estimate
[3]http://www.benfrederickson.com/matrix-factorization/
[4]http://www . benfrederickson . com/fast-implicit-matrix-factorization/
[5]https://medium . com/radon-dev/als-implicit-collaborative-filtering-5ed 653 ba 39 Fe
https://arxiv.org/ftp/arxiv/papers/1205/1205.2618.pdf
推荐系统和超参数调整
机器学习中(经常)被遗忘的孩子
每一个有互联网连接的人都受到推荐系统(RS)的影响。
Spotify suggestions to
几乎所有的媒体服务都有一个特定的部分,系统会在那里向你推荐一些东西,比如网飞的一部电影、亚马逊的一件商品、Spotify 的一个播放列表、脸书的一个喜欢的页面等等。在我们日常使用的几乎所有服务中,我们都至少看过一次“你可能喜欢这个”部分;背后的算法是一个推荐系统。
有些人可能会认为简历是一个试图比你自己更了解你并给你所需要的东西的系统。如果你这么说的话,听起来有点(也许很多)令人毛骨悚然,但它的目标是通过了解你的喜欢和不喜欢,让你的体验变得尽可能好。
像机器学习(ML)的所有应用一样,RS 的前景是从大量数据中学习,然后对新的输入数据进行预测,其中 RS 中的预测可以被视为用户是否喜欢推荐项目的分类问题。尽管从数据存储方式(稀疏矩阵)到仅适用于 RS 的方法和模型都有明显的差异,但所有 ML 应用程序遵循的步骤都是相同的:
- 数据可视化
- 数据预处理
- 选择模型
- 培养
- 估价
- 超参数调谐 (HPT)
虽然前 5 步都很好,但我在论文中遇到的最后一步是:超参数调整。在 RS 中进行 HPT 的可能方法缺乏材料和实际的例子,通常什么是最好的等等,这是非常突出的,这是写这篇文章的灵感来源。
温柔推荐系统介绍
RS 算法的设置与任何其他 ML 应用程序相同,但有两个关键要素除外:
- 数据存储:在 RS 中,数据存储在稀疏矩阵中,更准确地说是存储在两个矩阵中, URM (用户评级矩阵)和 ICM (项目内容矩阵)。一个 URM,一个 UserxItem 矩阵,包含关于用户偏好的所有信息,也就是说,在一行中,我们有用户对服务提供的项目所做的评级(显式或隐式)。相反,ICM 是一个保存所有项目元数据的矩阵,其中每一行都包含一个项目的所有信息。
- 方法:可分为三种类型。
- 基于内容的:我们利用项目的特征(元数据)来寻找其他与之相似的项目,然后向用户推荐与用户已经感兴趣的项目相似的项目。用更实际的话来说:对于一个喜欢/看过/评价电影《大美人》的用户来说,你推荐像《青春》这样的电影,是因为他们有一些共同点,比如导演(保罗·索伦蒂诺)、相同的流派(戏剧、喜剧)、关键词等等。
- 协同过滤:利用了这样一个事实,即尽管人们可能不同,但在偏好方面存在模式,因此两个具有相似偏好的用户,我们向其中一个推荐其他人喜欢但该用户不知道的项目。
- 混血儿:前两者通过旧方式组合而成
一旦你准备好了数据,也就是矩阵,并选择了使用的方法,这就是矩阵乘法的问题了。
超参数调谐
我们在模型调整中所做的是塑造我们的模型,目标是在看不见的数据(测试集)中获得尽可能好的分数。在跳到 HPT 可以做的方式之前,首先我们需要知道什么是超参数(HP)。
在 ML 中,超参数是模型不会自己学习的参数,但我们必须在模型开始学习之前提供给模型,例如神经网络中隐藏单元的数量、随机森林中的树的数量、KNN 最近邻居的 K 个数量等*。*
关键是 HP 本身需要被学习:我们事先不知道一个神经网络中的 10 个隐藏单元是否是我们问题的最佳选择,或者 1000 个是否更好,随机森林中的 50 棵树是否会比 100 棵树产生更好的性能,等等。因此需要做 HPT。
HP 不要与参数混淆:虽然 HP 是由我们提供给模型的,但参数是在模型通常的黑盒中自动学习的。
通过快速搜索,您会发现 HPT 最基本、最常用的方法是:
- 手动:我们可以回到用两块石头生火的时候
- 网格搜索(GS) :稍微好一点了
- 随机搜索:你开始看到光明了
- 贝叶斯优化(BO) :现在我们来谈谈
对 HPT 方法的这种考虑背后的主要原因仅仅是由于一个事实:时间。为您的问题找到最佳惠普所花费的时间至关重要,尤其是在必须实时提供建议,并根据您在线插入的信息进行更新的领域。
为了证明所有这一切背后的争论,我举了一个相当简单的例子来证明这一点,面对其中的两种方法:
- GS :一个简单的强力方法
- BO :一种自动化的方法,已经被证明在许多问题上优于其他最先进的优化算法。
为了不进入太多的细节,该算法用于后的范围是不是,基本事实是这些:
数据集 : MovieLens 数据集,有 1000 万次交互
RS 方法 : KNN,一种基于内容的方法,对于每部电影,我们找到与其相似的 K 部电影(最近的邻居),其中相似度是余弦相似度
训练-测试:80%-20%的分割,训练集中约有 800 万次交互,测试集中约有 200 万次交互
验证集:为了使 HPT 成为可能,我们还需要一个验证集,我通过将训练集以 80-20%的比例进一步分为训练集和验证集来生成它,所以现在我们在训练集中有大约 740 万个交互,在验证集中有 1.6 个交互
Metric:MAP @ 5(Mean Average Precision)将推荐视为一项排名任务,目标是首先向用户推荐最有可能让用户喜欢的项目。5 代表评估推荐的前 5 个项目。MAP 的值从 0 到 1。贴图值越高越好。
调整的超参数:NN(最近邻)和收缩系数
网格搜索
GS 背后的想法是用你的超参数的可能值创建一个网格,然后开始测试这些可能值的组合。
Hyper-parameters’ set of values
在我们的例子中,可能的组合是 81,这意味着用每个参数组合训练和评估我们的算法 81 次。想象一下有两个以上的参数需要调整,想象一下组合的数量会增加,因此时间也会增加。是啊,这需要更多的时间。
NN variation impact on performance (on Validation set)
Shrinkage variation impact on performance (on Validation set)
好的:通过将一个参数固定在 GS 找到的最佳值,我们改变另一个参数,以可视化性能的变化。模型对超参数的敏感性显而易见,表明了这一步骤在创建 rs 过程中的重要性。
Running time of GS
不太好:这是尝试所有组合所花的时间!
不用说,我疯狂地寻找另一种方法来完成我的模型训练的最后一步,我的研究将我引向 BO。
贝叶斯优化方法
关于 GS,手动和随机搜索,下一组要评估的超参数是在不知情的情况下产生的。这就是业务对象方法的突出之处:它使用过去做出的选择,以便为要测试的下一组值做出明智的选择,从而以搜索下一个要以更智能的方式测试的参数为代价来减少评估的数量。
随着优化的进行,在 BO 中,我们的目标是找到有界集合 X 上的函数 f (x) 的最大值(或最小值),这转化为这个特定问题意味着所考虑的函数是这样一个函数,在综合中给定来自X(HP 的所有可能值的集合)的输入 X(HP 的配置),它返回用这样的 HP 生成的模型的性能。对于业务对象流程,函数 f 是未知的,它所做的是在它之前关联 a。先验的目的是表达关于被优化的函数的假设,并且随着评估的进行,形成后验分布。然后,后验分布本身被用于驱动下一个输入(HP)的获取函数以进行评估。这是一个连续的策略,因此随着迭代次数的增加,后验的质量也增加,这反过来意味着下一个要探索的区域的质量的确定性更高。
至于其他许多关于 ds 世界的方法,你可以把它作为一个黑盒来达到你的目标,或者你可以试着做一些解包,试着理解这样的优化是如何完成的。这种方法的完整解释可以在这里阅读,这是本文所用 BO 实现的基础。如果你想读些轻松的东西,这篇文章对我很有帮助。
本例中使用的 BO 的实现是这个 Python 库。
在实践中,为了给 HPT 做业务对象,您需要定义三个基本要素:
-
参数值的范围,所以函数的定义域:
-
要优化的函数,其中您可以适应您想要的任何指标,因此该方法很方便:
-
调用函数
BO 唯一棘手的方面是,它选择连续值进行试验,如果超参数是整数,您需要进行调整;没有什么简单的铸造不能解决的。定义这三个要素,你的工作就完成了。
达到相同结果的时间差你可能会想:
BO running time
使用 GS 找到的最佳参数组合:
使用 BO 找到的最佳参数组合:
NN | Shrinkage
这些参数略有变化,但不用担心。一个简单的测试可以消除任何疑问。
Performance with parameters found by BO
Performance with parameters found by GS
时间性能上的差异是显而易见的,几乎少了 10 倍,但这两种方法都达到了目标。这绝不是一个简单的例子,可以用来证明贝叶斯优化是解决所有推荐系统问题的方法,但有趣的是,RS 在使用 BO 时也不例外。毕竟,如果数据科学中有确定性的话,那就是没有确定性的方法会在你的数据集中起作用。
实践中的推荐系统
公司如何推荐产品
by @rocinante_11
亚马逊、网飞、Linkedin 和 Pandora 等公司利用推荐系统帮助用户发现新的相关项目(产品、视频、工作、音乐),创造令人愉快的用户体验,同时推动收入增长。
在这里,我们提供了一个实用的推荐系统概述。首先,回顾了三个主要的系统:基于内容的、协同过滤的和混合的,随后讨论了冷启动、可扩展性、可解释性和开发/探索。
基于内容的推荐
在潘多拉,一个音乐团队给每首音乐贴上了 400 多种属性的标签。然后当用户选择一个音乐电台时,匹配该电台属性的歌曲将被添加到播放列表中(音乐基因组计划|Pandora,Howe|Pandora)。
这是基于内容的推荐。用户或项目具有描述其特征的简档,并且如果两个简档匹配,系统将向用户推荐项目。Stitch Fix 的时尚盒子是另一个基于内容推荐的例子。收集用户的属性(身高、体重等。)和搭配的时尚产品放在一个盒子里交付给用户(Stitch Fix|2013)。
对于潘多拉来说,创造音乐属性需要人工的努力/成本,但也有很多情况下没有这样的需求。Stitch Fix 的客户提供他们自己的偏好,Linkedin 用户提供他们自己的工作经验和技能,亚马逊上的商家提供他们的产品信息,所有这些都可以免费用于基于内容的推荐。
匹配用户和项目的一种简单方法是关键字匹配。例如,对于工作推荐,可以将工作描述与求职者的简历进行匹配。术语频率-逆文档频率通常用于为对项目或用户唯一的关键字赋予更大的权重。
一种更系统的方法是建立一个监督模型,估计用户喜欢看不见的物品的倾向。在该模型中,特征是来自用户和项目的属性(例如,工作和求职者是否在同一行业的指示变量),响应变量是用户是否喜欢该项目(例如,求职者是否会申请该工作)。
基于内容的方法计算速度快且可解释。它们可以很容易地适应新的项目或新的用户。然而,项目/用户的一些特征可能不容易捕捉或明确描述。Stitch Fix 通过让机器学习处理结构化数据,让人类处理非结构化数据(例如,用户的 Pinterest board)来解决这一问题。
协同过滤
协同过滤系统基于历史用户对项目的偏好(点击、观看、购买、喜欢、评级等)来做出推荐。).偏好可以被呈现为用户项目矩阵。下面是一个描述 4 个用户对 5 个项目的偏好的矩阵示例,其中 p_{12}是用户 1 对项目 2 的偏好。
虽然条目可以是数字的,例如网飞的电影分级预测挑战(分级范围从 1 到 5),但是在大多数应用中,它们是二进制的(例如,点击、观看、购买)。
在现实中,用户-项目矩阵可能超过数百万*数百万(例如,亚马逊、Youtube),并且大多数条目是缺失的——推荐系统的目标是填充那些缺失的条目。
在这里,我们描述了三种协同过滤相关的方法,最近邻法,以及两种创建新的潜在空间的方法:矩阵分解和深度学习。
最近邻
基于最近邻的方法基于成对的项目或用户之间的相似性。余弦相似性常用于度量距离。
偏好矩阵可以表示为项目向量
项目 I1 和项目 I2 的相似度计算为 cos(I1,I2) 。该矩阵也可以表示为用户向量
U1 和 U2 的相似度计算为 cos(U1,U2) 。注意,偏好矩阵中缺失的值通常用零填充。
对于 user_i,我们可以推荐 user_i 最相似用户喜欢的物品(user-to-user)或者 user_i 最相似物品的物品(item-to-item)。
亚马逊(Amazon|2003)、Youtube (Youtube|2010)、Linkedin (Linkedin|2014)等在实践中普遍采用了项目对项目的方法。当客户喜欢一个项目时,项目到项目系统可以快速显示与之相似的项目(每个项目的相似项目都是预先计算好的,并保存在键值数据存储中)。此外,项目对项目的推荐比用户对用户的推荐更容易解释,例如,系统可以解释为什么推荐一个项目,因为“你喜欢 X ”。
有可能与一个项目相似的项目的数量太小(在对相似性分数应用阈值之后)。人们可以通过包括相似物品的相似物品来扩展相似物品列表(Youtube|2010)。
在获得最相似的项目后,后处理步骤会很有用。(Youtube|2010)根据视频质量(例如,通过评级来测量)、多样性(例如,限制来自一个频道的推荐)和用户特异性(例如,与用户观看更多的视频相似的视频应该对用户排名更高)来对相似的项目进行排名。这三个要素与一个线性模型相结合,提供了一个最终排名。
潜在因素法
潜在因素方法创建了原始用户或项目向量的新的且通常减少的特征空间,导致实时的减少的噪声和更快的计算。
下面,我们介绍两种潜在因素方法——矩阵分解和深度学习。
矩阵分解
矩阵分解在网飞推荐挑战赛中被广泛使用,特别是奇异值分解和推荐系统的一个更实用的版本。
奇异值分解 ( SVD)将偏好矩阵分解为
U 和 V 是酉矩阵。对于 4 个用户和 5 个项目,它看起来像
其中西格玛 _1 >西格玛 _2 >西格玛 _3 >西格玛 _4 。
第一用户对第一项目的偏好可以写成
这可以用向量来表示
在 sigma 向量和第一个用户向量之间应用 entrywise 乘积,然后与第一个项目向量应用点积。可以看出 u 和 v 具有相同的长度,即它们在相同的潜在特征空间中。西格玛向量代表每个特征的重要性。
现在,让我们根据 sigmas 选择前两个特征
其可以表示为项目和用户向量,每个向量的长度为 2。
西蒙·芬克的奇异值分解
偏好矩阵中的许多条目可能会丢失,常规 SVD 存在以下问题:( 1)丢失值的估算方式可能会对结果产生不良影响。(2)考虑到所有条目,训练的计算复杂度可能很高。
在网飞挑战赛中,西蒙·芬克提出了一个可行的解决方案
在公式中,仅考虑非缺失条目 p_{ij} 。来自 i^{th} 用户的 j^{th} 项目的预计得分为
注意,用户和项目向量没有 SVD 中的单位长度,但这无关紧要,因为误差的平方和被最小化了。芬克的方法在网飞挑战赛中取得了巨大的成功,这个想法由网飞实施(网飞|2012)。
深度学习嵌入
深度学习在将各种因素纳入建模和创建嵌入方面更灵活(比矩阵分解更灵活)。例如,深度学习通过利用 skip-gram 模型来对序列信息进行建模,该模型最初用于计算单词相似度。(Airbnb|2018,Zillow|2018)
比如说,一个用户的项目序列是 item1 -> item2 -> item 3 -> item4 ->直觉是用序列中的每一个项目来预测它的相邻项目,公式化为一个分类问题,其中每一个项目都是一个类。训练数据包括每个项目的相邻 K 个项目(左 K 和右 K 个项目)。下图说明了 K = 1 的项目对。
此外,每个项目被表示为一个独热向量,其长度等于项目的数量。类神经网络将项目 one-hot 向量作为输入,并输出其相似项目之一的向量,如下图所示,使用(Item2,Item1)作为训练示例。
隐藏层是新的特征空间(或潜在空间),可以使用输入层和隐藏层之间的权重将每个项目转移到新的特征空间(本质上是原始特征的线性组合)。
在现实中,可能有数百万个项目,数十亿个示例用于训练网络。为了简化计算,可以应用负采样的思想。其思想是只更新输出项(项 1)和少量随机抽样的其他项的权重。在下面,我们突出显示需要更新的项目和权重。这使得计算速度更快。
一旦在新的特征空间中表示了每个项目,就可以计算项目之间的相似性,并且可以基于相似性分数来进行推荐。
在一些情况下,用户在转换之前访问一系列项目,例如,亚马逊用户在一系列页面浏览之后进行购买;Airbnb 用户在查看了几个房源后预订了一个房源。可以通过将购买的物品添加到每个物品的训练对(Airbnb|2018)来包含这些信息,如下图所示。以这种方式推荐的项目可以提高转化率。
混合方法
混合方法使用来自用户-项目交互和用户/项目特征的信息。
Linkedin 的“你可能想关注的公司”功能使用了内容和协作过滤信息(Linkedin|2014)。为了确定用户是否想要关注某个公司,逻辑回归分类器建立在一组特征上。协同过滤信息被包括在指示该公司是否与用户已经关注的公司相似的特征中。内容信息包括是否行业、地点等。用户和公司之间的匹配。
深度学习模型在结合协作过滤和基于内容的信息方面可以是强大的。Youtube 推荐系统(Youtube|2016)建立了深度学习模型,根据用户以前的活动(搜索查询和观看的视频)和静态信息(性别、位置等)来预测用户的观看。).观看的视频和查询被表示为嵌入。由于神经网络通常采用固定长度的输入,用户观看的视频或查询向量被平均,并与其他静态特征连接。建议将多个类别的特征嵌入到一个小得多的空间中(大致与唯一值个数的对数成正比),连续特征在 0 到 1 之间归一化(Youtube|2016)。
当用户/项目没有或很少活动时,混合方法可以依赖于基于内容的推荐,并且随着更多数据可用而变得更加准确。
冷启动、可扩展性、可解释性和开发探索
对于没有信息或信息很少的新用户/项目,无法做出准确的推荐。这被称为冷启动问题。这是依赖于用户-项目交互的协同过滤系统的典型问题。可以使用一些试探法。对于新用户,可以推荐用户区域中最受欢迎的项目。对于新项目,可以定义一些基于规则的相似性标准。例如,Airbnb 使用相同类型和价格范围的 3 个地理上最接近的房源的平均值来近似一个新房源(Airbnb|2018)。
在决定使用哪种类型的推荐系统时,可扩展性是一个关键因素。更复杂的系统需要更多的人,可能更难雇用,以更高的硬件成本来构建/维护。这可能是一个长期的承诺,因此企业应该了解增加的业务收益与增加的成本。也就是说,这里有一些构建可伸缩系统的关键要素。
离线批量计算和在线上菜。有了大量的用户和项目,人们必须离线批量计算容易获取的推荐。例如,Linkedin 使用 Hadoop 来批量处理用户项目事件数据,然后将建议加载到键值存储中进行低延迟实时查询。(领英|2014)
采样。当处理数百万用户和项目时,可以考虑抽样,随机抽样项目或用户,或者在没有显著用户参与的情况下删除项目。
利用稀疏度。在推荐系统中,用户项目偏好矩阵通常非常稀疏,大多数条目都丢失了。利用稀疏性可以显著降低计算复杂度(Amazon|2003)。
多阶段建模。Youtube 推荐系统将建模过程分为两步。在第一阶段,仅使用用户项目活动数据从数百万个候选项中选择数百个。在第二阶段,使用关于候选视频的更多信息用于进一步的选择和排序是可行的。(Youtube|2016)
规模化深度人脉。虽然在输出层中使用 softmax 或其他函数进行训练,但是在实时服务时间期间,不必计算概率,并且可以对来自最后一个隐藏层的输出使用最近邻方法。也可以考虑前面提到的负采样,以便对于每个训练示例,只更新少量的类的权重。
可解释性。从客户的角度来看,陈述为什么提出建议是有帮助的。在向用户推荐视频时,Youtube 添加了用户观看的视频的链接,并触发了推荐(Youtube|2010)。
从建模的角度来看,可解释性有助于开发人员理解和调试系统。基于内容的方法很容易理解,而协作过滤模型很难理解,尤其是在潜在空间。可以基于项目或用户的原始特征空间或潜在空间(矩阵分解和深度学习)对其进行聚类,并检查来自同一聚类的对象是否共享相似的特征。
此外,t-SNE 算法(Maaten|2018)可用于将高维空间投影到二维空间进行可视化(Zillow|2018)。拥有一个工具也是有用的,这样人们可以快速查看建议作为健全检查,例如 Airbnb 开发了一个内部探索工具来验证建议(Airbnb|2018)。
**开采——勘探。**推荐系统不应该过度拟合历史用户项目偏好数据(利用),以避免陷入局部最优。
首先,应该避免训练数据完全受到先前建议的影响。Youtube 包括嵌入在其他网站中用于培训的视频。在 Youtube 站点外观看的视频并非来自推荐系统,可以有效地浮出新内容(Youtube|2016)。还可以考虑将随机性注入系统中(例如,进行随机推荐)。
可以将简单的规则添加到系统中,以增加推荐的多样性。例如,在 Youtube 推荐(Youtube|2010)中,删除了彼此过于相似的视频,并且限制了来自同一频道的视频数量。
也可以应用来自多武装匪徒的方法。优步 eats 应用了置信上限,以增加推荐餐厅/菜肴的多样性(优步|2018)。置信上限的思想是使用估计成功率的上限(例如,订单率、点击率、观看率)。当一个新项目到达时没有任何信息,置信区间很宽,因此上限很高。因此,新项目将有很高的机会被推荐。随着项目获得更多的印象,估计会更准确,上限会更接近其实际价值。
关闭
本文讨论了构建推荐系统的方法和关键观点。在实践中,公司应根据准确性、复杂性和业务影响等多种因素,在现实的资源限制(例如,工程师和软件/硬件成本)下做出选择。
参考文献
【1】音乐基因组计划。潘多拉|维基百科
【2】潘多拉的音乐推荐器。迈克尔·豪|潘多拉
[3]Amazon.com 推荐:单品对单品协同过滤,格雷格、史密斯和约克|亚马逊| 2003
[4]YouTube 视频推荐系统。Davidson,Liebald,Liu,Nandy,Vleet,Gargi,Gupta 等人。
[5]浏览器地图:LinkedIn 的协同过滤。吴,山姆,肖恩,米图,波塞| Linkedin | 2014
[6]推荐:超越 5 星。网飞科技博客| 2012
【7】网飞更新:在家试试这个。Simon Funk | 2006
[8]列出搜索排名中的嵌入。mihajlo Grbovic | Airbnb | 2018
【9】YouTube 推荐的深度神经网络。Paul Covington,Jay Adams 和 Emre Sargin | Youtube | 2016
【10】类似住宅推荐的住宅嵌入。桑迪林|Zillow|2018
[11]使用 t-SNE 可视化数据。Maaten,Laurens van der,和 Geoffrey Hinton|2008
[12]用 Uber Eats 发现食物:向市场推荐。Yuyan Wang,Ning,Isaac Liu,和 Xian |优步|2018
[13]在推荐系统中使用人机处理。埃里克·科尔森|缝合修复|2013
用知识图表协调您的数据和世界
对知识图表迷人世界的全面介绍。
Featured image credits: The GDELT Project
知识是任何成功计划的核心。在数据时代,人们会认为整合知识的任务会比以往任何时候都容易。
然而,数据量、数据速度和数据准确性这三个因素使得这项任务一点也不容易。实现这一目标的有效方法是什么?
输入知识图表。
知识的图形化表示已经存在了几十年,可以追溯到 20 世纪 60 年代。
在我们的上一篇文章中,我们谈到了图形技术(数据库、处理和可视化)。我们还探讨了它如何解决阻碍数据驱动计划高效运行的多个棘手问题。
图形技术崛起的一个关键点是谷歌早在 2012 年就发布了其知识图 (KG)。
Google’s KG acquires and connects data from multiple sources so that you can see this box. Photo courtesy: Google
一些最大的技术公司的核心是知识图表。2018 年,Gartner 将 kg 纳入了技术炒作周期。
Knowledge graphs were included under the ‘Digitalized Ecosystems’ trend in the 2018 hype cycle.
Photo courtesy: Gartner
什么是知识图(KG)?
尽管有突出的学术和行业例子,围绕术语知识图有许多混乱。2016 年的论文“走向知识图的定义”探讨了这一困境,并试图提供一个定义。
你也可以在网上找到其他合理的定义。在这些定义的基础上,我尝试给出一个定义:
知识图由图形数据存储和知识工具包组成。它使用遵循本体的图模型将领域的数据存储为实体和关系。
知识工具包支持持续集成来自多个来源的数据,允许最终用户有效地查询图表,并从现有信息中进行推断。
Sample Panama papers data schema. Photo courtesy: Neo4j
Here’s how a portion of a KG may look like. Photo courtesy: Neo4j
可以把本体看作是图形数据的一种模式。这并不完全准确,但这是一个有用的开始方式。一个领域的本体以一种类似于真实世界的方式定义了它的成员(实体、关系)和它们的属性。点击阅读更多相关信息。
此外,上面提到的工具包可以提供许多高级功能,如语义搜索和机器学习(ML)能力。我的定义只涵盖了最低限度。
为什么要关心知识图(kg)?
当谷歌引入 KGs 时,他们写了一个博客,提到 KGs 如何允许用户通过“事物,而不是字符串”进行搜索。图表更接近我们的心理模型,使我们可以很容易地将数据描述为现实世界的对象。
一公斤的重量伴随着图形技术公司通常的 T4 优势。这意味着摆脱昂贵的连接操作、白板友好的数据模型、稀疏数据的有效处理,以及使用诸如 PageRank 之类的便捷算法。图表也可以帮助改善 ML 的现状。特别是,图形神经网络最近出现在新闻中。
现在,添加一个强大的知识工具包,您将获得:
- 从结构化(RDBMS)到非结构化(文本和图像)的多种来源和不同格式的数据的持续集成。
- 逻辑推理和推断能力。例如,从“A 在化学系工作”、“B 管理化学系”等关系中,系统应该推断出“B 是 A 的经理”。
- 实体解析和提取功能,用于处理杂乱的数据和事实的多个版本。下图显示了一个示例,其中一个人有两个与其姓名相关联的不同记录,这种情况必须得到解决。
first name | last name | address | phone | ------------------------------------------------------
Sal | khan | 10 m nagar | 91-0123 |
Salman | Khan | 10 Malviya Nagar | |
此外,KG 还充当了多个团队甚至整个组织的共享资源和公共接口。例如,使用来自多个部门的数据的 ML 模型需要查询 KG 的实体和关系,而不是来自多个筒仓(仓库、湖泊和 RDBMSes)的数据。
语义网和它有什么关系?
你可能经常会发现知识图和语义网在同一个语境中被提及。有一段时间,语义网技术和标准是 KGs 的同义词。现在不是这样的。
注意上面的定义并没有提到具体的标准。
使用语义 web 标准构建图表有很多好处,包括容易与使用相同标准发布的许多公共知识库集成。然而,相关的复杂性和陡峭的学习曲线可能会使其更加困难和无用。
那么,我该如何使用它呢?
以下任一方法都可以提供对 KG 的访问:
- 可视化层:可视化浏览器和直观的界面可以用来为最终用户提供图形浏览体验。这对于不熟悉编程或查询语言的领域经验丰富的用户特别有用。
- 查询层:可以使用 Sparql 、 Gremlin 和 Cypher 等语言查询存储 KG 的数据库。
An example of a query on Gremlin.
Query courtesy: Apache Tinkerpop
- **API 层:**能够通过 REST 或编程语言访问 KG 在开发应用程序时很有用。
野外知识图表
工业界、学术界和公共领域都有成功的例子。
- 一些最大的互联网公司,包括谷歌、微软(Bing,LinkedIn)、脸书、阿里巴巴和优步,使用 KGs 为他们的内部和外部服务提供动力。
- 像美国国家航空航天局(研究)和汤森路透(金融)这样的组织也接受了 KGs。
- CMU 的 NELL (永无止境的语言学习)是一个学术项目,试图创建一个学习阅读网页并使用 KG 存储信息的计算机系统。
GDelt 项目是一个实时的全球开放数据图。它不断从世界各地的新闻媒体中提取信息。
知识图表的挑战
知识图被用于不同的行业,它们的用例在功能上可能有所不同。但是他们在实现一个有用的知识工具包时面临的核心挑战是一样的。
- **实体歧义消除和解决:**不同的源可能不同地指代相同的实体。其他时候,不同的实体可能共享属性,如名称。我们需要为图中的实体分配唯一的规范化身份。
- **知识提取和整合:**尽管最近在 ML 和自然语言处理 (NLP)方面取得了进展,但从异构源(文本、RDBMS 和 pdf)中提取信息仍然是一个挑战。整合它们也不是一项简单的任务。
- **管理变化:**加上身份挑战,捕捉知识随时间的演变会变得很困难。KG 可能需要存储时间偏移和历史。例如,如果一家公司被收购,如何管理其新旧身份?
- **轻松访问:**用户界面可以是查询编辑器、可视化资源管理器或编程接口,如软件库或 API。
- **安全和隐私:**如果要广泛部署 kg,它们必须在提供价值的同时考虑隐私和安全问题。
- **规模化经营:**当规模化的挑战到来时,上述所有问题都变得更加难以解决。
在 Atlan,我们一直致力于为世界各地的数据团队解决数据民主化问题。我们每天都在应对激动人心的挑战,包括上面列出的挑战。请继续收听我们的经历。
最后的话
互联数据比以往任何时候都更加重要。能够有效地整合孤岛对于从数据中提取价值至关重要。知识图表提供了一个很好的方法来做同样的事情。它可以增强从业务用户(改进的数据发现)到数据科学家(更好的 ML 模型)的利益相关者的能力。
着手构建和操作知识图表确实会带来挑战。但是一个有效的工具包可以帮助你应对挑战。
如果你想了解 KGs 是否适合你的用例或者有疑问,请留下评论。🙂
以下是一些参考资料,它们在我为这篇文章做研究时对我有所帮助:
原载于https://humansofdata.atlan.com2019 年 8 月 22 日
谢谢你的阅读。关注我 中 了解更多内容。非常感谢您的反馈。你可以通过推特 @AkashTandon 联系到我。
重建谷歌趋势长期每日数据
比较方法以超越每日趋势数据的 9 个月查询限制。
iPhone search trends, AAPL stock price and Apple key events
- 我们可以在任何持续时间内以每日分辨率获取搜索趋势数据。
- 用每周趋势来衡量每日数据可能会产生一些假象。
- 只要在重叠期间有足够的搜索活动,使用重叠期间进行缩放会更好。
- 代码可以在这里找到。
随着谷歌获得了互联网搜索的垄断地位,随着时间的推移,我们搜索的任何内容都成为了另一种公众兴趣的衡量标准。谷歌新闻实验室已经很好地解释了这一点,一些文章展示了基于谷歌趋势的数据分析,如结束与某人关系的循环模式、预测美国总统竞选等。
局限性
为了充分利用搜索趋势数据库,可以使用 python 模块 pytrends 或 R 包 gtrendsR 。然而,google 目前基于查询的时间框架限制了时间分辨率。例如,过去 7 天的查询将具有每小时的搜索趋势(所谓的实时数据),每天的数据仅提供给短于 9 个月且在您搜索之前最多 36 个小时的查询期(如 Google Trends FAQ 所述),每周的数据提供给 9 个月到 5 年之间的查询,任何长于 5 年的查询将仅返回每月的数据。
我研究这个课题的动机最初是受到 Kaggle 的 Rossmann 竞赛的启发,在该竞赛中,谷歌搜索趋势被用来预测销售数字。我发现获取每日搜索趋势并不那么明显,人们使用每周趋势作为替代。但是,对于任何需要每日精度和实时应用的预测模型来说,它并不理想(因为每周数据只在本周结束时可用)。
比较重建每日趋势的方法
虽然人们已经想出了规避的方法(比如:这里的,这里的)。我很好奇这些方法是如何相互比较的,如何与原始的每日趋势数据最匹配。因此,我使用“iPhone”作为关键词,通过以下三种方法重建 35 个月的每日趋势数据:
- 从多个 1 个月的查询中串联的每日数据,并通过相应的每周趋势数据进行标准化。(pytrends 中实现的 dailydata 函数)。
- 查询具有大量重叠时段的多个 9 个月时段,并使用重叠时段来获得一致的缩放比例(类似于此处的目的)。
- 每日数据只是从每周数据中插入的。(供参考)
Comparing daily trend data obtained using the overlapping method(blue), dailydata method from pytrends(orange), interpolation from weekly data(green), and the overlapped period used for scaling (red)
乍一看,我们可以注意到他们给出了完全不同的结果。pytrends 的 dailydata 函数与周数据匹配得相当好,其基线值(重要峰值之间的周期)高于通过重叠方法获得的值。目前,很难说哪个更好,尽管如此,每日数据(绿线)在主要峰值附近有一些明显的下降,例如 2017 年 9 月左右的最低值。
为了验证哪些重建的每日趋势与原始数据匹配得更好,直接提取较短时期(< 9 个月)的每日数据进行比较。
Comparing daily trends data normalized differently with the original daily trends (pink)
现在很清楚,重叠方法(蓝线)与原始日数据(粉线)最匹配,橙色线的下降是由周数据缩放产生的伪影。
英国退出欧盟、谷歌趋势和英镑
为了进一步展示长期每日搜索数据的潜在优势和应用,我们使用“英国退出欧盟”作为 2018 年 10 月至 2019 年 11 月期间的搜索词。重建的每日数据与默认的每周数据(因为查询期长于 9 个月)一起绘制,以便进行比较。
Compare the daily trend reconstructed by the overlapping method (blue) with the original weekly trend (red).
有了重建的每日趋势,我们可以精确地将搜索趋势的激增与这 14 个月期间的每个重大事件相匹配。它还使我们能够比较每个不同事件日期的相对搜索量,而每周趋势失去了分辨率,相邻事件的相对搜索量被平均(或汇集在一起)。
出于好奇,我试图将英镑汇率叠加在每日趋势图上。当“英国退出欧盟”搜索达到顶峰时,英镑经常在同一天暴跌,这并不奇怪。
GBP/USD exchange rate and ‘Brexit’ search trends
也许谷歌会取消这样的限制,并在未来提供一个更方便的 API,但在此之前,缝合和缩放重叠查询可能是最好的方式,以获得长期的每日搜索趋势。
*重构每日走势和生成本文剧情的代码可以在 github 上找到。
RecoTour II:神经推荐算法
这是 python 推荐算法系列文章的第二篇。在我很久以前写的系列文章的第一篇中,我快速浏览了我使用 Kaggle 的 Ponpare 数据集实现并尝试的一些算法。你可以在回购中找到所有相关代码。在这篇文章中,我将使用亚马逊评论数据集 [1] [2],特别是 5 核电影和电视评论,来说明两种基于 DL 的推荐算法的使用:神经协同过滤 [3]和最近的神经图协同过滤 [4]。
在我继续之前,让我强调以下几点。我在这里所做的是,在阅读了作者的论文后,使用 Pytorch 实现了他们的原始解决方案(分别在 Keras 和 Tensorflow 中)。与 RecoTour repo 中的所有其他算法一样,我用大量细节编写了许多笔记本,从如何准备数据到如何训练和验证结果。我还加入了一些额外的功能,并根据我的喜好修改了代码。然而,当然,所有的荣誉都归于作者,感谢他们出色的论文和代码的发布,这总是令人感激的。一旦清楚了这一点,不再赘言,让我们继续讨论算法
1.神经协同过滤(NCF)
让我首先澄清一下,作者将 NCF 作为一个通用框架,在他们论文的第 3 节中,它被表述为由一系列接收用户和项目嵌入的所谓 NCF 层组成。
1.1 算法
他们最终在该通用框架的上下文中实现的特定算法被称为神经矩阵分解(NeuMF)。这个算法比较简单,所以我不打算在这里花太多时间。网上有很多帖子,你或许可以在那里找到更多信息,一如既往,我强烈建议你阅读报纸,在那里你可以找到所有的细节。此外,在前几节中,你会发现引导作者实现算法的基本原理(你知道…科学论证)。
NeuMF 由两部分组成,一部分被作者称为通用矩阵分解(GMF),另一部分是多层感知器(MLP)。GMF 实际上是用户和项目嵌入之间的元素产品。我猜是如此简单,作者甚至没有考虑包括一个数字只是 GMF。尽管如此,我还是做了一个,这就是:
Fig 1. GMF model
相应的向前传球很简单:
GMF forward pass
哪里out=nn.Linear(in_features=n_emb, out_features=1)
。
MLP 其实并不复杂。他们论文中的图 2 显示了 NCF 的一般框架:
Fig 2. MLP model. (Figure 2 in their paper)
如果我们认为神经 CF 层是一些激活的线性层,我们就有了 MLP 模型。相应的向前传球:
MLP forward pass
其中mlp
只是线性图层的Sequential
堆栈,而out
与 GMF 的相同,具有相应数量的输入要素。
一旦我们有了所有的构建模块,NeuMF 就是两者的结合。如图 3 所示:
Fig 3. NeuMF model (Figure 3 in their paper.)
形式上,NeuMF 可以定义为:
Equation(s) 1. NeuMF, all the math you need
其中φ-GMF 是 MF 嵌入之间的元素乘积。φ-MLP 是所谓的 MLP 嵌入通过一系列具有一些激活的线性层的结果,而 y_hat 只是φ-GMF 和φ-MLP 的串联的结果,通过具有 sigmoid 激活(σ)的线性层。
在代码中(即正向传递):
NeuMF forward pass
至于 NeuMF 算法本身,就是这样,真的。
1.2 培训/验证策略和结果
在我们进入下一个算法之前,请允许我简单地评论一下作者的训练/验证策略,以及我使用该策略在 Amazon Revies 数据集上获得的结果。
对于给定的用户,作者分割数据集,使得除了一个之外,该用户的所有评价项目都用于训练,而剩余的评价项目用于测试。然后,在训练期间,负面隐式反馈通过每个正面项目包括 N 个负面项目(从未评定)来表示。例如,如果用户评价了 10 部电影,并且 N =4,则在训练期间将为该用户使用 50 次观察(10 次肯定+ 40 次否定)。注意, N 负样本是每个历元随机采样的,这样算法就对用户不喜欢的物品类型有了更全面的看法(参见这里的中的 repo)。在训练期间,预测得分是对输出层应用 sigmoid 函数的结果,损失是二进制交叉熵(BCE)损失。
在测试期间,每个用户使用一组 100 个项目。其中一项是训练时没有用到的正面项目,其余九十九项是随机选取的负面项目。然后,我们预测这 100 个项目的得分,并计算排名指标。在 NeuMF 的情况下,这些是命中率(HR)和在 k 推荐值(在本例中 k=10)下的归一化贴现累积收益(NDCG)。
NeuMF 可以在有或没有 GMF 或 MLP 预训练权重的情况下运行,具有不同数量的嵌入、MLP 层等。我已经运行了许多实验(可以在 repo 的脚本run_experiments.sh
中找到),包括使用循环学习率【5】,对结果的讨论可以在本笔记本中找到。让我在这里简单总结一下。
Fig 4. Ranking metrics vs Embedding dimension for the GMF and MLP models
图 4 显示了根据嵌入数量(8、16、32 和 64)绘制的 GMF 和 MLP 模型获得的排名度量。有趣的是,使用最简单的模型(即 GMF 和低嵌入数)可以获得更好的排名指标。这表明,对于这个特定的数据集,可以通过简单的算法获得好的推荐,一般来说,这并不是不寻常的结果。尽管如此,值得一提的是,使用预训练权重的 NeuMF 算法获得了最好的结果,但是改进是微不足道的。当然,在“真实世界”中,人们可能想知道增加的复杂性是否补偿了排名指标的边际增加。
Fig 5. Ranking metrics vs BCE Loss for the GMF and MLP models
图 5 中显示了另一个有趣的发现,其中测试期间的排名度量相对于训练期间获得的 BCE 损失进行了绘制。这里可以看到 BCE 损失和排序度量是相关的,而先验地,人们可能期望相反的行为(即,反相关,BCE 损失越低,排序度量越高)。这种情况并不罕见,或许应该引起更多的关注。一旦我描述了神经图协同过滤及其相应的结果,我将在文章的结尾回到这个结果。
2.神经图协同过滤
这个算法比前一个稍微复杂一点,所以我将更详细地描述它。尽管如此,为了保持这篇文章的可读性,我将把内容限制在我认为理解算法所必需的最小限度。请一如既往地阅读这篇论文,在这种情况下,请阅读其中的参考文献。特别是用图卷积网络的半监督分类【6】和图卷积矩阵完成【7】。托马斯·基普夫和合著者为他们的论文发布的代码非常棒。让我们继续讨论算法:NGCF。
2.1。算法
Fig 6. Illustration of the user-item interaction up to order 3 (Figure 1 in their paper)
图 6 的左侧是用户-项目交互图的图示,作者称之为高阶连接。节点/用户 u ₁是为其提供建议的目标用户。我们可以看到,在第一阶( l -hop,其中 l =1),将捕获用户与项目 1、2 和 3 交互的信息。在第二阶(2-hop ),人们将捕获u₁←I₂←u2 和u₁←I₃←u₃,等等。
右边是模型方案。用作者的话说:“我们设计了一种神经网络方法,在图上递归传播嵌入。这是受图形神经网络的最近发展的启发[…],它可以被视为在嵌入空间中构造信息流。具体来说,我们设计了一个嵌入传播层,它通过聚合交互项目(或用户)的嵌入来细化用户(或项目)的嵌入。通过堆叠多个嵌入传播层,我们可以加强嵌入,以捕捉高阶连接中的协作信号。”
让我们试着通过一些数学和代码来增加前一段的清晰度。当然,我们需要的第一个构建模块是表示图,即构建拉普拉斯矩阵,定义为:
Eq 2. Laplacian Matrix
其中 D 是对角度矩阵, A 是邻接矩阵, R 是评级矩阵,在这种情况下是具有 1/0 的二进制矩阵,指示用户是否对电影进行了评级。构建拉普拉斯矩阵发生在utis
模块内的[load_data.py](https://github.com/jrzaurin/RecoTour/blob/master/Amazon/neural_graph_cf/utils/load_data.py)
中。你会看到,按照作者最初的实现,我构建了许多不同的邻接矩阵来探索不同的场景(例如,在某些情况下,我们考虑自连接,或者在连接的节点之间使用不同的衰减因子)。一旦拉普拉斯矩阵建立,让我们移动到模型。
示意性地,上面引用的模型可以绘制成这样:
Fig 7. Illustration of NGCF model architecture (Figure 2 in their paper).
嵌入传播层(图 7 中的灰色方块)中的第一个数学运算是“嵌入聚合”(即聚合每个用户/项目的所有交互项目/用户的嵌入)。然后,聚合的结果通过一系列带有 LeakyRelu 激活的线性层传递,并与初始嵌入连接。最后,我们直接计算损失(在这种情况下,BPR 损失,见下文)。也就是说,在该特定实现中,正向传递的输出将直接是损耗值。一旦我们研究了数学和代码,所有这些都会变得更加清晰。
形式上,该模型由两部分组成:消息构造和消息聚合*。*
消息结构定义为:
Eq 3. NCGF message construction.
其中⊙表示逐元素乘法。1/√(|nᵤ||nᵢ|)是图的拉普拉斯范数。 Nᵤ 和 Nᵢ 是用户 u 和项目 i 的第一跳邻居。如果你看一下load_data.py
中的代码,你会发现这个因子(两个相连节点之间的衰减因子)已经通过构造在我们的拉普拉斯矩阵中被考虑了。这意味着,一旦我们在 Pytorch 实现中达到了正向传递,我们就可以只关注等式 3 中括号内的两项。
还值得提醒的是,这里 eᵢ或 eᵤ不是初始嵌入,而是聚合嵌入,即对于用户 1,eᵢ将是该用户与之交互的所有项目的聚合嵌入。从程序上来说,这可以简单地通过将初始嵌入乘以拉普拉斯矩阵来实现。我们将在后面的前传中看到。
消息聚合定义为:
Eq4. NGCF message aggregation
这只是应用于所有构造的消息的总和的结果的 LeakyRelu 激活。
一旦构建和聚合了消息,我们会根据您的需要多次重复该过程(即分层)。如果您想了解更多关于消息构造和聚合公式背后的推理,请参阅本文。易于阅读和理解。对于这个职位我需要的 Eq 2,3 和 4 就足够了。
现在让我们关注训练期间使用的损失函数,即所谓的 贝叶斯个性化排序 损失【8】。在 NGCF 的论文中被定义为:
Eq 5. BPR Loss
其中 O = {( u,I,j )| ( u,i ) ∈ ℝ⁺,( u,j ) ∈ ℝ⁻}是训练元组的集合,其中ℝ⁺和ℝ⁻分别对应于观察到的和未观察到的交互(也称为正交互和负交互)。σ是 sigmoid 函数,θ都是训练参数。
总之,我们已经看到了如何构建拉普拉斯矩阵,如何构造和聚合消息,以及如何在训练期间评估算法的性能。我们现在可以转到代码:
NGCF Forward Pass
这个片段中的代码类似于带有 repo 的代码,只是去掉了一些额外的组件。让我们对这段代码稍加注释,看看它与前面显示的数学表达式有什么关系:
- 第 2 行:初始嵌入的简单串联。这将产生一个维度矩阵(# 用户 +# 项目,# 嵌入)。作者称这种串联的结果为
ego_embeddings
。这是因为在形式上,如果我们仅使用这些嵌入,我们将仅考虑从给定节点(又名焦点节点)传递到与其直接连接的节点(即自我网络)的信息。 - 第 9–10 行:对于每一跳(层或连接顺序),我们首先将拉普拉斯矩阵乘以前面描述的连接结果。该矩阵乘法的结果将是之前提到的聚合嵌入,并且在等式 3 中被称为 eᵤ 和 eᵢ 。因为拉普拉斯矩阵…很大,我们不能一下子做到这一点,所以我们把它分成“折叠”(按行划分)并依次相乘。
- 第 13 行:等式 3 括号内的第一项就是第 13 行。
- 第 15–16 行:这是等式 3 括号内的第二项。
从那里开始是相当简单的。在计算 BPR 损失之前,我们归一化嵌入并连接它们。
注意,我们还应用了作者所谓的“消息丢失”,这是通常直接应用于嵌入的nn.Dropout
。它们区分了消息丢失和节点丢失。作者通过在拉普拉斯矩阵上使用tf.sparse_retain
(见这里的)来实现后者,该矩阵保留位置。就我个人而言,我称之为边缘丢失,因为节点丢失,以我的理解,是将拉普拉斯矩阵中的一整行归零。尽管如此,无论是边缘还是节点丢失,这些在计算上都是非常昂贵的。因此,即使我已经实现了它们,并且包含在我的 repo 中的代码中,我也没有在运行实验时探究它们的效果。
在这个阶段,我想暂停一下,把注意力放在上面片段中的 NGCF 向前传球上。正如我们所看到的,直到第 24 行,批量的大小并不重要。到那一行,我们必须为所有的用户和条目构建和执行整个图。在这种情况下,静态(即声明性)框架,如 Tensorflow,更适合。当使用静态框架时,图被构建一次,然后当数据流经图时被端到端地执行(例如,我们称之为loss
函数)。另一方面,当使用动态框架(也称为命令式框架)时,图是在每次向前传递时构建和执行的。因此,虽然第二种方法比第一种方法更灵活,但在类似这里描述的问题中,它们的执行速度明显较慢。例如,Pytorch 在运行 NGCF 时保持"竞争力"的唯一方法是使用大批量,因此可以将每个时期的向前传递次数降至最低。尽管如此,作者最初的TF 实现更快。
2.2 培训/验证策略和结果
在 NGCF 的案例中,培训遵循的是使用 BPR 损失时的标准策略。每个批次由类似(用户、正项目、负项目)的三元组组成,即 256 的批次大小将包含 256 个这样的三元组,正向传递的输出直接是我们需要最小化的 BPR 损失。
然后,在测试过程中,我们对每个用户从未评价过的所有项目进行排名。在这种情况下,排名分数只是用户和项目嵌入之间的点积。请注意,由于在这种情况下,我们对每个用户的大量项目(用户在训练期间没有与之交互的所有项目)进行评级,因此此处获得的排名指标明显小于为 NeuMF 获得的排名指标,后者是在每个用户 100 个项目的组内计算的。
以 NCGF 为例,我只进行了 15 次实验。因此,这绝不是对参数空间的详尽探索。我尝试过使用 RAdam 优化器[9],这是为了在一些问题中找到 SOTA 解。事实是,在使用 RAdam 时,我在最少的历元数内获得了最佳的 BPR 损失。然而,正如我将在下面讨论的,在这些类型的问题(推荐算法)中,最佳损失值并不总是意味着最佳排名度量。尽管如此,我发现这个结果真的很有希望和鼓舞人心,我期待着在其他项目中尝试 RAdam。
总的来说,在这个笔记本里可以找到结果的总结和简短的讨论。让我在这里包括下图。
Fig8. Ranking metrics vs BPR Loss
图 8 显示了排名指标随着 BPR 损失的减少而提高的趋势,正如人们所预料的那样。然而,这并不是一个平稳的趋势。事实上,就排名指标而言,第二好的结果是第六好的 BPR 损失值(参见笔记本)。这与我之前关于“损失与排名指标”评估的评论有关,或许值得专门写一两段。
一般来说,在构建推荐算法时,您通常可以将其作为分类/回归问题或排名问题来评估其性能。后者与信息检索效率更相关,通常是我的偏好。首先,因为我认为这是衡量推荐算法表现的一个更可靠的方法,其次,因为有时评分可能有点、。例如,他们可能会受到用户当天情绪的影响,或者因为电影期间发生了一些事情(互联网故障,或者网站故障)。
此外,你不希望得到“太好”的预测评级。一般来说,你希望你的算法具有良好的覆盖率*(即尽可能多地覆盖商品空间)和多样性(即推荐用户可能喜欢的尽可能多样化的商品)。这也涉及到新颖性(即推荐用户没有意识到的项目)和偶然性(向用户推荐意想不到的项目)的概念。如果你的建议完全依赖于在预测明确评级时实现最佳损失,那么你最终将减少所有覆盖面、多样性、新奇性和意外收获,并最终减少参与度。*
如果你想了解更多关于如何评估推荐算法的细节,请确保阅读这本神奇的书【10】的第 7 章。
暂时就这样了。在 NCF 和 NGCF 这两个案例中,我都包含了一个名为get_embeddings.py
的脚本,其中我使用了学习嵌入和 KNN 来展示这些学习嵌入“有意义”。也就是说,给定某部电影,嵌入空间中最接近的电影将是明智的推荐。
3.未来的工作
当我有时间的时候,我打算使用最新发布的XL learn库,查看与分解机【11】和现场感知分解机【12】相关的笔记本。我相信他们已经解决了我在使用该软件包时所面临的许多问题,而且当时它已经是一个非常有前途的软件包了。因此,我认为值得再试一次。就添加更多算法而言,下一步是多 VAE【13】。正如法拉利·达克雷马等人【14】的优秀作品中所描述的,Mult-VAE 似乎是唯一一种基于深度学习的推荐算法,实际上比更简单的非 DL 技术表现得更好。
一如既往,任何想法或意见,请发邮件给我:jrzaurin@gmail.com
参考资料:
[1] J .麦考利,c .塔吉特,j .施,a .范登亨格尔。基于图像的风格和替代品建议。2015 年,SIGIR
[2]何,麦考利。用一类协同过滤对流行趋势的视觉演变建模。WWW,2016
[3]何湘南,廖,汉王张,聂,,蔡达生.神经协同过滤。arXiv:1708.05031v2. 2016
[4],何湘南,,冯福利,蔡达生.神经图协同过滤。SIGIR 2019。arXiv:1905.08108
[5]莱斯利·史密斯。训练神经网络的循环学习率。WACV 2017。arXiv:1506.01186
[6] Thomas N. Kipf 和 Max Welling:使用
图卷积网络的半监督分类。ICLR 2017。arXiv:1609.02907
[7]里安娜·范登贝格,托马斯·n·基普夫,马克斯·韦林。KDD 2018。arXiv:1706.02263
[8] Steffen Rendle、Christoph Freudenthaler、Zeno Gantner 和 Lars Schmidt-Thieme。2009.BPR:基于隐式反馈的贝叶斯个性化排序。在 UAI。452– 461.
[9],,江,何鹏程,,陈,,高剑锋,韩家伟.适应性学习率的方差及其超越。arXiv:1908.03265
[10]推荐系统:教科书。查鲁·阿加尔瓦尔。斯普林格 2016
[11]斯蒂芬·伦德尔。因式分解机。2010 年 IEEE 数据挖掘国际会议 ICDM 会议录
[12]·潘、·阿丰索··鲁伊斯、·赵、·潘、·孙玉、展示广告点击率预测的场加权因子分解机。WWW 2018。arXiv:1806.03514
[13] Dawen Liang,Rahul G. Krishnan,Matthew D. Hoffman,Tony Jebara:用于协同过滤的可变自动编码器。WWW 2018。arXiv:1802.05814
[14]毛里齐奥·费拉里·达克雷马、保罗·克雷莫内西、迪特马尔·扬纳克:我们真的取得了很大进步吗?最近神经推荐方法的令人担忧的分析。第 13 届 ACM 推荐系统会议录(RecSys 2019)。arXiv:1907.06902
使用 Plotly Express 用 2 行 Python 重新创建 Gapminder 动画
免责声明:使用了一个新模块
plotly_express
,Gapminder 动画没有使用 2 行代码从头开始编码
这是数据可视化的标志性时刻之一,当时汉斯·罗斯林在他的 ted 演讲中展示了著名的 Gapminder 动画,这是有史以来观看次数最多的 TED 演讲之一。从那时起,它就像是任何进行可视化的人复制它以显示他们的数据可视化能力的基准——就像复制爱德华·塔夫特或内特·西尔弗的可视化作品一样。
最近 Plotly (以 R 和 Python 的交互式可视化 DSL 而闻名)推出了一个新的工具/模块/库,名为 Plotly Express 。顾名思义,plotly express
的主要目标是成为一个非常简单、快速和易于使用的高级 API 来构建交互式可视化。
更像这样,
plotly Express:plotly . py::Seaborn:Matplotlib
受 R 的ggplot2
和 Python 的seaborn
的启发,以简单为核心的plotly express
试图在one-liners
中做事。在这篇文章中,我们将看到如何仅仅使用plotly express
来重现(如果不完全重现,至少类似于)标志性的 Gapminder 动画。
装置
pip3 install plotly_express
使用别名导入库:
import plotly_express as px
气泡图动画又名 Gapminder 动画
px.scatter(px.data.gapminder(), x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
size="pop", color="country", hover_name="country",
log_x = True,
size_max=45, range_x=[100,100000], range_y=[25,90])
这是一个非常简单的函数(我曾经见过这样的 Gapminder 动画)。函数px.scatter()
从px.data.gapminder()
获取数据,然后通常定义x
和y
轴以及每年递增的animation_frame
。随着更多关于外观改进的讨论,动画泡泡图已经准备好了!
Plotly Express 教程视频构建 Gapminder 动画:
鳍
这篇文章的目的是传播关于plotly_express
的信息,这是一个创造美丽的交互式可视化的惊人之举(也类似于 R 中的highcharter
)。如果你想从总体上了解《T2》的剧情,可以去看看《数据营》。
资源
从 WhatsApp 聊天中重塑自我
探索我能在聊天机器人中复制我的人格的程度
Image by Gerd Altmann from Pixabay
我一直在想,我们是否有一天可以在互联网上上传一份我们自己的副本。今天,虽然我们无法制造高分辨率的意识复制品,但我相信我至少可以用现有的技术捕捉到我的人格快照。本能地,人工智能的用法浮现在脑海中——特别是聊天机器人。
有许多现有的训练聊天机器人的模型。对我个人来说,我关注了使用 Python 和 TensorFlow 的send ex 的 Youtube 教程系列。我用了 nmt-chatbot (Github 资源库这里)作为基础,写了几个工具帮我做我的 WhatsApp 聊天数据的预处理(我的 Github 工具资源库这里)。我采取了很多步骤,也从这次经历中学到了很多。
第一部分:预处理
下载 WhatsApp 聊天作为训练数据
众所周知,WhatsApp 会自动将你的聊天记录备份到 Google Drive 中。现有的解决方案允许你直接读取加密文件,但我选择直接从 WhatsApp 下载聊天记录。要做到这一点,你必须点击下拉菜单内你的聊天对话的人,点击“更多”,然后其次是“导出聊天”。
然后会提示您选择包括或不包括介质。对我来说,我选择不这样做,因为我无法通过自动化手段处理除文本之外的任何东西。希望在未来,我可以这样做,以便给整个对话提供更多的上下文,并提高聊天机器人的准确性。
清理 WhatsApp 聊天
下载聊天内容后,用您选择的任何文本编辑器打开它。您将看到这样的内容(出于隐私考虑,我删除了这些名字):
My conversation with my friend in WhatsApp opened in Sublime Text
如你所见,时间戳和人名并不是训练聊天机器人所必需的。数据需要清理,所以我写了一个 Python 脚本来去掉多余的数据段。
我首先删除了聊天的时间戳,这样名字将定义每一行的开始。我写了一个脚本叫 chatparser.py,可以在聊天处理文件夹下找到。
正如您在下面的源代码中看到的,您可以将文件名添加到数组中,这样您就可以一次处理多个文本文件。使用终端更改目录后,我执行了以下命令:
$ python chatparser.py
执行该命令后,会生成一个新文件“WhatsApp 与人聊天 Bout.txt”。
Chat with timestamp removed.
接下来,我把我和其他人的聊天记录分成两个文本文件。我运行了自己编写的另一个脚本 chatseparator.py:
$ python chatseparator.py
这导致生成的文件“WhatsApp 与人聊天 Bsep.txt”和“WhatsApp 与人聊天 BCW.txt”(也就是我),如下所示:
The responses of the person I am talking to.
The things I texted to the other party.
“|”字符用作分隔符,表示当一个人回答或发起对话时,对话在哪里分开。后来证明这是非常有用的。
分组对话
发短信时,我们倾向于把句子分成几个部分,而不是把它们聚在一起作为一条信息发送。我对一对问题/回答进行分类的方法只是通过检测发短信的人何时改变。对于一个人输入的每一个连续的文本链,它相当于句子本身。我不得不承认,这是一个极其简化的模型,但它适用于我的大多数聊天。
现在,我执行我编写的下两个 python 脚本— otherstagdelete.py 和 mytagdelete.py —来删除对话前面的名字。
$ python otherstagdelete.py$ python mytagdelete.py
然后,我运行我的 combine.py 脚本来合并分散在多个聊天消息中的句子。
$ python combine.py
删除包含媒体的响应对
因为我们选择导入没有媒体的聊天,所以有几行显示。为了进一步清理数据,我删除了包含该内容的问题/回答对。切记从中删除两个文档,myside.txt 和 otherside.txt
第二部分:训练聊天机器人
将您发起的所有聊天复制到一个文档中,将其他人发起的所有聊天复制到一个单独的文档中。到目前为止,每个问题/回答对都应该对齐到同一行,所以应该没有问题。
如果你有超过一百万个问题/回答对,你的训练结果会更准确。参考 nmt-chatbot 的 Github 库,只需将你创建的各自的训练数据放入 train.from 和 train.to 即可。
第三部分:结果
在部署我的模型时,我用一些问题测试了它,很明显聊天机器人已经采用了我的说话风格。以下是一些快照:
当然,这并不都是美好的事情,因为聊天机器人仍然在很大程度上胡说八道。这是因为我的训练集太小,没有效果。然而,作为概念验证,我发现它非常有前途。
第四部分:吸取的教训和改进
通过这个项目,我想我有一些很棒的收获,我想分享一下。
首先,可以实现自然语言处理算法来确定对话的上下文何时改变。这进一步增强了问题/响应对的准确性,并允许更好的聊天机器人。
第二,也可以采用图像识别,使得包括照片的聊天也可以用作训练数据。通过给图片加上特定的标签,它也给对话提供了背景,这很好。
AI 和机器学习真的是一个潜力无限的神奇领域。即使你和我一样是初学者,我也觉得大有可为。我鼓励每个人都真正尝试一下学习人工智能。我希望你发现这个项目是有用的,也许在某种程度上是鼓舞人心的!
重现梵高遗失的画作
在寻找杰作的过程中使用生成模型
1889 年夏天,文森特·梵高开始创作一系列风景画。每一幅画他都寄给他在巴黎的兄弟西奥。
From Museum of Fine Arts, Boston
可以看到,其中一幅画缺少了对应的画。这幅画叫做“野生植被”,大概是一片开满鲜花的田野,背景是一座山。
人们注意到丢失的画,许多人想知道它可能在哪里。
118 年后的 2007 年,当波士顿美术博物馆的一位名叫 Meta Chavannes 的管理员用 X 射线对这幅名为“峡谷”的画进行检查时,这个谜有了一个结论,并在下面发现了野生植物的遗骸。
众所周知,梵高一生都缺乏材料,当绘画的欲望变得势不可挡时,他甚至用毛巾作为画布。考虑到这一点,他干脆重用野生植被画布也就不足为奇了。遗憾的是,很难从 x 光片上看出这幅画的样子,所以这幅画似乎已经失传了。
也就是说,直到现在。借助生成机器学习的力量,我开始尝试重建这幅画。
神经类型转移
我最初的想法是,神经类型转移可能会解决这个问题。神经类型转移是一种利用深度学习内部工作的有趣事实的技术。
Image from https://blog.datarobot.com/a-primer-on-deep-learning
深度学习的一大优势是它能够自动选择特征。事实证明,当训练一个深度神经网络时,例如在人脸上,每一层都学习识别越来越高抽象的特征,因此第一层寻找直线和边缘,随后的层寻找眼睛和耳朵,而进一步的层寻找整张脸。
如果我们看两幅图像,如果它们具有相同的“内容”,即都包含一辆汽车或一张脸,我们会期望它们在更深的层中具有相似的特征。这与汽车或面部的确切外观无关。
相比之下,如果图像都包含类似的“风格”,如颜色、边缘或圆形,则早期的层将具有类似的特征。然而,事情比这要复杂一些,因为我们所说的风格通常是几个特征的组合。例如,一幅草坪的图像可能包含“尖”和“绿”的特征,而一幅森林中的刺猬的图像包含相同的特征。如果我们使用第一张图片作为样式输入,大概我们实际上想要的是“草”的样式,它是绿色和尖尖的特征在同一个地方的组合。为了实现这一点,我们使用了 gram 矩阵,它告诉我们某些特征在图像中的什么位置出现在一起。在绿草如茵的图像中,绿色和尖刺出现在同一个地方,与刺猬图像形成对比,在刺猬图像中,尖刺与棕色相关。因此,为了实现相似的风格,我们试图最大化 gram 矩阵的相似性。上面的例子摘自生成式深度学习。
然后我们进行反向传播算法,但不是像我们通常在训练时那样改变网络的权重,而是保持它们固定不变,而是改变图像。
使用库神经风格转移,我在野生植物和油画“罂粟田”上做了这个,结果如下:
结果远不能令人满意,因为模型似乎有一个辨别什么是地面和什么是天空的问题,因此在某些地方使地面变成蓝色。这种把天空的颜色放在地面上的方式当然是梵高自己在精彩的作品《播种者》中所做的,他颠倒了地面和天空的颜色顺序,但我觉得这在上面的作品中可能不合适,至少在这里不合适。
我当然应该猜到会是这样,为什么神经类型转移会知道什么是天空,什么是地面?
CycleGAN
我的下一个想法是使用 CycleGAN。GAN 是两个相互竞争的神经网络的名称。第一个网络(生成器)试图绘制图像,第二个网络(鉴别器)试图猜测第一个网络是否绘制了图像,或者它是否取自训练数据。第一种训练的目标是愚弄第二种,第二种训练的目标是不被愚弄。
Image from https://developers.google.com/machine-learning/gan/gan_structure
我喜欢和你的对手一起通过竞争变得更好,不断挑战彼此的极限。有点像猎豹如何在试图跟上羚羊的同时变得如此完美地设计速度,而羚羊在与猎豹竞争时变得更快。
普通类型的 GANs 只能产生类似于大量训练数据的图像,但是没有办法指导它。然而,CycleGAN 是一种条件 GAN,它将图像作为条件,并使用该条件来创建新图像。
它由两个 gan 和两个数据集组成。一个 GAN 生成与第一个数据集相似的图像,另一个生成与另一个数据集相似的图像。我们还将附加的“重构标准”应用于 GAN。这意味着,如果第一个 GAN 获取图像并生成另一个图像,第二个 GAN 应该能够获取新图像并生成与原始起始图像非常相似的图像。
Generator Gx->y transform image from domain x into y. Discriminator Dy tries do determine if it belongs to domain Y. Image from GAN Lecture 2 (2017): CycleGAN
在我的慢速 GTX 670 上使用库GDL _ 代码一个晚上后,结果如下:
这个好多了。天空是蓝色的,地面是绿色的,开满了花。不过分辨率太低了,所以我用更高的设置再试了一次。
不幸的是,这里的结果实际上更糟。我认为一个问题是异常小的天空。在具有较大天空的图像上进行训练,网络很难知道它在哪里。
一路上帮助机器
由于不完全满意,我决定使用混合方法。由于网络似乎很难知道图像的不同部分应该是什么,也许人机合作将有利于解决这个问题。我作为一个人,告诉机器什么是天空,什么是花朵,机器做它最擅长的事情,并以正确的风格描绘一幅画。
好吧,那没用。梵高和其他后印象派画家仍然从现实中绘画,尽管他们对现实有自己特殊的解释。我需要的不是由大块彩色区域组成的图像,而是更像照片的东西。如果我能重现梵高看到的场景,那么风格转换就可能成功。
GauGAN 和 Pix2Pix
Nvidia 创造了他们自己风格的 Pix2Pix 算法,并将其称为 GauGAN (另一位后印象派画家高更的双关语)。在这里,GAN 在两个图像上训练,在 GauGAN 的情况下,一个是照片,另一个是照片的示意图,描绘了它的不同部分,如草,水,天空。通过这种方式,GauGAN 学会了在草图和照片之间进行转换。我从上面给了它我的草图。
这看起来像是梵高可能真的见过的场景。这让我想起了阿尔卑斯山,那里有鲜花和香草,背景是那座山。
通过风格转换运行重建的图片产生:
最后,我们有可能通过野生植物的重建。
结论
我们正处于一个有趣的时间点,在这个时间点上,无论是机器还是人类,都不是在所有方面都更优越。这开启了一些有趣的合作,每一方都可以做出贡献,做出一些他们自己无法做到的事情。
生物和人工神经网络中的递归
相似性、差异及其重要性
递归是神经网络上下文中的一个过载术语,在机器学习和神经科学社区中具有完全不同的口语含义。然而,这种差异正在缩小,因为用于实际应用的人工神经网络(ann)越来越复杂,在某些方面更像生物神经网络(BNNs)(但在整体上仍有很大不同)。
在本帖中,我们将讨论这两个社区中使用术语复发的历史差异,强调一些最近向神经科学发展的深度学习人工神经网络模型,指出一些揭示复发功能的神经科学研究,并推测未来的发展。
太长;没看
- 深度学习社区所说的循环 连接类似于神经科学社区所说的横向连接。即局部区域内相互连接的神经元。
- 在神经科学社区中,递归网络是一个连通性丰富的网络,包括前馈、 和反馈 连接。
- 反馈连接适应了动物的能力和行为,这些能力和行为在缺乏这种连接的深度学习模型中可能无法复制。
深度学习人工神经网络中的递归
正如许多读者所知,深度学习网络是人工神经网络的子类型,其中神经元(或节点)被排列成层。在这样一个网络中,许多层的存在给了它一个主观的深度,这就是它的名字,与早期研究的这种类型的网络相比,只有一个或两个这样的层。在一个典型的全连接前馈深度学习网络中,给定层中的所有神经元都将它们的输出发送给紧随其后的层中的所有神经元(计算的方向流通常被示意为从下到上或从左到右在层之间进行)。
人们也可以设计这样的网络,其中给定层中的神经元将它们的输出发送到它的上一层,从而在层间引入反馈连接。我们稍后将回到这一点。
最后,一层神经元可以以完全连接(或其他)的方式将其输出发送回自身。存储在层中的信息在下一个时间/处理步骤中作为输入再次出现。这是深度学习实践者讨论时几乎总是指的那种递归类型——局限于一个层的递归。(注意,可能有多个递归层,但层间连接只是前馈。)
Unlike the feed-forward network on the right, the network on the left has a recurrent layer (the larger light blue circles) that “feeds back” onto itself. In deep learning parlance, the network is termed a recurrent network rather than a feed-back network because the feed-back does not project to a preceding layer. Note that although the recurrent neurons in the figure are depicted as connecting back to themselves individually, the typical arrangement is for all neurons in the recurrent layer to connect to all other neurons in that same layer.
这种循环连接的作用是在循环神经网络(RNN)中赋予记忆。网络的输出不再仅仅依赖于对齐的时间步长上的输入。相反,网络在任何给定的时间都有一个“状态”,它与下一个输入相结合,提供一个新的输出,并更新网络的状态。
这使得 rnn 能够识别或产生时间结构不同的模式,如语音[1]。例如,话语和都可以被识别为单词“sleep”。事实上,这种序列到序列网络[2]的设计和训练方法的重大进步是语音识别技术在过去 2-3 年中取得如此巨大进步的关键原因。Siri 和 Alexa 可能仍然像石头一样哑,但至少它们可以非常准确地将你的口语翻译成文本(尽管你可能不总是根据它们的反应知道这一点!).
文本的语言翻译是另一个非常成功的领域。递归的使用允许信息在编码阶段被累积,并在解码阶段被分发(跨时间输出),由此直接的单词到单词或短语到短语的对齐是不必要的[2]。例如,允许一种语言中单词前面的修饰语跟随在另一种语言中的单词后面,例如当将 red hat 翻译为 sombrero rojo 时。
The use of LSTMs, a type of RNN, allows for language translation networks with network memory that can accumulate information. Words (as vector representations) are incrementally input to the network, and the network distributes output words in a different language, with some delay. This is successful even when ordering of parts of speech (nouns, adjectives, etc.) is different between the two languages. [Image taken from The Keras Blog.]
我们不能不提到上面描述的“香草”RNN 架构在实践中很少使用。高级应用通常依赖于人类设计的适应门控机制的修改。在某种意义上,当接收到某个输入或传递某个输出时,这允许循环层的状态存储器被“转储”。打个比方,当你完成一个句子,以及相关的想法时,你可能希望把那个想法扔掉,这样它就不会和你的下一个想法混淆了。值得注意的是,最常见和最有效的门控层之一,长短期记忆 (LSTM)层最初创建于 1997 年[3],远远早于 RNN 应用的最新进展。参见 Christopher Olah 的博客文章中关于 LSTMs 的精彩教程。
生物神经网络中的递归
在神经科学家中,递归有一个更宽泛的定义——部分基于生物神经网络(BNNs)中神经元之间近乎各向同性的连接模式。神经元在向其他神经元的轴突投射中是多产的,向前和向后,短距离和长距离地发送它们。虽然有强有力的证据表明在结构和功能上存在粗糙的层次排列[4],但大脑皮层显然没有排列成神经元的有限层(组)。大脑作为一个整体具有不同的区域,具有不同类型的神经元和神经递质,但不像作为深度学习人工神经网络的定义特征的划分连接。尽管如此,深度学习实践者所谓的循环连接更有可能被神经科学家称为横向连接。
计算神经科学家已经深入研究的递归网络的一个方面是所谓的吸引子网络的模式完成属性。想一想,在我们自己的头脑中,可能只需要短暂的一瞥、短暂的一阵声音或一点点气味就能带来强烈的、充满活力的记忆。或者当我们试图回忆一个男演员或女演员的名字时,我们会想象他们的脸,想到他们合作过的其他演员的名字,电影名称等等。直到他们的名字突然神奇地出现在我们的脑海中。在循环吸引子网络(一种人工神经网络,但没有深度学习结构,并且通常具有抑制性和兴奋性人工神经元,旨在成为 BNNs 的更现实的模型)的模拟中观察到了这种现象的类比。例如,由一张脸的图像驱动的神经活动模式也可能由同一张脸的模糊或嘈杂的图像驱动,尽管在后一种情况下,网络的动态需要更长时间才能进化到稳定状态。
The energy landscape of a Hopfield attractor network. Sensory information may briefly position the network activity in an unstable, partial-information state, from which it dynamically moves (adjusts neuron firing rates) to a stable state that represents a fully-remembered object, sensation, abstract idea, etc. In this case, “memory” is really the strength and pattern of the synaptic connections between neurons, and recall of that memory is the neuronal firing pattern that ensues when external or internal stimuli push the network beyond the edge of the memory’s attractor basin (like a drop of rain that eventually flows to one of many possible lakes or oceans). See Jack Terwilliger’s blog post for more detail.
*比深度学习 ann 的受限递归(层内)与 bnn 的广泛递归之间的区别更重要的是,大多数深度学习模型中缺乏反馈连通性。*在神经科学界,术语“复发”几乎是反馈和前馈连接的同义词,最近的研究为反馈的作用提供了新的证据。
生物网络中循环和反馈连接的可能功能:
- **迭代感觉处理:**循环处理,其中自下而上和自上而下的信息流相互作用以确定一个稳定的结果。关于这个主题的更深入的讨论,请参见下一节。
- **长期记忆:**不完整的信息可以在吸引子网络中从长期存储中启动对记忆的回忆(如上所述)。
- **短期记忆:**短期记忆,即需要记住一小段数字序列或几个句子内容的那种记忆,可能由神经元维持,这些神经元共同产生一个稳定的(但可能是动态的)放电模式,有点像吸引子,只是维持一个新的短期记忆,而不是回忆一个存储的长期记忆。该功能与上述序列到序列深度学习 RNNs 的功能相关(例如,允许语音识别和语言翻译)。
- **自上而下的目标驱动注意力:**基于一个有机体手头的任务和相关的目标,并不是所有的感官信息都同样有价值。一只寻找它最喜欢的红色浆果的动物可能有反馈连接,可以增强对红光做出反应的低级神经元的活动,同时降低对其他颜色做出反应的神经元的活动。这个过程的神经模型利用了深度学习社区的工作[5]。
- **可塑性:**递归也是生物大脑学习机制的重要组成部分。例如,皮质下基底核中的多巴胺释放神经元是由皮质和皮质下区域组成的复杂网络的一部分,最终可以增强皮质区域的可塑性,以响应导致奖励的行为(食物、交配等)。),从而强化了那种行为。这种类型的神经元和网络复杂性在最先进的深度学习中几乎完全不存在。
- **门控:**推测上,反馈也可能作为门控机制,控制信息从较低级神经元向较高级神经元的流动。注意力可能会选择这样的门控,但这里我们指的是不由有机体的意识感知和目标驱动的门控。例如,众所周知,关于物体身份的视觉信息沿着从枕叶皮层到下颞叶皮层的路径被提取和提炼。相反,对象位置信息是沿着从枕叶皮层到顶叶皮层的路径提取和提炼的。(注意这是一个过于简单化的描述。)门控可以帮助指导这种信息路由,并且可以是支持在该列表顶部讨论的迭代感觉处理的机制。
迭代感觉处理
我们将简要强调 BNNs 中递归/反馈连接的迭代感觉处理作用,并将其与深度学习 ann 中主导图像分类任务的前馈卷积神经网络(CNN)进行对比。
深度学习对象(图像)识别模型在该领域取得了巨大成功,自第一个赢得 ImageNet 大规模视觉识别挑战赛(ILSVRC)的 CNN 模型“Alex net”[6]发表以来,该领域发展迅速。想要一个好的教程,请看这篇博文,或者许多其他的。因为视觉皮层是哺乳动物皮层中研究得最充分的区域,所以在深度学习 CNN 和哺乳动物视觉之间进行了许多主观和定量的比较。
早期的视觉神经科学模型,基于 Hubel 和 Weisel 等人对单个神经元的记录[7],与标准的 CNN 相似,它们具有卷积、汇集和专门的前馈连接[8,9]。完全前馈的功能模型的部分动机是视觉感知发生迅速,大约 100 毫秒。这一估计是基于大脑“较高”区域的神经放电时间,相对于向实验室动物展示图像的时刻。基于解剖学,视觉皮层通常被建模为具有大量反馈连接的 4-6 级松散层级。尽管存在反馈连接,但更高级别的神经反应的快速性表明反馈连接并不完全必要(对于简单的物体识别任务)。如果不是这样,在这些区域形成稳定的反应将会更慢,因为反馈回路的贡献传播需要更多的时间。
然而,在具有挑战性的 ILSVRC 测试集上,CNN 需要几十层(如果不是几百层)才能实现良好的图像分类性能,这与仅由几个前馈层组成的视觉皮层模型相反。此外,在一些计算研究中,相对较浅的 rnn 的性能与非常深的 CNN 相当[10,11]。
Liao and Poggio [10] built a 4-level recurrent network meant to model the visual cortex. In this coarse model, visual input from the eye (via retina and thalamus) enters the primary visual cortex, V1. The network contains feed-forward connection (left-to-right), feed-back connections (right-to-left) and lateral connections (looping back to same area; synonymous with recurrent connections in deep learning terminology). Outputs from the inferotemporal area, IT, are used for object classification. They demonstrate that a shallow RNN is equivalent to a very deep ResNet model (a type of deep learning ANN) with weight sharing among the ResNet layers.
最近,世界一流实验室的两项神经科学研究,以及对生物循环连接的时间延迟的更细致入微的理解,表明需要循环来捕捉人类视觉皮层的动态计算[12],并且循环对视觉皮层执行物体识别行为至关重要[13]。简而言之,证据表明,如果不通过递归网络进行多次迭代,更具“挑战性”的物体图像实例就无法被识别。换句话说,需要额外的非线性变换来成功地识别挑战案例中的对象。
最后的话
如上所述,虽然递归深度学习 ANN 模型具有层内递归(神经科学术语中的“横向”连接),但很少具有神经科学家通常研究的反馈连接类型——即从较高层到较低层的连接。值得注意的例外包括模拟注意力的人工神经网络和一些图像分类模型。
具有反馈连接性的深度学习模型几乎不存在的一个原因是训练这种模型的难度。我们可能需要新的学习规则(除反向传播之外的方法)来实现反馈在 BNNs 中提供的功能类型。
与之相关的是,生物神经元并行工作,因此大规模循环网络中的计算可以快速进行。事实上,神经元状态的同时计算更新可能是成功的关键。对于在现代硬件上运行的大型、高重现性(神经科学术语)人工神经网络来说,这种程度的并行性可能很难或不可能实现。
我们推测,将重反馈递归引入深度学习模型,并开发这种模型的训练方法,将带来强大的 now AI 能力。然而,这些进展的速度很难预测。
参考
- 格雷夫斯(2012)。"神经网络的序列转换."https://arxiv.org/abs/1211.3711
- Sutskever、Vinyals 和 Le (2014 年)。“用神经网络进行序列对序列学习.” NIPS 2014 。【https://arxiv.org/abs/1409.3215
- Hochreiter 和 Schmidhuber (1997 年)。“长短期记忆。”神经计算。https://www . mitpressjournals . org/doi/ABS/10.1162/neco . 1997 . 9 . 8 . 1735
- 克拉维茨等人。(2013)."腹侧视觉通路:处理物体质量的扩展神经框架."趋势认知科学。https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3532569/
- 亚明斯和迪卡洛(2016)。“使用目标驱动的深度学习模型来理解感觉皮层。”自然神经科学。https://www.nature.com/articles/nn.4244
- Krizhevky、Sustskever 和 Hinton (2012 年)。“使用深度卷积神经网络的 ImageNet 分类” NIPS 2012。http://papers . nips . cc/paper/4824-imagenet-class ification-with-deep-convolutionary-neural-networking
- 胡贝尔和威塞尔(1959)。"猫纹状皮层中单个神经元的感受野."生理学博士。https://phys oc . online library . Wiley . com/doi/pdf/10.1113/jphysiol . 1959 . sp 006308
- 福岛(1980 年)。“Neocognitron。不受位置变化影响的模式识别机制的自组织神经网络模型*生物控制论。*https://www.rctn.org/bruno/public/papers/Fukushima1980.pdf
- Riesenhuber 和 Poggio (1999 年)。"大脑皮层中物体识别的层次模型."性质。https://www.nature.com/articles/nn1199_1019
- 廖和波焦(2016)。"弥合剩余学习、循环神经网络和视觉皮层之间的差距."CBMM 备忘录 047 。https://arxiv.org/abs/1604.03640
- 扎米尔等人。(2016).“反馈网络。”IEEE 计算机视觉和模式识别会议(CVPR)。https://arxiv.org/pdf/1612.09508.pdf
- Kietzmann,等人。(2019)."捕捉人类腹部视觉流的动态计算所需的递归."https://arxiv.org/abs/1903.05946
- 卡尔等人 (2019)。"证明循环回路对腹侧流执行核心物体识别行为至关重要."自然神经科学。https://www.nature.com/articles/s41593-019-0392-5