[歌曲推荐] 基于语义信息的歌曲推荐

总体介绍

本版本主要基于word2vec,后续还有一些改进想法,会继续更新。

本项目所有代码及数据:github

本项目主要包括如下内容:
(1) 网易云音乐歌曲信息的爬取(歌手姓名、歌曲名、歌词、评论数、歌曲id)。
(2) 使用word2vec对歌曲进行表示表示。
(3) 基于word2vec对歌曲进行推荐以及web系统展示,支持歌手名、歌手+关键词和关键词查询。

除此之外,涉及了数据处理以及去重操作。

本项目使用环境:
(1) 编码语言:Python 3、Java 1.8.0
(2) 编码工具:PyCharm、IntelliJ
(3) 数据库:Mysql 5.7.25、Redis 5.0.4
(4) 其他:gensim 3.6.1、Spring Boot 1.3.5.RELEASE、Bootstrap、AngularJS

一、网易云音乐的爬取与处理

本部分使用语言:Python。爬取的代码基本来源于网上,进行了部分更改。具体引用地址我也找不到了,时间拖得有点久了。歌词爬取大概来源于博客,评论数爬取来自知乎下面的某个评论。(如果原作者看到,可以联系我添加原链接。)

1、网易云音乐歌词爬取

这部分内容分析这里不再细说,详见之前的一篇博客:[歌词生成] 基于LSTM语言模型和seq2seq序列模型:数据爬取、模型思想、网络搭建、歌词生成

2、网易云音乐歌词处理

歌词处理主要是为了去除空行以及特殊字开头的行,另外,对于不包含中文的行也一并去除。
特殊字开头的行主要包括:

“编曲”, “编辑”, “歌名”, “歌手”, “专辑”, “木吉他”, “贝斯”, “发行日”, “曲”, “监制”, “制作人”, “中乐演奏”, “其余所有乐器演奏”, “演奏”, “和音”, “联合制作”, “制作”, “录音”, “混音”, “录音室”, “混音室”, “录音师”, “混音师”, “统筹”, “制作统筹”, “执行制作”, “母带后期处理”, “企划”, “鼓”, “合声”, “二胡”, “乌克丽丽”, “过带”, “Bass”, “Scratch”, “OP”, “Guitar”, “SP”, “Bass”, “SCRATCH”, “Programmer”, “弦乐”, “小提琴”, “女声”, “Cello solo”, “Piano”, “吉他”, “钢琴”, “os”, “弦乐”, “和声”, “DJ”, “Tibet”, “Violin”, “Viola”, “Cello”, “和声”, “母带”, “音乐”, “打击乐”, “Vocal”, “次中音”, “长号”, “小号”, “Music”, “监制”, “作词”, “词/曲”, “箫”, “筝”, “作词”, “作曲”, “Program”, “键盘”, “制作”

3、网易云音乐评论数爬取

评论数的爬取稍微复杂些,主要是因为网易云的加密措施,所以需要进行加密解密,具体可搜索知乎有关于这个加密解密的讨论。
这里的输入是第一步爬取的歌单中歌曲名称,对其评论数进行爬取,并存储。

我们主要爬取了47名歌手的信息,歌手分别是:

胡夏,林俊杰,李宗盛,林宥嘉,罗大佑,林志炫,王菲,李健,李荣浩,周笔畅,薛之谦,许茹芸,汪苏泷,光良,邓丽君,胡彦斌,王力宏,邓紫棋,陈奕迅,赵雷,许嵩,陈楚生,徐佳莹,丁当,安又琪,陶喆,五月天,梁咏琪,庾澄庆,周杰伦,张国荣,张学友,朴树,汪峰,莫文蔚,张碧晨,杨宗纬,张靓颖,蔡健雅,郑中基,梁静茹,田馥甄,张惠妹,花粥,蔡依林,张韶涵,李玉刚。

二、歌曲embedding及embedding结果的保存

本部分使用语言:Python,主要涉及数据库交互。

1、歌曲embedding

对歌曲进行向量化表示的详细过程如下:
1] 将之前处理过的歌曲信息进行拼接
2] 对拼接之后的信息分词处理
分词之后将一些常用词和标点符号直接去除,常用词如下:

“我”, “你”, “他”, “它”, “的”, “在”, “是”, “了”, “都”, " ", " ", “就”, “也”, “让”, “着”, “这”, “我们”, “你们”, “他们”, “它们”, “那”, “和”, “end”, “music”, ‘q’, ‘w’, ‘e’, ‘r’, ‘t’, ‘y’, ‘u’, ‘i’, ‘o’, ‘p’, ‘a’, ‘s’, ‘d’, ‘f’, ‘g’, ‘h’, ‘j’, ‘k’, ‘l’, ‘z’, ‘x’, ‘c’, ‘v’, ‘b’, ‘n’, ‘m’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘0’

注意: 因歌曲歌词信息的特殊性,所以没有使用通用的停用词。
3] 使用word2vec训练词向量,这里直接调用gensim中的word2vec库,其参数如下:

hs=1, workers=1, min_count=1, window=5, size=250

由于word2vec已经是一个非常成熟的模型,这里不再介绍。github上也有cluter.py通过去vector进行聚类看其表示效果,详情请见本人github。

