写点什么

歌曲推荐系统实践:Pandas、SciPy 和 D3.js

  • 2015-05-07
  • 本文字数:1997 字

    阅读完需:约 7 分钟

时至今日,虽然海量数据、大数据、数据挖掘、个性化等名词术语已耳熟能详,仿佛谁人两两遇到都可以轻易写个挖掘系统出来,但情况真的是这样么? Flipboard 数据产品部门的工程师 Ben Frederickson 在与友人的讨论中就发现,写个推荐系统并没有那么轻而易举,为此他专门写了一篇博文来记录自己实现的整个过程,利用的工具是数据挖掘领域很热门的 Pandas SciPy 函数库,最后使用 D3.js 进行交互和可视化,相关的代码都放在了 GitHub 上。

具体来讲,一个推荐系统包括数据的获取和存储,相似度的计算以及最终结果的可视化,下面分别阐述。

数据获取

Ben 的推荐系统是针对 Last.fm 用户的,所用数据集是通过 Last.fm 的 API 获取的大约 36 万用户对歌手的喜爱程度。程度以用户对该歌手的播放次数为指标,数据集大小在 1 千 7 百万左右。想要在程序中使用这个数据集,ben 通过 Python 数据挖掘工具 Pandas 的 read_table 将 csv 格式的数据导入成为表格。

复制代码
data = pandas.read_table("usersha1-artmbid-artname-plays.tsv",
usecols=[0, 2, 3],
names=['user', 'artist', 'plays'])

将数据加载为表格以后,剩下的任务就是计算相似度了,ben 给出了三种相似度的计算方法,分别是简单的相似度计算,余弦相似度和来自信息学的相似度计算,并给出了各类方法最后的可视化比较。

简单相似度

简单相似度计算,顾名思义,是最简单的相似度计算方法,用来计算两个歌手的相似程度。这种计算方法,忽略歌手被用户播放的次数,只是简单计算两个歌手重叠的用户数目。

复制代码
def overlap(a, b):
return len(a.intersection(b))

这种计算方法的问题在于,那些流行的歌手的存在,会极大影响相似度的准确性。例如几乎每个用户都听过 Radiohead、Coldplay 和披头士,这使得简单相似度方法给出的答案里面,越是流行的歌手越相似。

为了解决这个问题,ben 引入了新的相似度定义, Jaccard 相似度,利用数据挖掘中常用的正则化(Normalize)手段,将简单相似度正则化,消除用户数目对歌手相似度的影响,具体计算方法如下:

复制代码
def jaccard(a, b):
intersection = float(len(a.intersection(b)))
return intersection / (len(a) + len(b) - intersection)

类似的正则化方法还有很多,比如 Dice 正则和 Ochiai 正则等,从一定程度上改善了相似度计算的准确性,但也带来了一点问题,即集合大小相近的歌手会更加相似,ben 觉得这样也并不合理,因此进一步提出了使用余弦相似度。

余弦相似度

上文中提到的简单相似度抛弃了用户对歌手播放次数这一重要信息,实际上它代表了用户对该歌手的喜爱程度,细想一下是非常有道理的,一个披头士的重度听众怎么能够跟听过寥寥几曲的听众一样呢?那么,利用上播放次数这一信息最直接的办法,就是余弦相似度方法,计算公式如下:

复制代码
def cosine(a, b):
return dot(a, b.T)[0, 0] / (norm2(a) * norm2(b))

通过上面公式,我们就可以将播放次数引入到相似度的计算中。公式中的 a 和 b 分别代表歌手的听众向量,通过下面的代码构造生成:

复制代码
# map each username to a unique numeric value
userids = defaultdict(lambda: len(userids))
data['userid'] = data['user'].map(userids.__getitem__)
# map each artist to a sparse vector of their users
artists = dict((artist, csr_matrix(
(group['plays'], (zeros(len(group)), group['userid'])),
shape=[1, len(userids)]))
for artist, group in data.groupby('artist'))

来自信息学的相似度

