python音乐推荐系统_《Python数据分析与机器学习实战-唐宇迪》读书笔记第14章--音乐推荐系统实战...

本文是《Python数据分析与机器学习实战》第14章的读书笔记,主要介绍了如何从零开始构建音乐推荐系统。首先,数据预处理包括清洗和统计分析,如用户和歌曲的播放次数统计。接着,通过数据集整合,将播放数据与歌曲元数据结合。然后,采用基于相似度的推荐方法,计算用户与歌曲的Jaccard相似度。最后,利用SVD进行矩阵分解,提高推荐效率,解决了大数据计算的挑战。
摘要由CSDN通过智能技术生成

第14章推荐系统项目实战——打造音乐推荐系统

上一章介绍了推荐系统的基本原理,本章的目标就要从零开始打造一个音乐推荐系统,包括音乐数据集预处理、基于相似度进行推荐以及基于矩阵分解进行推荐。

14.1数据集清洗

很多时候拿到手的数据集并不像想象中那么完美,基本都需要先把数据清洗一番才能使用,首先导入需要的Python工具包:

1 importpandas as pd2 importnumpy as np3 importtime4 importsqlite35

6 data_home = './'

由于数据中有一部分是数据库文件,需要使用sqlite3工具包进行数据的读取,大家可以根据自己情况设置数据存放路径。

先来看一下数据的规模,对于不同格式的数据,read_csv()函数中有很多参数可以选择,例如分隔符与列名:

1 triplet_dataset = pd.read_csv(filepath_or_buffer=data_home+'train_triplets.txt',2 sep='\t', header=None,3 names=['user','song','play_count'])

1 triplet_dataset.shape2 #(48373586, 3)

输出结果显示共48373586个样本,每个样本有3个指标特征。

如果想更详细地了解数据的情况,可以打印其info信息,下面观察不同列的类型以及整体占用内存:

1 triplet_dataset.info()

RangeIndex: 48373586 entries, 0 to 48373585Data columns (total 3columns):

#Column Dtype

--- ------ -----0 user object

1song object

2play_count int64

dtypes: int64(1), object(2)

memory usage: 1.1+ GB

打印前10条数据:

1 triplet_dataset.head(n=10)

user                      song        play_count

0 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOAKIMP12A8C1309951

1 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOAPDEY12A81C210A9 1

2 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBBMDR12A8C13253B 2

3 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBFNSP12AF72A0E22 1

4 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBFOVM12A58A7D494 1

5 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBNZDC12A6D4FC103 1

6 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBSUJE12A6D4F8CF5 2

7 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBVFZR12A6D4F8AE3 1

8 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBXALG12A8C13C108 1

9 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBXHDL12A81C204C0 1

数据中包括用户的编号、歌曲编号以及用户对该歌曲播放的次数。

14.1.1统计分析

掌握数据整体情况之后,下一步统计出关于用户与歌曲的各项指标,例如对每一个用户,分别统计他的播放总量,代码如下:

1 output_dict ={}2 with open(data_home+'train_triplets.txt') as f:3 for line_number, line inenumerate(f):4 #找到当前的用户

5 user = line.split('\t')[0]6 #得到其播放量数据

7 play_count = int(line.split('\t')[2])8 #如果字典中已经有该用户信息,在其基础上增加当前的播放量

9 if user inoutput_dict:10 play_count +=output_dict[user]11 output_dict.update({user:play_count})12 output_dict.update({user:play_count})13 #统计 用户-总播放量

14 output_list = [{'user':k,'play_count':v} for k,v inoutput_dict.items()]15 #转换成DF格式

16 play_count_df =pd.DataFrame(output_list)17 #排序

18 play_count_df = play_count_df.sort_values(by = 'play_count', ascending = False)

构建一个字典结构,统计不同用户分别播放的总数,需要把数据集遍历一遍。当数据集比较庞大的时候,每一步操作都可能花费较长时间。后续操作中,如果稍有不慎,可能还得从头再来一遍。这就得不偿失,最好把中间结果保存下来。既然已经把结果转换成df格式,直接使用to_csv()函数,就可以完成保存操作。

1 play_count_df.to_csv(path_or_buf='user_playcount_df.csv', index = False)

