You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark ML ALS推荐算法为何返回用户已观看的项目?

为什么Spark ALS推荐会包含用户已观看的项目?

嘿,这个问题我之前做推荐系统的时候也踩过坑!其实Spark ML里的ALS算法默认就是不会自动排除用户已经交互过的项目的,原因主要有这几点:

  • 核心逻辑未内置历史过滤:ALS的recommendForAllUsers方法本质是基于用户和物品的隐因子向量计算预测评分,然后返回每个用户评分最高的N个物品。它完全不会去比对你的training数据集里的历史交互记录——哪怕某个电影是用户已经看过的,只要模型算出的预测评分够高(比如用户之前给过五星,模型预测分也拉满),就会被放进推荐结果里。
  • 设计上的灵活性考量:Spark把是否过滤历史交互的决定权交给了开发者。毕竟有些场景是需要推荐重复内容的——比如视频平台用户可能会反复刷喜欢的老剧,所以ALS不硬做过滤,让你根据业务需求自行处理。

解决办法:手动过滤历史交互记录

要得到只包含新项目的推荐,你需要把用户的历史观看数据和推荐结果做一次过滤,用Spark的DataFrame操作就能轻松实现。以下是Python版的示例代码:

from pyspark.sql import functions as F

# 1. 提取用户的历史观看记录(去重,避免重复过滤)
user_history = training.select("userId", "movieId").distinct()

# 2. 展开推荐结果,把嵌套的recommendations字段拆成单行数据
user_recs_exploded = userRecs.select(
    "userId",
    F.explode("recommendations").alias("rec")
).select(
    "userId",
    F.col("rec.movieId").alias("recommended_movieId"),
    F.col("rec.rating").alias("predicted_rating")
)

# 3. 用左反连接过滤掉用户已经看过的电影
# 左反连接会保留user_recs_exploded中不在user_history里的记录
filtered_recs = user_recs_exploded.join(
    user_history,
    (user_recs_exploded["userId"] == user_history["userId"]) & 
    (user_recs_exploded["recommended_movieId"] == user_history["movieId"]),
    how="left_anti"
)

# 4. 重新按用户分组,取预测评分最高的Top 10作为最终推荐
final_user_recs = filtered_recs.groupBy("userId").agg(
    F.sort_array(F.collect_list(F.struct("predicted_rating", "recommended_movieId")), ascending=False).alias("recommendations")
).select("userId", "recommendations")

这样处理之后,final_user_recs里就只会包含用户没看过的新项目啦!

内容的提问来源于stack exchange,提问作者peleitor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 22:17:31