除了单纯利用播放次数以外,ben 还介绍了来自信息学的,确切来讲是来自搜索引擎中常用的自然语言处理技术,来计算歌手之间的相似度,即词频 - 逆文档频率(TF-IDF)作为向量的相似度计算方法。

这种相似度的发明,来自搜索引擎对检索结果排序的需求,即计算检索关键词与检索返回的文档之间的相似程度。具体来讲,如果某个词语在一个描述语句中出现的频率很高(TF 很高),而在其他描述语句中很少出现(IDF 很高),则认为该词语具有很好的区分文档的能力,其 TF-IDF 值就比较高,那么对应到歌曲推荐这个任务来讲,ben 将用户(听众)看作一个个的单词,来进一步考虑特定用户对相似度准确性的影响,可谓是三种方法中比较准确的一个了,ben 还在原文中用 D3.js 给出了几种相似度的效果对比分析。

总结

在专业术语充斥耳畔的今天,能够有耐心真正自己去尝试一些想当然的东西、算法甚至系统,是非常难能可贵的精神,而收获也是非常丰富的。Ben 以 Python 中常用的 Pandas 和 SciPy 等工具,展现了从头实现一个推荐系统的方法,正是这种精神的实践典范。


感谢崔康对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-05-07 08:094997
用户头像

发布了 268 篇内容, 共 138.3 次阅读, 收获喜欢 24 次。

关注

评论

发布
暂无评论
发现更多内容

2025年YashanDB数据库在云计算中的应用前瞻分析

数据库砖家

2025年YashanDB在区块链数据管理领域的潜力研究

数据库砖家

智慧环保系统

深圳亥时科技

2025年YashanDB数据库在AI领域的潜在影响.

数据库砖家

2025年YashanDB在电商行业的典型应用剖析

数据库砖家

2025年YashanDB支持的多云部署技术前沿解析

数据库砖家

2025年YashanDB在人工智能数据处理中的潜力

数据库砖家

2025年YashanDB在智能制造领域的应用前景报告

数据库砖家

客户服务转折点:从工具效率到AI势能

天润融通

2025年YashanDB数据库深度学习辅助优化技术展望

数据库砖家

AI共智 开源共享|2025开放原子开发者大会开源鸿蒙技术分论坛即将启幕

新消费日报

Rust RefCell 多线程读为什么也panic了?

非专业程序员Ping

rust rust语言 #Rust

过程控制 通讯维护经验总结(6)

万里无云万里天

工业 工厂运维 过程控制

Nagarro公布2025年第三季度财报并宣布股份赎回及回购计划

财见

2025年YashanDB在智能制造中的应用前景

数据库砖家

京东工业平台商品详情API

Datafox(数据狐)

京东工业平台数据采集 京东工业平台商品数据 京东数据采集

用百度文心5.0修族谱,感觉又能了!!

苍何

工业管理 项目管理经验总结(33)

万里无云万里天

项目管理 工业 工厂运维

在AI技术唾手可得的时代,挖掘新需求成为制胜关键——某知名代码文档生成系统需求探索

qife122

AI技术 需求挖掘 代码文档

2025年YashanDB在人工智能数据管理中的创新应用

数据库砖家

2025 年最佳 SEO 学习路线和书籍列表推荐

程序员泥瓦匠

京东工业平台商品列表API

Datafox(数据狐)

京东工业平台数据采集 京东工业平台接口 京东数据采集

银行中外汇的由来(金融产品经理必读)

东边有耳

产品经理 金融科技 银行 结算 外汇

2025年YashanDB提交的关键特性展望

数据库砖家

电信业绿色转型:Orange Business的可持续IT实践

qife122

可持续IT 电信基础设施

基础设施即服务(IaaS)全面解析:云计算的基石

qife122

云计算 云基础设施

我用Claude Code开发了Obsidian内容分发插件,爆了!(附教程)

苍何

歌曲推荐系统实践:Pandas、SciPy和D3.js_语言 & 开发_张天雷_InfoQ精选文章