在实验阶段,最好把费了好大功夫处理出来的数据保存到本地,免得一个不小心又得重跑一遍,令人头疼。

对于每一首歌,可以分别统计其播放总量,代码如下:

1 #统计方法跟上述类似

2 output_dict ={}3 with open(data_home+'train_triplets.txt') as f:4 for line_number, line inenumerate(f):5 #找到当前歌曲

6 song = line.split('\t')[1]7 #找到当前播放次数

8 play_count = int(line.split('\t')[2])9 #统计每首歌曲被播放的总次数

10 if song inoutput_dict:11 play_count +=output_dict[song]12 output_dict.update({song:play_count})13 output_dict.update({song:play_count})14 output_list = [{'song':k,'play_count':v} for k,v inoutput_dict.items()]15 #转换成df格式

16 song_count_df =pd.DataFrame(output_list)17 song_count_df = song_count_df.sort_values(by = 'play_count', ascending = False)

1 song_count_df.to_csv(path_or_buf='song_playcount_df.csv', index = False)

下面来看看排序后的统计结果:

1 song_count_df = pd.read_csv(filepath_or_buffer='song_playcount_df.csv')2 song_count_df.head(10)

s!AosQNCBkCZ0CinNtTPRcGrGW68fB?e=AgerbS

上述输出结果显示,最忠实的粉丝有13132次播放。

1 song_count_df = pd.read_csv(filepath_or_buffer='song_playcount_df.csv')2 song_count_df.head(10)

s!AosQNCBkCZ0CinSdBzprwpDccxV9?e=fsOh27

上述输出结果显示,最受欢迎的一首歌曲有726885次播放。

由于该音乐数据集十分庞大,考虑执行过程的时间消耗以及矩阵稀疏性问题,依据播放量指标对数据集进行了截取。因为有些注册用户可能只是关注了一下,之后就不再登录平台,这些用户对后续建模不会起促进作用,反而增大矩阵的稀疏性。对于歌曲也是同理,可能有些歌曲根本无人问津。由于之前已经对用户与歌曲播放情况进行了排序,所以分别选择其中按播放量排名的前10万名用户和3万首歌曲,关于截取的合适比例,大家也可以通过观察选择数据的播放量占总体的比例来设置。

1 #10W名用户的播放量占总体的比例

2 total_play_count =sum(song_count_df.play_count)3 print ((float(play_count_df.head(n=100000).play_count.sum())/total_play_count)*100)4 play_count_subset = play_count_df.head(n=100000)

40.8807280500655

输出结果显示,前10万名最多使用平台的用户的播放量占到总播放量的40.88%

(float(song_count_df.head(n=30000).play_count.sum())/total_play_count)*100

78.39315366645269

输出结果显示,前3万首歌的播放量占到总播放量的78.39%。

接下来就要对原始数据集进行过滤清洗,也就是在原始数据集中,剔除掉不包含这10万名忠实用户以及3万首经典歌曲的数据。

1 song_count_subset = song_count_df.head(n=30000)2

3 user_subset =list(play_count_subset.user)4 song_subset =list(song_count_subset.song)5

6 #读取原始数据集

7 triplet_dataset = pd.read_csv(filepath_or_buffer=data_home+'train_triplets.txt',sep='\t',8 header=None, names=['user','song','play_count'])9 #只保留有这10W名用户的数据,其余过滤掉

10 triplet_dataset_sub =triplet_dataset[triplet_dataset.user.isin(user_subset) ]11 del(triplet_dataset)12 #只保留有这3W首歌曲的数据,其余也过滤掉

13 triplet_dataset_sub_song =triplet_dataset_sub[triplet_dataset_sub.song.isin(song_subset)]14 del(triplet_dataset_sub)15 triplet_dataset_sub_song.to_csv(path_or_buf=data_home+'triplet_dataset_sub_song.csv', index=False)

再来看一下过滤后的数据规模:

1 triplet_dataset_sub_song.shape

#(10774558, 3)

虽然过滤后的数据样本个数不到原来的1/4,但是过滤掉的样本都是稀疏数据,不利于建模,所以,当拿到数据之后,对数据进行清洗和预处理工作还是非常有必要的,它不仅能提

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值