训练过程也挺快,训练完毕,会生成4个文件:

  • word2vec_res.model
  • word2vec_res.model.trainables.syn1.npy
  • word2vec_res.model.trainables.syn1neg.npy
  • word2vec_res.model.wv.vectors.npy

4] 通过word2vec我们可以将word映射到隐空间,那如何得到歌曲的embedding呢?

方法1: 最简单的方便便是使用average pooling
方法2: 考虑到在使用average pooling的时候,我们认为每一个word同等重要,但是实际上word的重要程度是不同的,所以这里使用tfidf-based weighted pooling来对average pooling进行改进。

2、embedding结果存储

本部分主要包括如下内容:

i) word2vec模型加载与读取。
ii) 训练的词及其对应的向量存储到Redis中。
iii) 每首歌的信息存储到mysql。
iv) 歌曲信息去重。
v) Redis中存入歌曲及唱过此歌曲的歌手(其实存储的是倒排索引:vector: [vector向量], singers:[singers])。

i) word2vec模型加载与读取

将“歌曲embedding”部分生成的4个文件存放在同一目录。
word2vec加载过程如下:

model = word2vec.Word2Vec.load(file)    # 加载word2vec模型
vocabulary = model.wv.vocab.keys()       # 获取word2vec生成的所有词向量信息
ii) 训练的词及其对应的向量存储到Redis
存储到Redis中主要因为在后续推荐系统中,我们需要通过词获取其对应的vector,Redis作为一个key-value数据库,获取速度快。在Redis中,我们使用hash结构,词向量使用拼接字符串存储,其key为“vector”。其存储代码如下:
# vec_string_res:dict type, key is word, value is the vector string.
redis = Redis(host='localhost', port=6379, db=0, decode_responses=True)     # Redis连接信息
for key, value in vec_string_res.items():
    redis.hset(key, "vector", value)
iii) 歌曲信息存储到mysql
主要包括song_id, song_name, singer_name, vector, comments_num。对于歌曲的向量表示,我们取歌曲的词向量均值。

数据库存储格式如下:

在这里插入图片描述
其中,需要说明的是song_id就是网易云音乐中的歌曲id,这个在web系统推荐中将歌曲链接到网易云音乐页面时会用到。

本部分使用Mysql而不是用Redis的原因是在用户只输入歌手名的时候,我们推荐的是topK评论数最多的歌曲,Mysql中排序等处理比较方便。

注: 在本步骤中,对于同一歌手、同一歌曲名的歌曲已经进行了去重处理。

iv) 歌曲信息去重

本步骤中的去重操作主要是为了去重以下情况:

不同歌手歌唱了同一首歌,在网易云平台认为这是多首歌。
不同歌手或者同一歌手唱了同一首歌,但是可能歌曲名不是很准确,有一个字的差异之类的。

因为我的数据库歌曲不是很多,大概7000首,所以这一步直接暴力了,若其余弦相似度大于等于0.99,则去除评论数较小的歌曲id及其对应的信息。

如果是数据比较多,可以先考虑聚类或者分块,再类内/块内去重。

v) Redis中存入key-value

本部分倒排索引的存储主要是为了方便判断某首歌是否被歌手x歌唱过。存储格式:key是歌曲名称,value是歌手,若有多个歌手,则使用逗号拼接。

三、推荐算法和推荐系统

1、推荐算法

推荐系统总共有2个可输入的信息:歌手名和歌曲名/关键词。

推荐逻辑如下:

(1) 若只输入歌手名,则判断是否在数据库中,若在则推荐topK评论数最多的歌曲。否则,给出alert错误提示。
(2) 若同时给出了歌手名和歌曲名/关键字,则判断此歌曲是否被此歌手歌唱过,若是,则推荐此歌手与此首歌曲余弦相似度最高的K首歌。否则认为此输入信息是关键词,在Redis中获取此关键词的向量表示,推荐此歌手的topK余弦相似度歌曲。
(3) 若只输入歌曲名/关键词信息,则直接当做关键词进行推荐,在Redis中获取此关键词的向量表示,推荐此歌手的topK余弦相似度歌曲。
(4) 对于vocabulary不在数据库中的词语,给出alert报错信息。

2、web展示

本系统后台使用了SpringBoot,前端使用了AngularJS,css使用了Bootstrap。

系统展示如下:

①主界面:支持歌手名和歌曲名/关键词输入

②只输入歌手信息,这里举例:周杰伦

③输入歌手信息和关键词

④只输入关键词,这里举例:甜蜜、自由

四、v2待改进点

暂时本系统主要基于训练而成的vector信息进行推荐,主要存在的问题如下:

(1) 歌词信息不是很多,可能影响vector的训练质量。
(2) 歌词信息只涉及到歌曲的语义信息,因为此推荐基于纯语义,也就是说如果歌曲歌词比较类似,则会作为推荐结果。但是用户行为,比如用户喜好没有添加进来。

v2改进点:

爬取网易云歌单信息,因为歌单是用户创建的,在很大程序上可以反映此用户的喜好,无论是歌词、歌曲风格、歌手等这都反映了用户的行为信息。后续将考虑使用歌单信息将每首歌表示成一个vector,这个vector则不仅考虑了语义信息,还包括用户喜好、歌曲风格等隐含信息。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值