音乐推荐系统实战

news2024/10/7 14:26:58

文章目录

  • 1. 项目背景
  • 2. 数据处理
    • 2.1 统计用户播放总量
    • 2.2 统计歌曲播放总量
    • 2.3 过滤出实验数据
    • 2.4 加入音乐详情信息
    • 2.5 查看音乐集情况
    • 2.6 查看用户播放量的分布
  • 3. 推荐系统
    • 3.1 排行榜单排序
    • 3.2 基于歌曲相似度的推荐(协同过滤)
    • 3.3 基于矩阵分解(SVD)的推荐
  • 4. 总结

1. 项目背景

我们准备做一个音乐推荐系统,拥有的数据集是一个triplet_dataset.txt文件,大小大约为3GB:

在这里插入图片描述

数据集中有近5000万条数据,每条数据大概是这样用户|歌曲|播放次数

在这里插入图片描述

之后会对数据进行转换,便于计算任务,减少计算时使用到的内存。

2. 数据处理

2.1 统计用户播放总量

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])
        # 如果统计过该用户,则将该用户播放歌曲+1
        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)
# 将用户按照播放量从高到低排序(之后过滤掉播放量太少的用户)
song_count_df = play_count_df.sort_values(by='play_count', ascending=False)

将统计好的用户播放总量保存到文件user_playcount_df.cs文件中:

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

查看文件:

在这里插入图片描述

2.2 统计歌曲播放总量

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()]
song_count_df = pd.DataFrame(output_list)
# 将歌曲按照播放量从高到低排序(之后过滤掉播放量太少的用户)
song_count_df = song_count_df.sort_values(by='play_count', ascending=False)

将统计好的歌曲播放总量保存到文件song_playcount_df.csv文件中:

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

查看文件:

在这里插入图片描述

2.3 过滤出实验数据

前10万用户播放占比40%多

total_play_count = sum(song_count_df.play_count) # 所有歌曲的播放量
print((float(play_count_df.head(n=100000).play_count.sum()) / total_play_count) * 100) # 前10万用户播放总量占比
play_count_subset = play_count_df.head(n=100000)

输出:

40.8807280500655

前3万歌曲播放占比78%多

(float(song_count_df.head(n=30000).play_count.sum()) / total_play_count) * 100 # 前3万首歌曲播放占比

输出:

78.39315366645269

  • 取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'])
triplet_dataset_sub = triplet_dataset[triplet_dataset.user.isin(user_subset)]
del(triplet_dataset)
triplet_dataset_sub_song = triplet_dataset_sub[triplet_dataset_sub.song.isin(song_subset)]
del(triplet_dataset_sub)

将过滤后的数据保存到triplet_dataset_sub_song.csv文件中

triplet_dataset_sub_song.to_csv(path_or_buf=data_home + 'triplet_dataset_sub_song.csv', index=False)

查看文件:

在这里插入图片描述

查看过滤后的数据量:

在这里插入图片描述

2.4 加入音乐详情信息

.db文件需要稍微处理下 转换成csv

conn = sqlite3.connect(data_home + 'track_metadata.db')
cur = conn.cursor()
cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
cur.fetchall()

输出:

[('songs',)]
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) # 生成csv文件
track_metadata_df_sub.shape

输出:

(30447, 14)

查看现有信息:

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()

输出:

在这里插入图片描述

track_metadata_df_sub.head()

输出:

在这里插入图片描述

此时我们可以通过song_id把歌曲与歌名对应起来了。

  • 清洗数据集
# 去除掉无用的和重复的
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'])

搞定数据:

在这里插入图片描述

2.5 查看音乐集情况

  • 查看播放量最高的20首歌曲:
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_song_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()

在这里插入图片描述

  • 查看最受欢迎的release:
#按专辑名字来统计播放总量
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()

在这里插入图片描述

  • 查看最受欢迎的歌手:
popular_artist = triplet_dataset_sub_song_merged[['artist_name', 'listen_count']].groupby('artist_name').sum().reset_index()
popular_artist_top_20 = popular_artist.sort_values('listen_count', ascending=False).head(n=20)

