🎧 基于 Python 的深度学习音乐推荐系统设计与实现
✨ 前言
在数字音乐高速发展的今天,如何为用户推荐他们可能喜欢的歌曲,成为各大平台竞争的核心。传统的基于协同过滤的推荐算法已广泛应用,但随着用户兴趣多样化、数据稀疏性提升,深度学习正逐步在推荐系统中展现出强大优势。
本文将带你一步一步搭建一个基于 Python 与深度学习的音乐推荐系统,从数据预处理到模型训练、再到预测接口,涵盖完整实现流程,适用于毕业设计、企业项目实践或学习研究使用。
🧠 一、项目目标与技术路线
我们将构建一个融合协同过滤与神经网络的音乐推荐系统:
- 🎯 支持根据用户听歌记录,推荐相似歌曲;
- 🎯 实现基于神经网络的推荐模型(NCF);
- 🎯 提供命令行或 Flask 接口调用预测结果;
- 🎯 模块化结构,便于扩展与部署。
技术选型
模块 | 技术 |
---|---|
语言 | Python 3.8+ |
模型框架 | PyTorch |
数据处理 | pandas + pickle |
推荐算法 | Surprise(协同过滤)+ NCF(深度学习) |
接口服务 | Flask(可选) |
📦 二、数据预处理模块设计
我们使用一个格式为 .playlist
的本地文件,每行包含一个歌单信息及其包含的歌曲列表。
歌单名称##标签##歌单ID##收藏数 \t 歌曲ID:::歌曲名:::歌手:::热度 \t ...
示例代码:解析歌单
import pickle
def parse_playlist_get_info(in_line, playlist_dic, song_dic):
contents = in_line.strip().split("\t")
name, tags, playlist_id, subscribed_count = contents[0].split("##")
playlist_dic[playlist_id] = name
for song in contents[1:]:
try:
song_id, song_name, artist, popularity = song.split(":::")
song_dic[song_id] = song_name
except:
continue
def parse_file(in_file, out_playlist, out_song):
playlist_dic, song_dic = {}, {}
for line in open(in_file, 'r', encoding='UTF-8'):
parse_playlist_get_info(line, playlist_dic, song_dic)
pickle.dump(playlist_dic, open(out_playlist, "wb"))
pickle.dump(song_dic, open(out_song, "wb"))
🎯 三、基于 Surprise 的协同过滤推荐
Surprise 是一个流行的推荐系统库,适用于快速构建协同过滤模型。
模型训练(基于歌曲)
from surprise import Dataset, Reader, KNNBaseline
import surprise
import os
def train_item_model(file_path):
reader = Reader(line_format='user item rating timestamp', sep=',')
data = Dataset.load_from_file(file_path, reader=reader)
trainset = data.build_full_trainset()
algo = KNNBaseline(sim_options={'user_based': False})
algo.fit(trainset)
surprise.dump.dump('./model/KNNBaseline_Item.model', algo=algo)
模型训练完成后,可使用以下接口推荐与某首歌相似的歌曲:
def predict_by_song(song_name):
song_dic = pickle.load(open("song_id_name_dic.pkl", "rb"))
song_name_id = {v: k for k, v in song_dic.items()}
_, algo = surprise.dump.load('./model/KNNBaseline_Item.model')
inner_id = algo.trainset.to_inner_iid(song_name_id[song_name])
neighbors = algo.get_neighbors(inner_id, k=10)
return [song_dic[algo.trainset.to_raw_iid(n)] for n in neighbors]
🔥 四、基于 PyTorch 的深度学习推荐(NCF)
4.1 模型设计(Embedding + MLP)
import torch.nn as nn
import torch
class NCFModel(nn.Module):
def __init__(self, num_users, num_items, emb_dim=32):
super(NCFModel, self).__init__()
self.user_emb = nn.Embedding(num_users, emb_dim)
self.item_emb = nn.Embedding(num_items, emb_dim)
self.fc = nn.Sequential(
nn.Linear(emb_dim * 2, 64),
nn.ReLU(),
nn.Linear(64, 16),
nn.ReLU(),
nn.Linear(16, 1),
nn.Sigmoid()
)
def forward(self, user, item):
u = self.user_emb(user)
i = self.item_emb(item)
x = torch.cat([u, i], dim=1)
return self.fc(x).squeeze()
4.2 构建训练数据
import pandas as pd
from sklearn.preprocessing import LabelEncoder
def preprocess_data(csv_file):
df = pd.read_csv(csv_file)
user_enc = LabelEncoder()
item_enc = LabelEncoder()
df['user_id'] = user_enc.fit_transform(df['user_id'])
df['item_id'] = item_enc.fit_transform(df['item_id'])
return df, user_enc, item_enc
4.3 训练过程
from torch.utils.data import Dataset, DataLoader
import torch.optim as optim
class MusicDataset(Dataset):
def __init__(self, df):
self.users = torch.tensor(df['user_id'].values)
self.items = torch.tensor(df['item_id'].values)
self.labels = torch.tensor(df['label'].values, dtype=torch.float32)
def __getitem__(self, idx):
return self.users[idx], self.items[idx], self.labels[idx]
def __len__(self):
return len(self.labels)
def train_ncf(df, num_users, num_items):
dataset = MusicDataset(df)
loader = DataLoader(dataset, batch_size=128, shuffle=True)
model = NCFModel(num_users, num_items)
loss_fn = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
total_loss = 0
for u, i, l in loader:
pred = model(u, i)
loss = loss_fn(pred, l)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {total_loss:.4f}")
torch.save(model.state_dict(), "./model/ncf.pth")
return model
🚀 五、预测接口(可选 Flask 服务)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/recommend', methods=['POST'])
def recommend():
song = request.json['song']
results = predict_by_song(song)
return jsonify({"推荐结果": results})
if __name__ == '__main__':
app.run(debug=True)
✅ 六、系统亮点总结
- ✅ 支持协同过滤与深度学习推荐双引擎;
- ✅ 支持歌曲相似推荐、歌单相似推荐;
- ✅ 模块化结构,便于迁移与部署;
- ✅ 兼容批量预测与Web服务;
- ✅ 可拓展支持情感分析、歌词匹配、流派分类等高级功能。
📚 七、未来优化方向
方向 | 说明 |
---|---|
✳ 多模态推荐 | 融合歌词文本、歌曲旋律向量、用户行为等 |
✳ 强化学习推荐 | 引入用户反馈迭代优化推荐 |
✳ 协同训练 | 与现有推荐系统(网易云 / QQ音乐)数据融合 |