46向量空间:如何实现一个简单的音乐推荐系统

首先,该文章来自于极客时间网站,王争的专栏——《数据结构与算法之美》,我这里只是做简单的解释、记录并添加自己的见解,只是作为个人笔记,若侵权,马上删除。最后建议直接去该网站上购买该课程看原作者的讲解,一来是支持作者,二来是作者写的确实不错。

现在的听歌软件都会根据你听歌的偏好给你推荐歌曲,那么这个功能该如何实现呢?

算法解析

这个问题的解决思路核心很简单、直白:

  • 找到跟你口味偏好相似的用户,把他们爱听的歌曲推荐给你;
  • 找出跟你喜爱的歌曲特征相似的歌曲,把这些歌曲推荐给你。

下面分别讲解一下这两种思路的具体实现方法。

基于相似用户做推荐

如何找到相似用户呢?如下所示,用“1”表示“喜爱”,用“0”笼统地表示“不发表意见”。你和小明共同喜爱的歌曲最多,有 5 首。于是可以说,小明跟你的口味非常相似。

img

我们只需要遍历所有用户,对比每个用户跟你共同喜爱的歌曲个数,若这个个数高于阈值,则这个用户作为你的相似用户,将其喜爱听但你还没听的歌曲推荐给你。

不过,如何定义用户对某首歌曲的喜爱程度呢?这个可以根据用户的行为,定义这个喜爱程度,如下所示,对每个行为定义一个得分,得分越高表示喜爱程度越高。

img

对于刚才那个例子,不再使用”1“或者”0“表示某个人堆某首歌曲的喜爱,而是使用具体的分值。

img

有了这个表,就不能采用简单的计数统计两个用户之间的相似度。之前讲到字符串相似度度量时,使用的是编辑距离。而这里的相似度度量,可以用另一个距离——欧几里得距离(Euclidean distance),它是用来度量两个向量之间的距离的。

类比一维、二维、三维中某个位置的表示方法,K维空间的某个位置,可以写作$(X_1,X_2,X_3,…,X_K)$,这种表示方法就是向量(vector)。低维空间中两个位置有距离的概念,同样高维空间也有距离的概念,这就是两个向量的距离

类比低维空间距离的计算方式,可以得到两个向量之间距离的计算方式——欧几里得距离的计算公式:

img

每个用户对所有歌曲的喜爱程度,都可以用一个向量表示。两个向量之间的欧几里得距离,作为两个用户的口味相似程度的度量。如下,小明与你的的欧几里得距离最小,所以你们两个口味最相似。

img

基于相似歌曲做推荐

若用户是一个新用户,没有搜集到足够多的行为数据,基于相似用户的推荐算法就无法生效了。这时就需要用到基于相似歌曲做推荐。但是如何判断两首歌曲是否相似呢?

最容易想到是,对歌曲定义一些特征项,比如是伤感的还是愉快的,是摇滚还是民谣等等。类似基于相似用户的推荐方法,给每个歌曲的所有特征项打一个分数,这样每个歌曲就都对应一个特征项向量。基于这个特征项向量,来计算两个歌曲之间的欧几里得距离。欧几里得距离越小,表示两个歌曲的相似程度越大。

但是这个方案实现需要有几个前提:

  • 能够找到足够多,并且能够全面代表歌曲特点的特征项,这是一个庞大的工程。
  • 要人工给每首歌标注每个特征项的得分,这个人工标注也有很大主观性,影响到推荐的准确性。

既然基于歌曲特征项计算相似度不可行,那就换一种思路。对于两首歌,如果喜欢听的人群都是差不多的,那侧面就可以反映出,这两首歌比较相似。如下所示,每个用户对歌曲有不同的喜爱程度:

img

实际上,这个图跟基于相似用户推荐中的图几乎一样。只不过这里把歌曲和用户主次颠倒了一下。基于相似用户的推荐方法中,针对每个用户,我们将对各个歌曲的喜爱程度作为向量。基于相似歌曲的推荐思路中,针对每个歌曲,我们将每个用户的打分作为向量。

有了每个歌曲的向量表示,通过计算向量之间的欧几里得距离,来表示歌曲之间的相似度。欧几里得距离越小,表示两个歌曲越相似。

总结引申

实际上,这个问题是推荐系统(Recommendation System)里最典型的一类问题。

这节算法主要展示了算法的强大之处,利用简单的向量空间的欧几里得距离,就能解决如此复杂的问题。

------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道