python音乐推荐系统
首先对音乐数据集进行清理和特征提取,然后基于矩阵分解进行音乐推荐。
[En]
Firstly, the music data set is cleaned and features are extracted, and the music recommendation is carried out based on matrix decomposition.
- 音乐数据处理
阅读音乐数据集,统计其指标,并选择有价值的信息作为我们的特征。[En]
Read the music data set, count its indicators, and choose valuable information as our characteristics.
- 基于商品相似性的推荐
选择相似度计算方法,通过相似度来计算推荐结果 - 基于SVD矩阵分解的推荐
使用矩阵分解方法,快速高效得到推荐结果
import pandas as pd
import numpy as np
import time
import sqlite3
data_home = './'
数据提取
提取用户,歌曲,播放量
triplet_dataset = pd.read_csv(filepath_or_buffer=data_home+'train_triplets.txt',
sep='\t', header=None,
names=['user','song','play_count'])
查看数据大小
triplet_dataset.shape
triplet_dataset.info()
查看原始数据
triplet_dataset.head(n=5)
得到每个用户的播放量
对每个用户进行遍历
output_dict = {}
with open(data_home+'train_triplets.txt') as f:
for line_number, line in enumerate(f):
user = line.split('\t')[0]
play_count = int(line.split('\t')[2])
if user in output_dict:
play_count +=output_dict[user]
output_dict.update({user:play_count})
output_dict.update({user:play_count})
output_list = [{'user':k,'play_count':v} for k,v in output_dict.items()]
play_count_df = pd.DataFrame(output_list)
play_count_df = play_count_df.sort_values(by = 'play_count', ascending = False)
保存中间结果 防止丢失(df格式)
play_count_df.to_csv(path_or_buf='user_playcount_df.csv', index = False)
得到每首歌的播放量
#统计方法跟上述类似
output_dict = {}
with open(data_home+'train_triplets.txt') as f:
for line_number, line in enumerate(f):
#找到当前歌曲
song = line.split('\t')[1]
#找到当前播放次数
play_count = int(line.split('\t')[2])
#统计每首歌曲被播放的总次数
if song in output_dict:
play_count +=output_dict[song]
output_dict.update({song:play_count})
output_dict.update({song:play_count})
output_list = [{'song':k,'play_count':v} for k,v in output_dict.items()]
#转换成df格式
song_count_df = pd.DataFrame(output_list)
song_count_df = song_count_df.sort_values(by = 'play_count', ascending = False)
song_count_df.to_csv(path_or_buf='song_playcount_df.csv', index = False)
查看目前的排行
play_count_df = pd.read_csv(filepath_or_buffer='user_playcount_df.csv')
play_count_df.head(n =10)
song_count_df = pd.read_csv(filepath_or_buffer='song_playcount_df.csv')
song_count_df.head(10)
对数据进行清洗
选择十万名用户和3w首歌曲来作为新的数据集
查看这10w名用户的播放量占总体的比例
total_play_count = sum(song_count_df.play_count)
print ((float(play_count_df.head(n=100000).play_count.sum())/total_play_count)*100)
play_count_subset = play_count_df.head(n=100000)
查看3w歌曲的播放量占总体的比例
(float(song_count_df.head(n=30000).play_count.sum())/total_play_count)*100
song_count_subset = song_count_df.head(n=30000)
前3W首歌的播放量占到了总体的78.39% 现在已经有了这10W名忠实用户和3W首经典歌曲,接下来我们就要对原始数据集进行过滤清洗,说白了就是在原始数据集中剔除掉不包含这些用户以及歌曲的数据。
取10W个用户,3W首歌
user_subset = list(play_count_subset.user)
song_subset = list(song_count_subset.song)
过滤其他用户数据
#读取原始数据集
triplet_dataset = pd.read_csv(filepath_or_buffer=data_home+'train_triplets.txt',sep='\t',
header=None, names=['user','song','play_count'])
#只保留有这10W名用户的数据,其余过滤掉
triplet_dataset_sub = triplet_dataset[triplet_dataset.user.isin(user_subset) ]
del(triplet_dataset)
#只保留有这3W首歌曲的数据,其余也过滤掉
triplet_dataset_sub_song = triplet_dataset_sub[triplet_dataset_sub.song.isin(song_subset)]
del(triplet_dataset_sub)
triplet_dataset_sub_song.to_csv(path_or_buf=data_home+'triplet_dataset_sub_song.csv', index=False)
当前的数据量
triplet_dataset_sub_song.shape
此时,样本量少,但有利于建模,既能提高效率,又能提高精度。
[En]
At this time, the number of samples is small, but it is beneficial to modeling, which can improve not only the efficiency but also the accuracy.
triplet_dataset_sub_song.head(n=10)
加入音乐的详细信息(歌手,发布时间,主题等)
conn = sqlite3.connect(data_home+'track_metadata.db')
cur = conn.cursor()
cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
cur.fetchall()
track_metadata_df = pd.read_sql(con=conn, sql='select * from songs')
track_metadata_df_sub = track_metadata_df[track_metadata_df.song_id.isin(song_subset)]
track_metadata_df_sub.to_csv(path_or_buf=data_home+'track_metadata_df_sub.csv', index=False)
track_metadata_df_sub.shape
现有的数据
triplet_dataset_sub_song = pd.read_csv(filepath_or_buffer=data_home+'triplet_dataset_sub_song.csv',encoding = "ISO-8859-1")
track_metadata_df_sub = pd.read_csv(filepath_or_buffer=data_home+'track_metadata_df_sub.csv',encoding = "ISO-8859-1")
triplet_dataset_sub_song.head()
清洗数据集
# 去掉无用的信息
del(track_metadata_df_sub['track_id'])
del(track_metadata_df_sub['artist_mbid'])
# 去掉重复的
track_metadata_df_sub = track_metadata_df_sub.drop_duplicates(['song_id'])
# 将这份音乐信息数据和我们之前的播放数据整合到一起
triplet_dataset_sub_song_merged = pd.merge(triplet_dataset_sub_song, track_metadata_df_sub, how='left', left_on='song', right_on='song_id')
# 可以自己改变列名
triplet_dataset_sub_song_merged.rename(columns={'play_count':'listen_count'},inplace=True)
# 去掉不需要的指标
del(triplet_dataset_sub_song_merged['song_id'])
del(triplet_dataset_sub_song_merged['artist_id'])
del(triplet_dataset_sub_song_merged['duration'])
del(triplet_dataset_sub_song_merged['artist_familiarity'])
del(triplet_dataset_sub_song_merged['artist_hotttnesss'])
del(triplet_dataset_sub_song_merged['track_7digitalid'])
del(triplet_dataset_sub_song_merged['shs_perf'])
del(triplet_dataset_sub_song_merged['shs_work'])
triplet_dataset_sub_song_merged.head(n=10)
现有的数据
现在的数据看起来要整齐得多,不仅是一首音乐的播放用户数,还有作品的名字和发行专辑,以及作者的名字和发行时间。现在我们对数据中每个指标的含义只有一个大概的了解,还没有分析它的具体内容。我们在介绍推荐系统的时候,提到了开机过冷的问题,就是当一个新用户来了,不知道推荐什么给他的时候,我们可以在这个时候使用排行榜。你可以数出最受欢迎的歌曲和歌手:
[En]
Now the data looks much more tidy, not only in terms of the number of users playing a piece of music, but also the name and release album of the work, as well as the author's name and release time. Now we only have a general understanding of the meaning of each index in the data, and we have not analyzed its specific content yet. when we introduced the recommendation system, we mentioned the problem of over-cold startup, that is, when a new user comes and does not know what to recommend to him, we can use the ranking list at this time. You can count the most popular songs and singers:
查看最流行的歌曲
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
#按歌曲名字来统计其播放量的总数
popular_songs = triplet_dataset_sub_song_merged[['title','listen_count']].groupby('title').sum().reset_index()
#对结果进行排序
popular_songs_top_20 = popular_songs.sort_values('listen_count', ascending=False).head(n=20)
#转换成list格式方便画图
objects = (list(popular_songs_top_20['title']))
#设置位置
y_pos = np.arange(len(objects))
#对应结果值
performance = list(popular_songs_top_20['listen_count'])
#绘图
plt.bar(y_pos, performance, align='center', alpha=0.5)
plt.xticks(y_pos, objects, rotation='vertical')
plt.ylabel('Item count')
plt.title('Most popular songs')
plt.show()
查看最受欢迎的专辑
#按专辑名字来统计播放总量
popular_release = triplet_dataset_sub_song_merged[['release','listen_count']].groupby('release').sum().reset_index()
#排序
popular_release_top_20 = popular_release.sort_values('listen_count', ascending=False).head(n=20)
objects = (list(popular_release_top_20['release']))
y_pos = np.arange(len(objects))
performance = list(popular_release_top_20['listen_count'])
#绘图
plt.bar(y_pos, performance, align='center', alpha=0.5)
plt.xticks(y_pos, objects, rotation='vertical')
plt.ylabel('Item count')
plt.title('Most popular Release')
plt.show()
用户播放过歌曲量的分布
user_song_count_distribution = triplet_dataset_sub_song_merged[['user','title']].groupby('user').count().reset_index().sort_values(
by='title',ascending = False)
user_song_count_distribution.title.describe()
x = user_song_count_distribution.title
n, bins, patches = plt.hist(x, 50, facecolor='green', alpha=0.75)
plt.xlabel('Play Counts')
plt.ylabel('Num of Users')
plt.title(r'$\mathrm{Histogram\ of\ User\ Play\ Count\ Distribution}\ $')
plt.grid(True)
plt.show()
正式开始构建推荐系统
import Recommenders as Recommenders
from sklearn.model_selection import train_test_split
最简单的就是根据榜单推荐(新用户冷启动问题)
triplet_dataset_sub_song_merged_set = triplet_dataset_sub_song_merged
train_data, test_data = train_test_split(triplet_dataset_sub_song_merged_set, test_size = 0.40, random_state=0)
train_data.head()
def create_popularity_recommendation(train_data, user_id, item_id):
#根据指定的特征来统计其播放情况,可以选择歌曲名,专辑名,歌手名
train_data_grouped = train_data.groupby([item_id]).agg({user_id: 'count'}).reset_index()
#为了直观展示,我们用得分来表示其结果
train_data_grouped.rename(columns = {user_id: 'score'},inplace=True)
#排行榜单需要排序
train_data_sort = train_data_grouped.sort_values(['score', item_id], ascending = [0,1])
#加入一项排行等级,表示其推荐的优先级
train_data_sort['Rank'] = train_data_sort['score'].rank(ascending=0, method='first')
#返回指定个数的推荐结果
popularity_recommendations = train_data_sort.head(20)
return popularity_recommendations
recommendations = create_popularity_recommendation(triplet_dataset_sub_song_merged,'user','title')
得到结果
recommendations
排行前20的歌曲
基于歌曲相似度的推荐
核心思想
- 计算相似度
首先我们要针对某一个用户进行推荐,那必然得先得到他都听过哪些歌曲,通过这些已被听过的歌曲跟整个数据集中的歌曲进行对比,看哪些歌曲跟用户已听过的比较类似,推荐的就是这些类似的。如何计算呢?例如当前用户听过了66首歌曲,整个数据集中有4879个歌曲,我们要做的就是构建一个[66,4879]的矩阵,其中每一个值表示用户听过的每一个歌曲和数据集中每一个歌曲的相似度。这里使用Jaccard相似系数,矩阵中[i,j]的含义就是用户听过的第i首歌曲这些歌曲被哪些人听过,比如有3000人听过,数据集中的j歌曲被哪些人听过,比如有5000人听过。Jaccard相似系数就要求:
说白了就是如果两个歌曲很相似,那其受众应当是一致的,交集/并集的比例应该比较大,如果两个歌曲没啥相关性,其值应当就比较小了。 上述代码中计算了矩阵[66,4879]中每一个位置的值应当是多少,在最后推荐的时候我们还应当注意一件事对于数据集中每一个待推荐的歌曲都需要跟该用户所有听过的歌曲计算其Jaccard值,例如歌曲j需要跟用户听过的66个歌曲计算其值,最终是否推荐的得分值还得进行处理,即把这66个值加在一起,最终求一个平均值,来代表该歌曲的推荐得分。
选取一部分数据进行推荐
song_count_subset = song_count_df.head(n=5000)
user_subset = list(play_count_subset.user)
song_subset = list(song_count_subset.song)
triplet_dataset_sub_song_merged_sub = triplet_dataset_sub_song_merged[triplet_dataset_sub_song_merged.song.isin(song_subset)]
triplet_dataset_sub_song_merged_sub.head()
计算相似度得到推荐结果
import Recommenders as Recommenders
train_data, test_data = train_test_split(triplet_dataset_sub_song_merged_sub, test_size = 0.30, random_state=0)
is_model = Recommenders.item_similarity_recommender_py()
is_model.create(train_data, 'user', 'title')
user_id = list(train_data.user)[7]
user_items = is_model.get_user_items(user_id)
#执行推荐
is_model.recommend(user_id)
结果
基于矩阵分解(SVD)的推荐
比相似推荐省时间不用对每个用户进行遍历
核心思想
相似度计算的方法看起来比较简单,但当数据量大时,计算的时间消耗太大,每个用户需要多次遍历整个数据集才能进行计算。矩阵分解是目前比较常用的一种方法。
[En]
The method of similarity calculation seems to be relatively simple to implement, but when the data is large, the time consumption of calculation is too large, and each user needs to traverse the entire data set many times to calculate. Matrix decomposition is a more commonly used method at present.
奇异值分解(Singular Value Decomposition,SVD)是矩阵分解中一个经典方法,接下来我们的推荐就可以SVD来进行计算,奇异值分解的基本出发点跟我们之前讲的隐语义模型有些类似都是将大矩阵转换成小矩阵的组合,基本形式如下图所示:
对矩阵进行SVD分解,将得到USV
重新计算 USV的结果得到A2 来比较下A2和A的差异,看起来差异是有的,但是并不大,所以我们可以近似来代替
在SVD中我们所需的数据是用户对商品的打分,但是我们现在的数据集中只有用户播放歌曲的情况并没有实际的打分值,所以我们还得自己来定义一下用户对每个歌曲的评分值。如果一个用户喜欢某个歌曲,那应该经常播放这个歌曲,相反如果不喜欢某个歌曲,那播放次数肯定就比较少了。 用户对歌曲的打分值,定义为:用户播放该歌曲数量/该用户播放总量。代码如下:
triplet_dataset_sub_song_merged_sum_df = triplet_dataset_sub_song_merged[['user','listen_count']].groupby('user').sum().reset_index()
triplet_dataset_sub_song_merged_sum_df.rename(columns={'listen_count':'total_listen_count'},inplace=True)
triplet_dataset_sub_song_merged = pd.merge(triplet_dataset_sub_song_merged,triplet_dataset_sub_song_merged_sum_df)
triplet_dataset_sub_song_merged.head()
triplet_dataset_sub_song_merged['fractional_play_count'] = triplet_dataset_sub_song_merged['listen_count']/triplet_dataset_sub_song_merged['total_listen_count']
triplet_dataset_sub_song_merged[triplet_dataset_sub_song_merged.user =='d6589314c0a9bcbca4fee0c93b14bc402363afea'][['user','song','listen_count','fractional_play_count']].head()
from scipy.sparse import coo_matrix
small_set = triplet_dataset_sub_song_merged
user_codes = small_set.user.drop_duplicates().reset_index()
song_codes = small_set.song.drop_duplicates().reset_index()
user_codes.rename(columns={'index':'user_index'}, inplace=True)
song_codes.rename(columns={'index':'song_index'}, inplace=True)
song_codes['so_index_value'] = list(song_codes.index)
user_codes['us_index_value'] = list(user_codes.index)
small_set = pd.merge(small_set,song_codes,how='left')
small_set = pd.merge(small_set,user_codes,how='left')
mat_candidate = small_set[['us_index_value','so_index_value','fractional_play_count']]
data_array = mat_candidate.fractional_play_count.values
row_array = mat_candidate.us_index_value.values
col_array = mat_candidate.so_index_value.values
data_sparse = coo_matrix((data_array, (row_array, col_array)),dtype=float)
data_sparse
上面代码先根据用户进行分组,计算每个用户的总的播放总量,然后用每首歌的播放总量相处,得到每首歌的分值,最后一列特征fractional_play_count就是用户对每首歌曲的评分值。 有了评分值之后就可以来构建矩阵了,这里有一些小问题需要处理一下,原始数据中无论是用户ID还是歌曲ID都是很长一串,这表达起来不太方便,需要重新对其制作索引。
user_codes[user_codes.user =='2a2f776cbac6df64d6cb505e7e834e01684673b6']
使用SVD方法进行矩阵分解
矩阵构造好了之后我们就要执行SVD矩阵分解了,这里还需要一些额外的工具包来帮助我们完成计算,scipy就是其中一个好帮手了,里面已经封装好了SVD计算方法。
import math as mt
from scipy.sparse.linalg import * #used for matrix multiplication
from scipy.sparse.linalg import svds
from scipy.sparse import csc_matrix
def compute_svd(urm, K):
U, s, Vt = svds(urm, K)
dim = (len(s), len(s))
S = np.zeros(dim, dtype=np.float32)
for i in range(0, len(s)):
S[i,i] = mt.sqrt(s[i])
U = csc_matrix(U, dtype=np.float32)
S = csc_matrix(S, dtype=np.float32)
Vt = csc_matrix(Vt, dtype=np.float32)
return U, S, Vt
def compute_estimated_matrix(urm, U, S, Vt, uTest, K, test):
rightTerm = S*Vt
max_recommendation = 250
estimatedRatings = np.zeros(shape=(MAX_UID, MAX_PID), dtype=np.float16)
recomendRatings = np.zeros(shape=(MAX_UID,max_recommendation ), dtype=np.float16)
for userTest in uTest:
prod = U[userTest, :]*rightTerm
estimatedRatings[userTest, :] = prod.todense()
recomendRatings[userTest, :] = (-estimatedRatings[userTest, :]).argsort()[:max_recommendation]
return recomendRatings
在执行SVD的时候需要我们额外指定一个指标K值,其含义就是我们选择前多少个特征值来做近似代表,也就是S矩阵中的数量。如果K值较大整体的计算效率会慢一些但是会更接近真实结果,这个值还需要我们自己来衡量一下
K=50
urm = data_sparse
MAX_PID = urm.shape[1]
MAX_UID = urm.shape[0]
U, S, Vt = compute_svd(urm, K)
选取测试用户
uTest = [4,5,6,7,8,873,23]
uTest_recommended_items = compute_estimated_matrix(urm, U, S, Vt, uTest, K, True)
对用户进行推荐
for user in uTest:
print("Recommendation for user with user id {}". format(user))
rank_value = 1
for i in uTest_recommended_items[user,0:10]:
song_details = small_set[small_set.so_index_value == i].drop_duplicates('so_index_value')[['title','artist_name']]
print("The number {} recommended song is {} BY {}".format(rank_value, list(song_details['title'])[0],list(song_details['artist_name'])[0]))
rank_value+=1
这里,针对每个用户获取相应的推荐结果,并根据得分对结果进行排序。
[En]
Here, the corresponding recommendation results are obtained for each user, and the results are sorted according to the score.
uTest = [27513]
#Get estimated rating for test user
print("Predictied ratings:")
uTest_recommended_items = compute_estimated_matrix(urm, U, S, Vt, uTest, K, True)
计算结果
for user in uTest:
print("Recommendation for user with user id {}". format(user))
rank_value = 1
for i in uTest_recommended_items[user,0:10]:
song_details = small_set[small_set.so_index_value == i].drop_duplicates('so_index_value')[['title','artist_name']]
print("The number {} recommended song is {} BY {}".format(rank_value, list(song_details['title'])[0],list(song_details['artist_name'])[0]))
rank_value+=1
总结: 选择了音乐数据集来进行个性化推荐任务,首先对数据进行预处理和整合,选择两种方法分别完成推荐任务。在相似度计算中根据用户所听过的歌曲在候选集中选择与其最相似的歌曲,存在的问题就是计算时间消耗太多,每一个用户都需要重新计算一遍才能得出推荐结果。在SVD矩阵分解的方法中,首先构建评分矩阵,对其进行SVD分解,然后选择待推荐用户,还原得到其对所有歌曲的估测评分值,最后排序返回结果即可
Original: https://blog.csdn.net/m0_46406029/article/details/114444213
Author: 耿耿的星河
Title: 音乐推荐系统(协同过滤和SVD)
相关阅读
Title: dirsearch安装+使用+运行问题(小宇特详解)
dirsearch安装+使用+运行问题(小宇特详解)
前几天电脑坏了重新安装了一下dirsearch,却发现好多问题今天写个文章说一下
这里着重说一下我运行时出现的问题
安装
dirsearch是一个用python开发的网站目录扫描工具
github下载地址
我的系统是win10的
我一开始是将这个东西放到过D盘,也放到过python3环境的位置进行了解压
这里两个方式都可
一般解压之后就可以使用
; 使用
使用的方法就是打开dirsearch-master文件后打开cmd命令
打开后运行
python setup.py
安装后运行
python dirsearch.py -u ip
详细用法可以查看帮助
python dirsearch.py -h
运行问题
这里我详细说一下这个问题
首先是缺库问题
这里请看图
解决办法
pip install certifi
后来又出现了
这时用上面的方法来pip的话,我这里出现了问题
这里提示pip版本过低
这里升级pip
这里先查看pip版本
pip -V
然后直接升级pip
D:\python3\python.exe -m pip install --upgrade pip
这里的D:\python3\python.exe是我电脑上的python路径
然后
pip install cryptography
这里又出现问题了
这个问题我找了半天才找到原因。
这里提示连接被中断,一开始没多想觉得时pip被国内的网断了觉得时下面红字提示的找不到满足加密要求的版本的问题
后来我关了我电脑上的代理才解决了问题。这里直接关代理运行上面的pip即可。
希望我走过的坑你们不用再走。
Original: https://blog.csdn.net/xhy18634297976/article/details/122900500
Author: 小宇特详解
Title: dirsearch安装+使用+运行问题(小宇特详解)

如何使用MSGEQ7音频频谱分析仪芯片

浅谈:纯语音聊天系统与语音源码开发运营方向

你的声音价值百万,教你六个利用声音赚钱的方法

树莓派4B使用NCNN部署Yolov5-lite

Python命令行参数定义及注意事项

Transformer 模型详解

基于kears的LSTM时间序列预测
![【tensorflow】[Python] tensorflow tensor的批量条件改值 如何修改tensor中符合特定条件的元素值 将满足特定规则的tensor元素值修改](https://www.itcode1024.com/wp-content/themes/begin/prune.php?src=https://www.itcode1024.com/wp-content/themes/begin/img/loading.png&w=280&h=210&a=&zc=1)
【tensorflow】[Python] tensorflow tensor的批量条件改值 如何修改tensor中符合特定条件的元素值 将满足特定规则的tensor元素值修改

python opencv 详细入门操作(含创建窗口, 显示图像, 标记图像, 调动摄像头, 简单人脸识别)

如何无障碍地快速在linux上安装tensorflow?

关于Attention的超详细讲解

动态卷积 Dynamic convolution

使用labelme工具标注人像数据集

基于ROS的自动驾驶 激光雷达点云物体检测 项目实战
