这个基于ThinkPHP框架和协同过滤算法的音乐推荐系统,是我在开发音乐类应用时的一个实战项目。它的核心目标是通过分析用户的历史行为数据,为每个用户生成个性化的音乐推荐列表,解决传统音乐平台"千人一面"的推荐痛点。
在实际应用中,我发现很多音乐平台的推荐效果并不理想——要么重复推荐用户已经听过的歌曲,要么推荐完全不相关的曲风。这个系统通过协同过滤算法,能够挖掘出用户潜在的音乐偏好,实现真正的"猜你喜欢"。
系统采用B/S架构,前端使用Vue.js实现响应式交互,后端基于ThinkPHP 6.0开发,数据库选用MySQL存储用户行为数据和音乐元数据,推荐算法部分用Python实现并通过接口与PHP交互。整套系统可以在2GB内存的服务器上流畅运行,特别适合中小型音乐平台使用。
传统音乐推荐主要面临三个核心问题:
选择ThinkPHP作为后端框架主要基于:
协同过滤算法选择基于:
code复制前端层(Vue.js)
↑↓ HTTP/JSON
应用层(ThinkPHP)
↑↓ 内部API
服务层(Python算法服务)
↑↓ MySQL协议
数据层(MySQL + Redis)
用户行为采集模块:
推荐算法模块:
首先需要构建用户对歌曲的偏好矩阵:
python复制# 偏好得分计算规则
def calc_preference(play_count, like_weight=2, share_weight=3):
return play_count + (like_weight * like_count) + (share_weight * share_count)
实际存储时采用稀疏矩阵存储,节省80%以上空间。
使用改进的余弦相似度计算用户相似度:
python复制def cosine_sim(user1, user2):
# 只计算共同评分项
common_items = set(user1.rated_items) & set(user2.rated_items)
if not common_items:
return 0
# 均值中心化处理
mean1 = np.mean(list(user1.ratings.values()))
mean2 = np.mean(list(user2.ratings.values()))
numerator = sum((user1.ratings[item]-mean1)*(user2.ratings[item]-mean2)
for item in common_items)
denom1 = sqrt(sum(pow(user1.ratings[item]-mean1,2) for item in common_items))
denom2 = sqrt(sum(pow(user2.ratings[item]-mean2,2) for item in common_items))
return numerator/(denom1*denom2) if denom1*denom2 !=0 else 0
采用Top-K最近邻算法生成推荐:
python复制def recommend(user_id, k=20, n=10):
# 获取相似用户
similar_users = find_k_neighbors(user_id, k)
# 候选歌曲集合
candidates = {}
for sim_user, similarity in similar_users:
for item in sim_user.rated_items:
if item not in target_user.rated_items:
candidates.setdefault(item, 0)
candidates[item] += similarity * (sim_user.ratings[item] - sim_user.mean_rating)
# 归一化处理
max_score = max(candidates.values()) if candidates else 0
rec_items = sorted(candidates.items(),
key=lambda x: x[1]/max_score if max_score!=0 else 0,
reverse=True)[:n]
return [item[0] for item in rec_items]
矩阵计算加速:
实时推荐优化:
php复制// ThinkPHP中的推荐接口实现
public function getRecommend($userId) {
$cacheKey = "user_rec_{$userId}";
if ($rec = Redis::get($cacheKey)) {
return json_decode($rec, true);
}
$pythonService = new PythonService();
$recList = $pythonService->getRecommendation($userId);
Redis::setex($cacheKey, 3600, json_encode($recList));
return $recList;
}
sql复制CREATE TABLE user_behavior (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
song_id INT NOT NULL,
action_type ENUM('play','like','share') NOT NULL,
action_time DATETIME NOT NULL,
INDEX idx_user (user_id),
INDEX idx_song (song_id)
);
bash复制# 安装Python依赖
pip install -r requirements.txt
# 启动算法服务
gunicorn -w 4 -b 127.0.0.1:5000 algorithm_service:app
env复制# .env文件配置
[ALGORITHM]
SERVER_URL = http://localhost:5000
CACHE_EXPIRE = 3600
php复制// 在ThinkPHP中实现AB测试路由
Route::get('recommend/:id', function($id) {
$abTest = new ABTest();
$group = $abTest->getUserGroup($id);
if ($group == 'A') {
// 原算法
return $this->fetchOriginalRecommend($id);
} else {
// 新算法
return $this->fetchNewRecommend($id);
}
});
测试结果显示新算法使CTR提升了18.7%,但覆盖率下降了5.2%,需要权衡调整。
现象:用户频繁看到相同歌曲推荐
解决方案:
现象:Python服务CPU持续高位
优化措施:
解决方案:
在项目落地过程中,我发现最影响推荐效果的不是算法本身,而是用户行为数据的质量。为此我们开发了专门的数据清洗模块,过滤异常播放记录(如单曲循环整夜的情况),使推荐准确率提升了23%。
另一个重要经验是推荐结果的解释性。我们在界面上增加了"为什么推荐这首歌"的功能,展示"因为您喜欢A歌手"或"您的朋友也在听"等解释,大幅提升了用户对推荐结果的接受度。