摘要
互联网和信息计算的快速发展,衍生了海量的数据,我们已经进入了一个信息爆炸的时代,每时每刻都有海量信息产生,然而这些信息并不全是个人所关心的,用户从大量的信息中寻找对自己有用的信息也变得越来越困难。另一方面,信息的生产方也在绞尽脑汁的把用户感兴趣的信息送到用户面前,每个人的兴趣又不尽相同,所以可以实现千人千面的推荐系统应运而生。简单来说,推荐系统是根据用户的浏览习惯,确定用户的兴趣,通过发掘用户的行为,将合适的信息推荐给用户,满足用户的个性化需求,帮助用户找到对他胃口但是不易找到的信息或商品。
推荐系统在互联网和传统行业中都有着大量的应用。在互联网行业,几乎所有的互联网平台都应用了推荐系统,如资讯新闻/影视剧/知识社区的内容推荐、电商平台的商品推荐等;在传统行业中,有些用于企业的营销环节,如银行的金融产品推荐、保险公司的保险产品推荐等。根据QM报告,以推荐系统技术为核心的短视频行业在2019年的用户规模已超8.2亿,市场规模达2千亿,由此可见这项技术在现代社会的经济价值。
推荐系统的目标
随着现代工业和互联网的兴起,长尾经济变得越来越流行。在男耕女织的农业时代,人们以“个性化”的模式生产“个性化”的产品;在流水线模式的工业化时代,人们以“规模化”的模式生产“标准化”的产品;而在互联网和智能制造业不断发展的今天,人们以“规模化”的模式生产“个性化”的产品,极大地丰富了商品种类。在此情况下,用户的注意力和消费力变成极为匮乏的资源。如何从海量的产品和服务中选择自己需要的,成为用户第一关心的事,这就是推荐系统的价值所在。但每个人的喜好极具个性化,例如年轻人偏爱健身的内容,而父母一代偏爱做菜的内容,如果推荐内容相反,用户会非常不满。正所谓此之甘露,彼之砒霜,基于个性化需求进行推荐是推荐系统的关键目标。
推荐系统的基本概念
构建推荐系统本质上是要解决“5W”的问题。如下图示例,当用户在晚间上网阅读军事小说时,系统在小说的底部向他推荐三国志游戏,并给出了推荐理由“纸上谈兵不如亲身实践”。
哪些信息可以用于推荐
观察只保留两个核心问题的推荐任务示例,思考有哪些信息可以用于推荐? 图中蕴含的数据可以分为三种:
- 每个用户的不同特征,如性别、年龄;
- 物品的各种描述属性,如品牌、品类;
- 用户对部分物品的兴趣表达,即用户与物品的关联数据,如历史上的评分、评价、点击行为和购买行为。
结合这三种信息可以形成类似“女性A 喜欢 LV包”这样的表达。
基于3的关联信息,人们设计了“协同过滤的推荐算法”。基于2的内容信息,设计出“基于内容的推荐算法”。现在的推荐系统普遍同时利用这三种信息,下面我们就来看看这些方法的原理。
常用的推荐系统算法
常用的推荐系统算法实现方案有三种:
协同过滤推荐(Collaborative Filtering Recommendation)
该算法的核心是分析用户的兴趣和行为,利用共同行为习惯的群体有相似喜好的原则,推荐用户感兴趣的信息。兴趣有高有低,算法会根据用户对信息的反馈(如评分)进行排序,这种方式在学术上称为协同过滤。协同过滤算法是经典的推荐算法,经典意味着简单、好用。协同过滤算法又可以简单分为两种:
基于用户的协同过滤:
根据用户的历史喜好分析出相似兴趣的人,然后给用户推荐其他人喜欢的物品。假如小李,小张对物品A、B都给了十分好评,那么可以认为小李、小张具有相似的兴趣爱好,如果小李给物品C十分好评,那么可以把C推荐给小张,可简单理解为“人以类聚”。
基于物品的协同过滤:
根据用户的历史喜好分析出相似物品,然后给用户推荐同类物品。比如小李对物品A、B、C给了十分好评,小王对物品A、C给了十分好评,从这些用户的喜好中分析出喜欢A的人都喜欢C,物品A、C是相似的,如果小张给了A好评,那么可以把C也推荐给小张,可简单理解为“物以群分”。
基于内容过滤推荐(Content-based Filtering Recommendation)
基于内容的过滤是信息检索领域的重要研究内容,是更为简单直接的算法,该算法的核心是衡量出两个物品的相似度。首先对物品或内容的特征作出描述,发现其相关性,然后基于用户以往的喜好记录,推荐给用户相似的物品。比如,小张对物品A感兴趣,而物品A和物品C是同类物品(从物品的内容描述上判断),可以把物品C也推荐给小张。
组合推荐(Hybrid Recommendation)
以上算法各有优缺点,比如基于内容的过滤推荐是基于物品建模,在系统启动初期往往有较好的推荐效果,但是没有考虑用户群体的关联属性;协同过滤推荐考虑了用户群体喜好信息,可以推荐内容上不相似的新物品,发现用户潜在的兴趣偏好,但是这依赖于足够多且准确的用户历史信息。所以,实际应用中往往不只采用某一种推荐方法,而是通过一定的组合方法将多个算法混合在一起,以实现更好的推荐效果,比如加权混合、分层混合等。具体选择哪种方式和应用场景有很大关系。
如何实现推荐
如何根据上述数据实现推荐系统呢?首先思考下,实现推荐系统究竟需要什么?
如果能将用户A的原始特征转变成一种代表用户A喜好的特征向量,将电影1的原始特征转变成一种代表电影1特性的特征向量。那么,我们计算两个向量的相似度,就可以代表用户A对电影1的喜欢程度。据此,推荐系统可以如此构建:
这样设计的核心是两个特征向量的有效性,它们会决定推荐的效果。
如何获得有效特征
如何获取两种有效代表用户和电影的特征向量?首先,需要明确什么是“有效”?
对于用户评分较高的电影,电影的特征向量和用户的特征向量应该高度相似,反之则相异。
我们已经获得大量评分样本,因此可以构建一个训练模型如下图所示,根据用户对电影的评分样本,学习出用户特征向量和电影特征向量的计算方案(灰色箭头)。
- 第一层结构:特征变换,原始特征集合变换为两个特征向量。
- 第二层结构:计算向量相似度。(计算相似度是代表两个向量的之间的相似程度为多少?)为确保结果与电影评分可比较,两个特征向量的相似度从【0~1】缩放5倍到【0~5】。
- 第三层结构:计算Loss,计算缩放后的相似度与用户对电影的真实评分的“均方误差”。
以在训练样本上的Loss最小化为目标,即可学习出模型的网络参数,这些网络参数本质上就是从原始特征集合到特征向量的计算方法,如灰色箭头所示。根据训练好的网络,我们可以计算任意用户和电影向量的相似度,进一步完成推荐。
从原始特征到特征向量之间的网络如何设计?
将每个原始特征转变成Embedding表示,再合并成一个用户特征向量和一个电影特征向量。计算两个特征向量的相似度后,再与训练样本(已知的用户对电影的评分)做损失计算。
但不同类型的原始特征应该如何变换?有哪些网络设计细节需要考虑?我们将在后续几节结合代码实现逐一探讨,包括四个小节:
- 数据处理,将MovieLens的数据处理成神经网络理解的形式。
- 模型设计,设计神经网络模型,将离散的文字数据映射为向量。
- 配置训练参数并完成训练,提取并保存训练后的数据特征。
- 利用保存的特征构建相似度矩阵完成推荐。
模型设计介绍
神经网络模型设计是电影推荐任务中重要的一环。它的作用是提取图像、文本或者语音的特征,利用这些特征完成分类、检测、文本分析等任务。在电影推荐任务中,我们将设计一个神经网络模型,提取用户数据、电影数据的特征向量,然后计算这些向量的相似度,利用相似度的大小去完成推荐。
神经网络模型的设计包含如下步骤:
- 分别将用户、电影的多个特征数据转换成特征向量。
- 对这些特征向量,使用全连接层或者卷积层进一步提取特征。
- 将用户、电影多个数据的特征向量融合成一个向量表示,方便进行相似度计算。
- 计算特征之间的相似度。
依据这个思路,我们设计一个简单的电影推荐神经网络模型:
该网络结构包含如下内容:
- 提取用户特征和电影特征作为神经网络的输入,其中:
- 用户特征包含四个属性信息,分别是用户ID、性别、职业和年龄。
- 电影特征包含三个属性信息,分别是电影ID、电影类型和电影名称。
- 提取用户特征。使用Embedding层将用户ID映射为向量表示,输入全连接层,并对其他三个属性也做类似的处理。然后将四个属性的特征分别全连接并相加。
- 提取电影特征。将电影ID和电影类型映射为向量表示,输入全连接层,电影名字用文本卷积神经网络得到其定长向量表示。然后将三个属性的特征表示分别全连接并相加。
- 得到用户和电影的向量表示后,计算二者的余弦相似度。最后,用该相似度和用户真实评分的均方差作为该回归模型的损失函数。
衡量相似度的计算有多种方式,比如计算余弦相似度、皮尔森相关系数、Jaccard相似系数等等,或者通过计算欧几里得距离、曼哈顿距离、明可夫斯基距离等方式计算相似度。余弦相似度是一种简单好用的向量相似度计算方式,通过计算向量之间的夹角余弦值来评估他们的相似度,本节我们使用余弦相似度计算特征之间的相似度。在不同的场景下使用的不懂的有利于的完成更好的推荐的功能,这个科研工作的一个热点方向。
为何如此设计网络呢?
- 如何将“数字”转变成“向量”?
如NLP章节的介绍,使用词嵌入(Embedding)的方式可将数字转变成向量。 - 如何合并多个向量的信息?例如:如何将用户四个特征(ID、性别、年龄、职业)的向量合并成一个向量?
最简单的方式是先将不同特征向量(ID 32维、性别 16维、年龄 16维、职业 16维)通过4个全连接层映射到4个等长的向量(200维度),再将4个等长的向量按位相加即可得到1个包含全部信息的向量。这个涉及的到数据矩阵的升维的操作,同时这个涉及的矩阵轮的相关知识需要自行补充。
电影类型的特征是将多个数字(代表出现的单词)转变成的多个向量(6个),可以通过相同的方式合并成1个向量。 - 如何处理文本信息?
如NLP章节的介绍,使用卷积神经网络(CNN)和长短记忆神经网络(LSTM 处理的是简单的文本信息,但是如果是复杂文本信息呢?需要用什么网络处理?)处理文本信息会有较好的效果。因为电影标题是相对简单的短文本,所以我们使用卷积网络结构来处理电影标题。 - 尺寸大小应该如何设计? 这涉及到信息熵的理念:越丰富的信息,维度越高。所以,信息量较少的原始特征可以用更短的向量表示,例如性别、年龄和职业这三个特征向量均设置成16维,而用户ID和电影ID这样较多信息量的特征设置成32维。综合了4个原始用户特征的向量和综合了3个电影特征的向量均设计成200维度,使得它们可以蕴含更丰富的信息。当然,尺寸大小并没有一贯的最优规律,需要我们根据问题的复杂程度,训练样本量,特征的信息量等多方面信息探索出最有效的设计。(矩阵设计成为多少维度这个是没有固定的计算方法,需要依据问题的复杂程度,训练样本量,特征的信息量等多方面信息探索出最有效的设计)
Embedding介绍
原理为:实际上,Embedding层和Conv2D, Linear层一样,Embedding层也有可学习的权重,通过矩阵相乘的方法对输入数据进行映射。Embedding中将输入映射成向量的实际步骤是:
- 将输入数据转换成one-hot格式的向量;
- one-hot向量和Embedding层的权重进行矩阵相乘得到Embedding的结果。
Embedding是一个嵌入层,将输入的非负整数矩阵中的每个数值,转换为具有固定长度的向量。
使用Embedding时,需要注意num_embeddings
和embedding_dim
这两个参数。num_embeddings
表示词表大小;embedding_dim
表示Embedding层维度。
下面展示了另一个使用Embedding函数的案例。该案例从0到9的10个ID数字中随机取出了3个,查看使用默认初始化方式的Embedding结果,再查看使用KaimingNormal(0均值的正态分布)初始化方式的Embedding结果。实际上,无论使用哪种参数初始化的方式,这些参数都是要在后续的训练过程中优化的,只是更符合任务场景的初始化方式可以使训练更快收敛,部分场景可以取得略好的模型精度。
上面代码中,我们在[0, 10]范围内随机产生了3个整数,因此数据的最大值为整数9,最小为0。因此,输入数据映射为每个one-hot向量的维度是10,定义Embedding权重的第一个维度USR_ID_NUM为10。
这里输入的数据shape是[3, 1],Embedding层的权重形状则是[10, 16],Embedding在计算时,首先将输入数据转换成one-hot向量,one-hot向量的长度和Embedding层的输入参数size的第一个维度有关。比如这里我们设置的是10,所以输入数据将被转换成维度为[3, 10]的one-hot向量,参数size决定了Embedding层的权重形状。最终维度为[3, 10]的one-hot向量与维度为[10, 16]Embedding权重相乘,得到最终维度为[3, 16]的映射向量。我们也可以对Embeding层的权重进行初始化,如果不设置初始化方式,则采用默认的初始化方式。
神经网络处理文本数据时,需要用数字代替文本,Embedding层则是将输入数字数据映射成了高维向量,然后就可以使用卷积、全连接、LSTM等网络层处理数据了,接下来我们开始设计用户和电影数据的特征提取网络。
提供用户特征
用户特征网络主要包括:
- 将用户ID数据映射为向量表示,通过全连接层得到ID特征。
- 将用户性别数据映射为向量表示,通过全连接层得到性别特征。
- 将用户职业数据映射为向量表示,通过全连接层得到职业特征。
- 将用户年龄数据影射为向量表示,通过全连接层得到年龄特征。
- 融合ID、性别、职业、年龄特征,得到用户的特征表示。
在用户特征计算网络中,我们对每个用户数据做embedding处理,然后经过一个全连接层,激活函数使用ReLU,得到用户所有特征后,将特征整合,经过一个全连接层得到最终的用户数据特征,该特征的维度是200维,用于和电影特征计算相似度。
开始构建用户ID的特征提取网络,ID特征提取包括两个部分。首先,使用Embedding将用户ID映射为向量;然后,使用一层全连接层和ReLU激活函数进一步提取用户ID特征。 相比较电影类别和电影名称,用户ID只包含一个数字,数据更为简单。这里需要考虑将用户ID映射为多少维度的向量合适,使用维度过大的向量表示用户ID容易造成信息冗余,维度过低又不足以表示该用户的特征。理论上来说,如果使用二进制表示用户ID,用户最大ID是6040,小于2的13次方,因此,理论上使用13维度的向量已经足够了,为了让不同ID的向量更具区分性,我们选择将用户ID映射为维度为32维的向量。
1. 提取用户ID特征
注意到,将用户ID映射为one-hot向量时,Embedding层参数size的第一个参数是,在用户的最大ID基础上加上1。原因很简单,从上一节数据处理已经发现,用户ID是从1开始计数的,最大的用户ID是6040。并且已经知道通过Embedding映射输入数据时,是先把输入数据转换成one-hot向量。向量中只有一个 1 的向量才被称为one-hot向量,比如,0 用四维的on-hot向量表示是[1, 0 ,0 ,0],同时,4维的one-hot向量最大只能表示3。所以,要把数字6040用one-hot向量表示,至少需要用6041维度的向量。
融合用户特征
特征融合是一种常用的特征增强手段,通过结合不同特征的长处,达到取长补短的目的。简单的融合方法有:特征(加权)相加、特征级联、特征正交等等。此处使用特征融合是为了将用户的多个特征融合到一起,用单个向量表示每个用户,更方便计算用户与电影的相似度。上文使用Embedding加全连接的方法,分别得到了用户ID、年龄、性别、职业的特征向量,可以使用全连接层将每个特征映射到固定长度,然后进行相加,得到融合特征。
这里使用全连接层进一步提取特征,而不是直接相加得到用户特征的原因有两点:
- 一是用户每个特征数据维度不一致,无法直接相加;
- 二是用户每个特征仅使用了一层全连接层,提取特征不充分,多使用一层全连接层能进一步提取特征。而且,这里用高维度(200维)的向量表示用户特征,能包含更多的信息,每个用户特征之间的区分也更明显。
上述实现中需要对每个特征都使用一个全连接层,实现较为复杂,一种简单的替换方式是,先将每个用户特征沿着长度维度进行级联,然后使用一个全连接层获得整个用户特征向量,两种方式的对比见下图:
相似度计算
计算得到用户特征和电影特征后,我们还需要计算特征之间的相似度。如果一个用户对某个电影很感兴趣,并给了五分评价,那么该用户和电影特征之间的相似度是很高的。
衡量向量距离(相似度)有多种方案:欧式距离、曼哈顿距离、切比雪夫距离、余弦相似度等,本节我们使用忽略尺度信息的余弦相似度构建相似度矩阵。余弦相似度又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度,如下图,两条红色的直线表示两个向量,之间的夹角可以用来表示相似度大小,角度为0时,余弦值为1,表示完全相似。