spark音乐推荐系统源码 协同过滤音乐推荐 技术栈:springboot vue 协同过滤算...
spark音乐推荐系统源码 协同过滤音乐推荐 技术栈:springboot vue 协同过滤算法 算法:als基于模型协同过滤 用户行为:近一年听歌日志与收藏记录,听一次歌算1分,收藏算5分
搞音乐推荐系统最带劲的就是看着算法从用户行为里挖出宝藏。这次用SpringBoot+Vue搭了个推荐系统,核心算法选了ALS协同过滤,处理用户近一年的听歌日志和收藏记录。听一次歌算1分,收藏直接给5分,这权重设置得够狠吧?
数据炼金术
原始日志长得像这样:
user_id | song_id | action_type | timestamp
1024 | 8876 | play | 2023-03-12 14:23
1024 | 7765 | collect | 2023-03-12 14:25
用Spark做数据清洗时,发现个有趣现象——某些用户收藏了从没听过的歌。处理逻辑得加个判断:只有听过才能收藏。下面这段Scala代码负责生成训练数据:
val rawData = spark.read.parquet("hdfs://music_logs/*.parquet")
val validActions = rawData.filter(
(col("action_type") === "collect" && col("song_id").isin(playedSongs)) ||
col("action_type") === "play"
)
val ratingData = validActions.groupBy("user_id", "song_id")
.agg(
sum(when(col("action_type") === "collect", 5).otherwise(1)).alias("rating")
)
这段代码干了三件事:过滤无效收藏、按用户-歌曲分组、用when表达式计算评分。有个坑点是collect动作可能比play多,所以用了isin(playedSongs)来约束。
ALS实战现场
spark音乐推荐系统源码 协同过滤音乐推荐 技术栈:springboot vue 协同过滤算法 算法:als基于模型协同过滤 用户行为:近一年听歌日志与收藏记录,听一次歌算1分,收藏算5分
矩阵分解就像把用户和歌曲的关系拆成两个矩阵相乘。Spark的ALS实现用起来是真香:
val als = new ALS()
.setRank(10)
.setMaxIter(15)
.setRegParam(0.01)
.setUserCol("user_id")
.setItemCol("song_id")
.setRatingCol("rating")
val model = als.fit(ratingData)
参数调教是个玄学活。rank=10是试出来的——设小了模型太笨,大了又过拟合。迭代15次后loss基本稳定,正则化参数0.01防止放飞自我。训练完记得处理冷启动:
model.setColdStartStrategy("drop") // 直接过滤未知用户/歌曲
推荐服务落地
SpringBoot里搞了个推荐接口,核心逻辑是这样的:
@GetMapping("/recommend/{userId}")
public List<Song> getRecommendations(@PathVariable String userId) {
Dataset<Row> userDF = spark.createDataFrame(
Collections.singletonList(new User(userId)),
User.class
);
Dataset<Row> recs = model.recommendForUserSubset(userDF, 20);
return convertToSongList(recs); // 转成前端需要的VO
}
有个性能优化点:别在每次请求都加载模型。实战中用了单例模式持有SparkSession和ALS模型,避免重复加载开销。
前端骚操作
Vue这边有个细节挺有意思——当推荐列表出现用户收藏过的歌时,得做去重处理:
watch: {
recommendations(newVal) {
this.filteredList = newVal.filter(
song => !this.collectedSongs.has(song.id)
)
}
}
这比在后端过滤更灵活,毕竟用户收藏状态可能实时变化。
踩坑实录
- 内存爆过两次,后来发现是笛卡尔积计算时没控制分区数,加了个repartition(1000)才稳住
- 初期没处理隐式反馈,导致推荐结果全是热门歌曲。加了权重衰减因子才解决
- Vue的无限滚动加载和推荐分数排序打架,最后用了个混合排序策略才顺眼
这套系统上线后,有个意外发现——那些收藏分高的冷门歌曲推荐效果出奇好。可能用户觉得收藏是"真爱认证",这波评分规则算是赌对了。下次想试试把分享行为也加进去,说不定能挖出更多宝藏歌曲。

更多推荐
所有评论(0)