objects = (list(popular_artist_top_20['artist_name']))
y_pos = np.arange(len(objects))
performance = list(popular_artist_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 Artist')
plt.show()

在这里插入图片描述

2.6 查看用户播放量的分布

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()

输出:

count    99996.000000
mean       107.749890
std         79.742561
min          1.000000
25%         53.000000
50%         89.000000
75%        141.000000
max       1189.000000
Name: title, dtype: float64
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()

在这里插入图片描述

3. 推荐系统

3.1 排行榜单排序

对新用户来说需要解决冷启动问题,最简单的推荐方式就是排行榜单了,这里我们创建了一个函数,需要我们传入的是原始数据,用户列名,待统计的指标(例如按歌曲名字,歌手名字,专辑名字。选择统计哪项指标得到的排行榜单):

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的歌曲排行榜单,其中的得分这里只是进行了简单的播放计算,在设计的时候也可以综合考虑更多的指标,比如综合计算歌曲发布年份,歌手的流行程度等。

3.2 基于歌曲相似度的推荐(协同过滤)

接下来就要进行相似度的计算来推荐歌曲了,为了加快代码的运行速度,选择了其中一部分数据来进行实验。

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()

输出:

在这里插入图片描述

首先导入了Recommenders,是一个自定义的工具包,这里就包括了我们接下来要使用的所有函数,由于接下来进行计算的代码量较大,直接在notebook中进行展示比较麻烦,所有自己写了一个.py文件,所有的实际计算操作都在这里完成了。

Recommenders.py文件:

# Thanks to Siraj Raval for this module
# Refer to https://github.com/llSourcell/recommender_live for more details

import numpy as np
import pandas

#Class for Popularity based Recommender System model
class popularity_recommender_py():
    def __init__(self):
        self.train_data = None
        self.user_id = None
        self.item_id = None
        self.popularity_recommendations = None
        
    #Create the popularity based recommender system model
    def create(self, train_data, user_id, item_id):
        self.train_data = train_data
        self.user_id = user_id
        self.item_id = item_id

        #Get a count of user_ids for each unique song as recommendation score
        train_data_grouped = train_data.groupby([self.item_id]).agg({self.user_id: 'count'}).reset_index()
        train_data_grouped.rename(columns = {user_id: 'score'},inplace=True)
    
        #Sort the songs based upon recommendation score
        train_data_sort = train_data_grouped.sort_values(['score', self.item_id], ascending = [0,1])
    
        #Generate a recommendation rank based upon score
        train_data_sort['Rank'] = train_data_sort['score'].rank(ascending=0, method='first')
        
        #Get the top 10 recommendations
        self.popularity_recommendations = train_data_sort.head(10)

    #Use the popularity based recommender system model to
    #make recommendations
    def recommend(self, user_id):    
        user_recommendations = self.popularity_recommendations
        
        #Add user_id column for which the recommendations are being generated
        user_recommendations['user_id'] = user_id
    
        #Bring user_id column to the front
        cols = user_recommendations.columns.tolist()
        cols = cols[-1:] + cols[:-1]
        user_recommendations = user_recommendations[cols]
        
        return user_recommendations
    

#Class for Item similarity based Recommender System model
class item_similarity_recommender_py():
    def __init__(self):
        self.train_data = None
        self.user_id = None
        self.item_id = None
        self.cooccurence_matrix = None
        self.songs_dict = None
        self.rev_songs_dict = None
        self.item_similarity_recommendations = None
        
    #Get unique items (songs) corresponding to a given user
    def get_user_items(self, user):
        user_data = self.train_data[self.train_data[self.user_id] == user]
        user_items = list(user_data[self.item_id].unique())
        
        return user_items
        
    #Get unique users for a given item (song)
    def get_item_users(self, item):
        item_data = self.train_data[self.train_data[self.item_id] == item]
        item_users = set(item_data[self.user_id].unique())
            
        return item_users
        
    #Get unique items (songs) in the training data
    def get_all_items_train_data(self):
        all_items = list(self.train_data[self.item_id].unique())
            
        return all_items
        
    #Construct cooccurence matrix
    def construct_cooccurence_matrix(self, user_songs, all_songs):
            
        ####################################
        #Get users for all songs in user_songs.
        # 现在要计算的是给我选中的测试用户推荐什么
        # 流程如下
        # 1. 先把选中的测试用户听过的歌曲都拿到
        # 2. 找出这些歌曲中每一个歌曲都被那些其他用户听过
        # 3. 在整个歌曲集中遍历每一个歌曲,计算它与选中测试用户中每一个听过歌曲的Jaccard相似系数
        # 通过听歌的人的交集与并集情况来计算
        ####################################
        user_songs_users = []        
        for i in range(0, len(user_songs)):
            user_songs_users.append(self.get_item_users(user_songs[i]))
            
        ###############################################
        #Initialize the item cooccurence matrix of size 
        #len(user_songs) X len(songs)
        ###############################################
        cooccurence_matrix = np.matrix(np.zeros(shape=(len(user_songs), len(all_songs))), float)
           
        #############################################################
        #Calculate similarity between user songs and all unique songs
        #in the training data
        #############################################################
        for i in range(0,len(all_songs)):
            #Calculate unique listeners (users) of song (item) i
            songs_i_data = self.train_data[self.train_data[self.item_id] == all_songs[i]]
            users_i = set(songs_i_data[self.user_id].unique())
            
            for j in range(0,len(user_songs)):       
                    
                #Get unique listeners (users) of song (item) j
                users_j = user_songs_users[j]
                    
                #Calculate intersection of listeners of songs i and j
                users_intersection = users_i.intersection(users_j)
                
                #Calculate cooccurence_matrix[i,j] as Jaccard Index
                if len(users_intersection) != 0:
                    #Calculate union of listeners of songs i and j
                    users_union = users_i.union(users_j)
                    
                    cooccurence_matrix[j,i] = float(len(users_intersection))/float(len(users_union))
                else:
                    cooccurence_matrix[j,i] = 0
                    
        
        return cooccurence_matrix

    
    #Use the cooccurence matrix to make top recommendations
    def generate_top_recommendations(self, user, cooccurence_matrix, all_songs, user_songs):
        print("Non zero values in cooccurence_matrix :%d" % np.count_nonzero(cooccurence_matrix))
        
        #Calculate a weighted average of the scores in cooccurence matrix for all user songs.
        user_sim_scores = cooccurence_matrix.sum(axis=0)/float(cooccurence_matrix.shape[0])
        user_sim_scores = np.array(user_sim_scores)[0].tolist()
 
        #Sort the indices of user_sim_scores based upon their value
        #Also maintain the corresponding score
        sort_index = sorted(((e,i) for i,e in enumerate(list(user_sim_scores))), reverse=True)
    
        #Create a dataframe from the following
        columns = ['user_id', 'song', 'score', 'rank']
        #index = np.arange(1) # array of numbers for the number of samples
        df = pandas.DataFrame(columns=columns)
         
        #Fill the dataframe with top 10 item based recommendations
        rank = 1 
        for i in range(0,len(sort_index)):
            if ~np.isnan(sort_index[i][0]) and all_songs[sort_index[i][1]] not in user_songs and rank <= 10:
                df.loc[len(df)]=[user,all_songs[sort_index[i][1]],sort_index[i][0],rank]
                rank = rank+1
        
        #Handle the case where there are no recommendations
        if df.shape[0] == 0:
            print("The current user has no songs for training the item similarity based recommendation model.")
            return -1
        else:
            return df
 
    #Create the item similarity based recommender system model
    def create(self, train_data, user_id, item_id):
        self.train_data = train_data
        self.user_id = user_id
        self.item_id = item_id

    #Use the item similarity based recommender system model to
    #make recommendations
    def recommend(self, user):
        
        ########################################
        #A. Get all unique songs for this user
        ########################################
        user_songs = self.get_user_items(user)    
            
        print("No. of unique songs for the user: %d" % len(user_songs))
        
        ######################################################
        #B. Get all unique items (songs) in the training data
        ######################################################
        all_songs = self.get_all_items_train_data()
        
        print("no. of unique songs in the training set: %d" % len(all_songs))
         
        ###############################################
        #C. Construct item cooccurence matrix of size 
        #len(user_songs) X len(songs)
        ###############################################
        cooccurence_matrix = self.construct_cooccurence_matrix(user_songs, all_songs)
        
        #######################################################
        #D. Use the cooccurence matrix to make recommendations
        #######################################################
        df_recommendations = self.generate_top_recommendations(user, cooccurence_matrix, all_songs, user_songs)
                
        return df_recommendations
    
    #Get similar items to given items
    def get_similar_items(self, item_list):
        
        user_songs = item_list
        
        ######################################################
        #B. Get all unique items (songs) in the training data
        ######################################################
        all_songs = self.get_all_items_train_data()
        
        print("no. of unique songs in the training set: %d" % len(all_songs))
         
        ###############################################
        #C. Construct item cooccurence matrix of size 
        #len(user_songs) X len(songs)
        ###############################################
        cooccurence_matrix = self.construct_cooccurence_matrix(user_songs, all_songs)
        
        #######################################################
        #D. Use the cooccurence matrix to make recommendations
        #######################################################
        user = ""
        df_recommendations = self.generate_top_recommendations(user, cooccurence_matrix, all_songs, user_songs)
         
        return df_recommendations

整体的代码量还是比较多,我先从整体上介绍这段代码做了一件什么事,大家在自己玩的时候最好按照我之前说的还是debug一遍更舒服。首先我们要针对某一个用户进行推荐,那必然得先得到他都听过哪些歌曲,通过这些已被听过的歌曲跟整个数据集中的歌曲进行对比,看哪些歌曲跟用户已听过的比较类似,推荐的就是这些类似的。如何计算呢?

例如当前用户听过了66首歌曲,整个数据集中有4879个歌曲,我们要做的就是构建一个[66,4879]的矩阵,其中每一个值表示用户听过的每一个歌曲和数据集中每一个歌曲的相似度。这里使用Jaccard相似系数,矩阵中[i,j]的含义就是用户听过的第i首歌曲这些歌曲被哪些人听过,比如有3000人听过,数据集中的j歌曲被哪些人听过,比如有5000人听过。Jaccard相似系数就要求:

在这里插入图片描述

说白了就是如果两个歌曲很相似,那其受众应当是一致的,交集/并集的比例应该比较大,如果两个歌曲没啥相关性,其值应当就比较小了。
上述代码中计算了矩阵[66,4879]中每一个位置的值应当是多少,在最后推荐的时候我们还应当注意一件事对于数据集中每一个待推荐的歌曲都需要跟该用户所有听过的歌曲计算其Jaccard值,例如歌曲j需要跟用户听过的66个歌曲计算其值,最终是否推荐的得分值还得进行处理,即把这66个值加在一起,最终求一个平均值,来代表该歌曲的推荐得分。

#执行推荐
is_model.recommend(user_id)

在这里插入图片描述

3.3 基于矩阵分解(SVD)的推荐

相似度计算的方法看起来比较简单就是实现出来,但是当数据较大的时候计算的时间消耗实在太大了,对每一个用户都需要多次遍历整个数据集来进行计算,矩阵分解的方法是当下更常使用的方法。

奇异值分解(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

输出:

<99996x30000 sparse matrix of type '<class 'numpy.float64'>'
	with 10774558 stored elements in COOrdinate format>

上面代码先根据用户进行分组,计算每个用户的总的播放总量,然后用每首歌的播放总量相除,得到每首歌的分值,最后一列特征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)

这里我们选择K值等于50,其中PID表示我们最开始选择的部分歌曲,UID表示我们选择的部分用户。

接下来我们需要选择待测试用户了:

uTest = [4,5,6,7,8,873,23]

随便选择一些用户就好,这里表示用户的索引编号,接下来需要对每一个用户计算其对我们候选集中3W首歌曲的喜好程度,说白了就是估计他对这3W首歌的评分值应该等于多少,前面我们通过SVD矩阵分解已经计算所需各个小矩阵了,接下来把其还原回去就可以啦:

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

输出:

Recommendation for user with user id 4
The number 1 recommended song is Fireflies BY Charttraxx Karaoke
The number 2 recommended song is Hey_ Soul Sister BY Train
The number 3 recommended song is OMG BY Usher featuring will.i.am
The number 4 recommended song is Lucky (Album Version) BY Jason Mraz & Colbie Caillat
The number 5 recommended song is Vanilla Twilight BY Owl City
The number 6 recommended song is Crumpshit BY Philippe Rochard
The number 7 recommended song is Billionaire [feat. Bruno Mars]  (Explicit Album Version) BY Travie McCoy
The number 8 recommended song is Love Story BY Taylor Swift
The number 9 recommended song is TULENLIEKKI BY M.A. Numminen
The number 10 recommended song is Use Somebody BY Kings Of Leon
Recommendation for user with user id 5
The number 1 recommended song is Sehr kosmisch BY Harmonia
The number 2 recommended song is Ain't Misbehavin BY Sam Cooke
The number 3 recommended song is Dog Days Are Over (Radio Edit) BY Florence + The Machine
The number 4 recommended song is Revelry BY Kings Of Leon
The number 5 recommended song is Undo BY Björk
The number 6 recommended song is Cosmic Love BY Florence + The Machine
The number 7 recommended song is Home BY Edward Sharpe & The Magnetic Zeros
The number 8 recommended song is You've Got The Love BY Florence + The Machine
The number 9 recommended song is Bring Me To Life BY Evanescence
The number 10 recommended song is Tighten Up BY The Black Keys
Recommendation for user with user id 6
The number 1 recommended song is Crumpshit BY Philippe Rochard
The number 2 recommended song is Marry Me BY Train
The number 3 recommended song is Hey_ Soul Sister BY Train
The number 4 recommended song is Lucky (Album Version) BY Jason Mraz & Colbie Caillat
The number 5 recommended song is One On One BY the bird and the bee
The number 6 recommended song is I Never Told You BY Colbie Caillat
The number 7 recommended song is Canada BY Five Iron Frenzy
The number 8 recommended song is Fireflies BY Charttraxx Karaoke
The number 9 recommended song is TULENLIEKKI BY M.A. Numminen
The number 10 recommended song is Bring Me To Life BY Evanescence
Recommendation for user with user id 7
The number 1 recommended song is Behind The Sea [Live In Chicago] BY Panic At The Disco
The number 2 recommended song is The City Is At War (Album Version) BY Cobra Starship
The number 3 recommended song is Dead Souls BY Nine Inch Nails
The number 4 recommended song is Una Confusion BY LU
The number 5 recommended song is Home BY Edward Sharpe & The Magnetic Zeros
The number 6 recommended song is Climbing Up The Walls BY Radiohead
The number 7 recommended song is Tighten Up BY The Black Keys
The number 8 recommended song is Tive Sim BY Cartola
The number 9 recommended song is West One (Shine On Me) BY The Ruts
The number 10 recommended song is Cosmic Love BY Florence + The Machine
Recommendation for user with user id 8
The number 1 recommended song is Undo BY Björk
The number 2 recommended song is Canada BY Five Iron Frenzy
The number 3 recommended song is Better To Reign In Hell BY Cradle Of Filth
The number 4 recommended song is Unite (2009 Digital Remaster) BY Beastie Boys
The number 5 recommended song is Behind The Sea [Live In Chicago] BY Panic At The Disco
The number 6 recommended song is Rockin' Around The Christmas Tree BY Brenda Lee
The number 7 recommended song is Devil's Slide BY Joe Satriani
The number 8 recommended song is Revelry BY Kings Of Leon
The number 9 recommended song is 16 Candles BY The Crests
The number 10 recommended song is Catch You Baby (Steve Pitron & Max Sanna Radio Edit) BY Lonnie Gordon
Recommendation for user with user id 873
The number 1 recommended song is The Scientist BY Coldplay
The number 2 recommended song is Yellow BY Coldplay
The number 3 recommended song is Clocks BY Coldplay
The number 4 recommended song is Fix You BY Coldplay
The number 5 recommended song is In My Place BY Coldplay
The number 6 recommended song is Shiver BY Coldplay
The number 7 recommended song is Speed Of Sound BY Coldplay
The number 8 recommended song is Creep (Explicit) BY Radiohead
The number 9 recommended song is Sparks BY Coldplay
The number 10 recommended song is Use Somebody BY Kings Of Leon
Recommendation for user with user id 23
The number 1 recommended song is Garden Of Eden BY Guns N' Roses
The number 2 recommended song is Don't Speak BY John Dahlbäck
The number 3 recommended song is Master Of Puppets BY Metallica
The number 4 recommended song is TULENLIEKKI BY M.A. Numminen
The number 5 recommended song is Bring Me To Life BY Evanescence
The number 6 recommended song is Kryptonite BY 3 Doors Down
The number 7 recommended song is Make Her Say BY Kid Cudi / Kanye West / Common
The number 8 recommended song is Night Village BY Deep Forest
The number 9 recommended song is Better To Reign In Hell BY Cradle Of Filth
The number 10 recommended song is Xanadu BY Olivia Newton-John;Electric Light Orchestra

这里对每一个用户都得到了其对应的推荐结果,并且将结果按照得分值进行排序。

4. 总结

本文选择了音乐数据集来进行个性化推荐任务,首先对数据进行预处理和整合,选择两种方法分别完成推荐任务。在相似度计算中根据用户所听过的歌曲在候选集中选择与其最相似的歌曲,存在的问题就是计算时间消耗太多,每一个用户都需要重新计算一遍才能得出推荐结果。在SVD矩阵分解的方法中,我们首先构建评分矩阵,对其进行SVD分解,然后选择待推荐用户,还原得到其对所有歌曲的估测评分值,最后排序返回结果即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/593126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

市面上流行的 5 大网页制作工具总结

这里是对市面上流行的 5 大网页制作工具的总结&#xff1a; 1. 即时设计 即时设计是一款国内新一代在线协作设计工具&#xff0c;具备原型、设计、交付、协作和资源管理等功能&#xff0c;适合个人用户和团队使用。它提供丰富的社区设计资源和原型模板&#xff0c;支持 UI/UX…

Python 的十大特性

摘要 在了解 Python 的特性之前&#xff0c;我们首先要了解 Python 编程语言是什么。Python 编程语言是世界上发展最快的编程语言。这一高级通用编程语言提供了广泛的实际应用&#xff0c;并且是一种非常流行的认证。 Python 可以让程序员更加高效地工作和集成系统。Python 的…

vue中如何通过iframe方式加载本地的vue页面

这个需求一般很少能遇到&#xff0c;只要说去了iframe&#xff0c;很多人就会唾弃。 但是有时候的确无法避免使用它&#xff0c;当iframe的特性带来的优势远远高于自己用div模拟的时候 啥时候需要用到iframe加载本地的vue文件呢 我在写一个demo&#xff0c;我需要demo效果模拟…

【接口测试】神器JMeter

‍1 JMeter是什么 Apache JMeter是Apache组织开发的一款开源软件&#xff0c;是一款非常好用的接口测试工具。它的特点是开源免费&#xff0c;简单好用。 我们在测试过程需要做接口测试的话就可以使用它&#xff0c;也可以用来批量造数据&#xff0c;接下来我们就来看看JMete…

Django框架之验证码简单实现

是一种方式防止csrf的策略。在用户注册、登录页面的时候使用&#xff1b;为了防止暴力请求&#xff0c;减轻服务器压力。 目录 安装pillow库 验证码显示 引入类库 视图方法 创建路由 创建表单 模板内容 模板路由 模板视图 视图验证 路由 引入 验证视图 效果 成功…

从7K到20K,在测试行业摸爬滚打的这5年,想个2023年还没找到工作的提个醒~

我是一名转IT测试人&#xff0c;我的专业是化学&#xff0c;去化工厂实习才发现这专业的坑人之处&#xff0c;化学试剂害人不浅&#xff0c;有毒&#xff0c;易燃易爆&#xff0c;实验室经常用丙酮&#xff0c;甲醇&#xff0c;四氯化碳&#xff0c;接触多了&#xff0c;吃个饭…

JMeter 接口测试教程,详解 HTTP Request 取样器和 fiddler 调试技巧!

目录 前言&#xff1a; 一、HTTP Request取样器介绍 二、使用HTTP Request取样器进行接口调试 1. 创建测试计划&#xff08;Test Plan&#xff09;和线程组&#xff08;Thread Group&#xff09; 2. 配置HTTP Request取样器参数 3. 添加断言 4. 运行接口测试 三、结合f…

Linux 企业级安全原理和防范技巧

Linux 企业级安全原理和防范技巧 1. 企业级Linux系统防护概述1.1 企业级Linux系统安全威胁1.2 企业级Linux系统安全立体式防范体系1.2.1 Linux文件系统访问安全1.2.2 Linux进程安全1. 进程的种类2. 进程管理方法 1.2.3 Linux用户管理安全1. 管理用户及组文件安全2. 用户密码管理…

【云计算】云存储是什么意思?与本地存储有什么区别?

云计算环境下&#xff0c;衍生了云存储、云安全、云资源、云管理、云支出等等概念。今天我们就来了解下什么是云存储&#xff1f;云存储与本地存储有什么区别&#xff1f; 云存储是什么意思&#xff1f; 云存储是一种新型的数据管理方式&#xff0c;它通过网络将大量不同类型、…

UGUI进阶知识[二十九]循环GridView

节省内存的常用滑动列表还有一种形式&#xff0c;上下滑动的GridView。这种格式的滑动列表可用于移动设备的背包&#xff0c;仓库&#xff0c;商店UI等数据可能海量从而导致产生特别多但又看不见的UI的情况。 于是基于 UGUI进阶知识[八]循环利用滑动列表的循环ListView工程做了…

普源1G带宽4通道10G采样率数字示波器MSO8104

超高性价比七合一 集成示波器在如今的集成设计领域&#xff0c;一款集成度较高的综合示波器已经成为设计工程师必不可少的得力工具。 MSO8000 系列数字示波器&#xff0c;它集 7 种独立仪器于一体&#xff0c;包括一台示波器、一台 16 通道逻辑分析仪、一台频谱分析仪、一台任…

煤矿电子封条建设实施方案算法 yolov7

煤矿电子封条建设实施方案算法通过yolov7网络模型深度学习技术&#xff0c;煤矿电子封条建设实施方案算法作为一种智能化安全新模式被广泛应用于各类场景中。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研究团队希望它能够同时支持移动 GPU 和从边缘到云端的…

高完整性系统:Separation Logic for Automated Verification

目录 1. INTRODUCTION TO SEPARATION LOGIC 分离逻辑 1.1 霍尔推理&#xff08;Hoare Reasoning&#xff09; 1.2 堆指针的影响 1.3 全局和局部推理&#xff08;Global and Local Reasoning&#xff09; 1.4 组合推理&#xff08;Compositional Reasoning&#xff09; 1.…

chatgpt赋能python:Python中怎样输入数据以及数据类型

Python中怎样输入数据以及数据类型 Python是一种高级编程语言&#xff0c;常用于数据处理和分析、机器学习和Web开发等任务。输入数据是Python编程中的重要环节&#xff0c;因此本文将介绍Python中输入数据的方法和数据类型。 什么是数据输入&#xff1f; 数据输入是指将数据…

国内主流AI大模型盘点

今年年初&#xff0c;轰动科技圈的大事就是ChatGPT的面世&#xff0c;它的到来打响了AI智能时代的第一枪&#xff0c;同时展开了一场别开生面的智能科技革命。 随着ChatGPT迅速走红,国内各大企业纷纷发力认知大模型领域。经过一段时间的酝酿&#xff0c;国内的AI领域也开启了“…

StableStudio,比Midjourney还牛逼的绘画平台,免费!

大家好&#xff0c;我是鸟哥。 之前给大家推荐过Midjourney和Bluewillow两个AI绘画平台&#xff1a;简直了&#xff01;比Midjourney更刺激&#xff0c;还免费&#xff01;Midjourney功能超级强大&#xff0c;但比较傲娇&#xff0c;很贵&#xff0c;是否让用户免费体验要看心…

数据可视化系列指南之地图类图表大全

导语 随着数据在各行业中的应用越来越广泛&#xff0c;大家也逐渐认识到数据可视化在企业生产经营中的重要作用&#xff0c;在数据可视化过程中&#xff0c;图表是处理数据的重要组成部分&#xff0c;因为它们是一种将大量数据压缩为易于理解的格式的方法。数据可视化可以让受…

jar包和war包的区别;项目打包成jar或者war且运行在Linux上的tomcat

jar包和war包的区别&#xff1a; war包&#xff1a;通常是web应用后&#xff0c;例如网站&#xff0c;打成包部署到容器(可以是tomcat)中。含有包括WEB-INF包。war包通常就是放在tomcat包的/webapps下然后自动编译和运行。 jar包&#xff1a;通常是开发时要引用的类&#xff…

怎样使用Fiddler进行移动端抓包?附视频教程包你学会

目录 前言 抓包 什么是抓包 哪些场景下需要抓包 Fiddler Fiddler抓包原理 安装 Fiddler移动端抓包 第一步&#xff1a;允许远程计算机连接 第二步&#xff0c;设置手机网络代理 第三步&#xff0c;允许捕获HTTPS连接 第四步&#xff0c;手机安装证书 前言 本篇文章…

chatgpt赋能python:Python中如何提取字段中的数字

Python中如何提取字段中的数字 在数据分析和处理中&#xff0c;经常需要提取文本中的数字数据。在Python中&#xff0c;有多种方法可以实现这一操作。本篇文章将介绍Python中提取字段中的数字的方法&#xff0c;并给出示例代码。 使用正则表达式 正则表达式是Python中处理文…