书名:推荐系统实践 作者:项亮
链接:微信读书链接
文章目录
自从Netflix Prize比赛举办以来,LFM(latent factor model)隐语义模型逐渐成为推荐系统领域耳熟能详的名词。其实该算法最早在文本挖掘领域被提出,用于找到文本的隐含语义。相关的名词有LSI、pLSA、LDA和Topic Model。本节将对隐含语义模型在Top-N推荐中的应用进行详细介绍,并通过实际的数据评测该模型。
基础算法
隐语义模型的核心是用过隐含特诊联系用户兴趣和物品
有两个用户,A的兴趣涉及侦探小说、科普图书以及一些计算机技术书籍,B的兴趣比较集中在数学和机器学习方面。
那么如何给A和B推荐图书呢?
- 对于UserCF,首先需要找到和他们看了同样书的其他用户(兴趣相似的用户),然后给他们推荐那些用户喜欢的其他书。
- 对于ItemCF,需要给他们推荐和他们已经看的书相似的书,比如作者B看了很多关于数据挖掘的书,可以给他推荐机器学习或者模式识别方面的书。
- 还有一种方法,可以对书和物品的兴趣进行分类。对于某个用户,首先得到他的兴趣分类,然后从分类中挑选他可能喜欢的物品。
即这三种方法需要解决3个问题:
- 如何给商品进行分类
- 如何确定用户对这哪些类的物品感兴趣,以及感兴趣的程度?
- 对于一个给定的类,选择哪些属于这个类的商品推荐给用户,以及如何确定这些物品在一个类中的权重?
对于第一个问题的简单解决方案是找编辑给物品分类。以图书为例,每本书出版时,编辑都会给书一个分类。为了给图书分类,出版界普遍遵循中国图书分类法。但是,即使有很系统的分类体系,编辑给出的分类仍然具有以下缺点。
- 编辑的意见不能代表各种用户的意见。 比如,对于《具体数学》应该属于什么分类,有人认为应该属于数学,有些人认为应该属于计算机。从内容看,这本书是关于数学的,但从用户看,这本书的读者大部分是做计算机出身的。编辑的分类大部分是从书的内容出发,而不是从书的读者群出发。
- 编辑很难控制分类的粒度。 我们知道分类是有不同粒度的,《数据挖掘导论》在粗粒度的分类中可能属于计算机技术,但在细粒度的分类中可能属于数据挖掘。对于不同的用户,我们可能需要不同的粒度。比如对于一位初学者,我们粗粒度地给他做推荐就可以了,而对于一名资深研究人员,我们就需要深入到他的很细分的领域给他做个性化推荐。
- 编辑很难给一个物品多个分类。 有的书不仅属于一个类,而是可能属于很多的类。
- 编辑很难给出多维度的分类。 我们知道,分类是可以有很多维度的,比如按照作者分类、按照译者分类、按照出版社分类。比如不同的用户看《具体数学》原因可能不同,有些人是因为它是数学方面的书所以才看的,而有些人是因为它是大师Knuth的著作所以才去看,因此在不同人的眼中这本书属于不同的分类。
- 编辑很难决定一个物品在某一个分类中的权重。 比如编辑可以很容易地决定《数据挖掘导论》属于数据挖掘类图书,但这本书在这类书中的定位是什么样的,编辑就很难给出一个准确的数字来表示。
所以为了解决这个问题,从数据出发,采用用户行为统计的自动聚类,较好地解决了上面提出的5个问题;
- 编辑的意见不能代表各种用户的意见,但隐含语义分析是来自用户行为的统计,代表用户对物品的看法。隐含语义分析技术和ItemCF在物品分类方面的思想类似,如果两个物品被很多用户同时喜欢,那么这两个物品就很有可能属于同一个类。
- 编辑很难控制分类的粒度,但隐含语义分析技术允许我们指定最终有多少个分类,这个数字越大,分类的粒度就会越细,反之分类粒度就越粗。
- 编辑很难给一个物品多个分类,但隐含语义分析技术会计算出物品属于每个类的权重,因此每个物品都不是硬性地被分到某一个类中。
- 编辑很难决定一个物品在某一个分类中的权重,但隐含语义分析技术可以通过统计用户行为决定物品在每个类中的权重,如果喜欢某个类的用户都会喜欢某个物品,那么这个物品在这个类中的权重就可能比较高。
隐含语义分析技术从诞生到今天产生了很多著名的模型和方法,其中和该技术相关且耳熟能详的名词有pLSA、LDA、隐含类别模型(latent class model)、隐含主题模型(latent topic model)、矩阵分解(matrix factorization)。这些技术和方法在本质上是相通的,其中很多方法都可以用于个性化推荐系统。本章将以LFM为例介绍隐含语义分析技术在推荐系统中的应用。
LFM通过如下公式计算用户u对物品i的兴趣:
P
r
e
f
e
r
e
n
c
e
(
u
,
i
)
=
r
u
i
=
p
u
T
q
i
=
∑
f
=
1
F
p
u
,
k
q
i
,
k
Preference(u,i)=r_{ui}=p_u^Tq_i=\sum_{f=1}^F{p_{u,k}q_{i,k}}
Preference(u,i)=rui=puTqi=f=1∑Fpu,kqi,k
这个公式中pu,k 和qi,k 是模型的参数,其中pu,k 度量了用户u的兴趣和第k个隐类的关系,而qi,k度量了第k个隐类和物品i之间的关系。那么,下面的问题就是如何计算这两个参数。
要计算这两个参数,需要一个训练集,对于每个用户u,训练集里都包含了用户u喜欢的物品和不感兴趣的物品,通过学习这个数据集,就可以获得上面的模型参数。
在选择不感兴趣的样本中,遵循与正样本数据相似,选取哪些很热门,而用户确没有行为的物品。
下面的Python代码实现了负样本采样过程:
def RandomSelectNegativeSample(self, items):
ret = dict()
for i in items.keys():
ret[i] = 1
n = 0
for i in range(0, len(items) * 3):
item = items_pool[random.randint(0, len(items_pool) -1)]
if item in ret:
continue
ret[item] = 0
n + = 1
if n > len(items):
break
return ret
在上面的代码中,items_pool维护了候选物品的列表,在这个列表中,物品i出现的次数和物品i的流行度成正比。items是一个dict,它维护了用户已经有过行为的物品的集合。因此,上面的代码按照物品的流行度采样出了那些热门的、但用户却没有过行为的物品。经过采样,可以得到一个用户—物品集K={( u, i)},其中如果(u, i)是正样本,则有ru i=1,否则有ru i=0。然后,需要优化如下的损失函数来找到最合适的参数p和q:
C
=
∑
(
u
,
i
)
∈
K
(
r
u
i
−
r
u
i
^
)
2
=
∑
(
u
,
i
)
∈
K
(
r
u
i
−
∑
k
=
1
K
p
u
,
k
q
i
,
k
)
2
+
λ
∣
∣
p
u
∣
∣
2
+
λ
∣
∣
q
i
∣
∣
2
C=\sum_{(u,i) \in K}{(r _{ui}- \hat{r_{ui}})^2} = \sum_{(u,i)\in K}{(r_{ui}- \sum_{k=1}^{K}{p_{u,k}q_{i,k}})^2}+\lambda ||p_u||^2+\lambda ||q_i||^2
C=(u,i)∈K∑(rui−rui^)2=(u,i)∈K∑(rui−k=1∑Kpu,kqi,k)2+λ∣∣pu∣∣2+λ∣∣qi∣∣2
λ可以通过实验获得。要最小化上面的损失函数,可以利用一种称为随机梯度下降法的算法。该算法是最优化理论里最基础的优化算法,它首先通过求参数的偏导数找到最速下降方向,然后通过迭代法不断地优化参数。下面介绍优化方法的数学推导。
上面定义的损失函数里有两组参数puk和qik,随机梯度下降法需要首先对它们分别求偏导数,可以得到:
然后,根据随机梯度下降法,需要将参数沿着最速下降方向向前推进,因此可以得到如下递推公式:
其中,α是学习速率(learning rate),它的选取需要通过反复实验获得。
def LatentFactorModel(user_items, F, N, alpha, lambda):
[P, Q] = InitModel(user_items, F)
for step in range(0, N):
for user, items in user_items.items():
samples = RandSelectNegativeSamples(items)
for item, rui in samples.items():
eui = rui - Predict(user, item)
for f in range(0, F):
P[user][f] += alpha * (eui * Q[item][f] - \
lambda * P[user][f])
Q[item][f] += alpha * (eui * P[user][f] - \
lambda * Q[item][f])
alpha *= 0.9
def Recommend(user, P, Q):
rank = dict()
for f, puf in P[user].items():
for i, qfi in Q[f].items():
if i not in rank:
rank[i] += puf * qfi
return rank
我们同样通过离线实验评测LFM的性能。首先,我们在MovieLens数据集上用LFM计算出用户兴趣向量p和物品向量q,然后对于每个隐类找出权重最大的物品。如表2-13所示,表中展示了4个隐类中排名最高(qik最大)的一些电影。结果表明,每一类的电影都是合理的,都代表了一类用户喜欢看的电影。从而说明LFM确实可以实现通过用户行为将物品聚类的功能。
其次,我们通过实验对比了LFM在TopN推荐中的性能。在LFM中,重要的参数有4个:
- 隐特征的个数F;
- 学习速率alpha;
- 正则化参数lambda;
- 负样本/正样本比例 ratio。
通过实验发现,ratio参数对LFM的性能影响最大。因此,固定F=100、alpha=0.02、lambda=0.01,然后研究负样本/正样本比例ratio对推荐结果性能的影响。
如表2-14所示,随着负样本数目的增加,LFM的准确率和召回率有明显提高。不过当ratio>10以后,准确率和召回率基本就比较稳定了。同时,随着负样本数目的增加,覆盖率不断降低,而推荐结果的流行度不断增加,说明ratio参数控制了推荐算法发掘长尾的能力。如果将LFM的结果与表2-6、表2-9、表2-10中ItemCF和UserCF算法的性能相比,可以发现LFM在所有指标上都优于UserCF和ItemCF。当然,这只是在MovieLens一个数据集上的结果,我们也发现,当数据集非常稀疏时,LFM的性能会明显下降,甚至不如UserCF和ItemCF的性能。关于这一点读者可以通过实验自己研究。