【问题标题】:Spark 2.0 ALS Recommendation how to recommend to a userSpark 2.0 ALS Recommendation 如何向用户推荐
【发布时间】:2017-05-05 19:53:55
【问题描述】:

我已按照链接中给出的指南进行操作 http://ampcamp.berkeley.edu/big-data-mini-course/movie-recommendation-with-mllib.html

但这已经过时了,因为它使用 spark Mlib RDD 方法。新 Spark 2.0 具有 DataFrame 方法。 现在我的问题是我得到了更新的代码

val ratings = spark.read.textFile("data/mllib/als/sample_movielens_ratings.txt")
  .map(parseRating)
  .toDF()
val Array(training, test) = ratings.randomSplit(Array(0.8, 0.2))

// Build the recommendation model using ALS on the training data
val als = new ALS()
  .setMaxIter(5)
  .setRegParam(0.01)
  .setUserCol("userId")
  .setItemCol("movieId")
  .setRatingCol("rating")
val model = als.fit(training)
// Evaluate the model by computing the RMSE on the test data
val predictions = model.transform(test)

现在问题来了,在旧代码中,获得的模型是 MatrixFactorizationModel,现在它有自己的模型(ALSModel)

在 MatrixFactorizationModel 你可以直接做

val recommendations = bestModel.get
  .predict(userID)

这将给出用户喜欢它们的概率最高的产品列表。

但是现在没有 .predict 方法。任何想法如何在给定用户 ID 的情况下推荐产品列表

【问题讨论】:

    标签: scala apache-spark machine-learning apache-spark-2.0


    【解决方案1】:

    Spark 中的ALS Model 包含以下有用的方法:

    • recommendForAllItems(int numUsers)

      返回为每个项目、所有项目推荐的前 numUsers 用户。

    • recommendForAllUsers(int numItems)

      为所有用户返回为每个用户推荐的前 numItems 个项目。

    • recommendForItemSubset(Dataset<?> dataset, int numUsers)

      返回为输入数据集中每个项目 id 推荐的前 numUsers 用户。

    • recommendForUserSubset(Dataset<?> dataset, int numItems)

      返回为输入数据集中每个用户 id 推荐的前 numItems 个项目。


    例如蟒蛇

    from pyspark.ml.recommendation import ALS
    from pyspark.sql.functions import explode
    
    alsEstimator = ALS()
    
    (alsEstimator.setRank(1)
      .setUserCol("user_id")
      .setItemCol("product_id")
      .setRatingCol("rating")
      .setMaxIter(20)
      .setColdStartStrategy("drop"))
    
    alsModel = alsEstimator.fit(productRatings)
    
    recommendForSubsetDF = alsModel.recommendForUserSubset(TargetUsers, 40)
    
    recommendationsDF = (recommendForSubsetDF
      .select("user_id", explode("recommendations")
      .alias("recommendation"))
      .select("user_id", "recommendation.*")
    )
    
    display(recommendationsDF)
    

    例如斯卡拉:

    import org.apache.spark.ml.recommendation.ALS
    import org.apache.spark.sql.functions.explode 
    
    val alsEstimator = new ALS().setRank(1)
      .setUserCol("user_id")
      .setItemCol("product_id")
      .setRatingCol("rating")
      .setMaxIter(20)
      .setColdStartStrategy("drop")
    
    val alsModel = alsEstimator.fit(productRatings)
    
    val recommendForSubsetDF = alsModel.recommendForUserSubset(sampleTargetUsers, 40)
    
    val recommendationsDF = recommendForSubsetDF
      .select($"user_id", explode($"recommendations").alias("recommendation"))
      .select($"user_id", $"recommendation.*")
    
    display(recommendationsDF)
    

    【讨论】:

      【解决方案2】:

      这是我为使用spark.ml 获取特定用户推荐所做的工作:

      import com.github.fommil.netlib.BLAS.{getInstance => blas}
      
      userFactors.lookup(userId).headOption.fold(Map.empty[String, Float]) { user =>
      
        val ratings = itemFactors.map { case (id, features) =>
          val rating = blas.sdot(features.length, user, 1, features, 1)
          (id, rating)
        }
      
        ratings.sortBy(_._2).take(numResults).toMap
      }
      

      在我的例子中,userFactorsitemFactors 都是 RDD[(String, Array[Float])],但您应该能够使用 DataFrames 做类似的事情。

      【讨论】:

        【解决方案3】:

        在型号上使用transform方法:

        import spark.implicits._
        val dataFrameToPredict = sparkContext.parallelize(Seq((111, 222)))
            .toDF("userId", "productId")
        val predictionsOfProducts = model.transform (dataFrameToPredict)
        

        有一个jira机票来实现推荐(用户)方法,但它尚未在默认分支中

        现在你有一个分数的Dataframe

        您可以简单地使用orderby和限制来显示N推荐产品:

        // where is for case when we have big DataFrame with many users
        model.transform (dataFrameToPredict.where('userId === givenUserId))
            .select ('productId, 'prediction)
            .orderBy('prediction.desc)
            .limit(N)
            .map { case Row (productId: Int, prediction: Double) => (productId, prediction) }
            .collect()
        

        dataframe dataframetopredict可以是一些大​​的用户 - 产品dataframe,例如所有用户x所有产品

        【讨论】:

        • 变换只会转换给定表,并为该特定用户和电影添加预测值,但我想要一个列表,因为我们将使用userid将来的流,我们可以推荐他的产品。但谢谢你的帮助 span>
        • @ user2983451现在添加了代码来推荐给定用户的n个产品;) span>
        猜你喜欢
        • 1970-01-01
        • 2015-05-21
        • 2017-04-10
        • 2015-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-04
        • 2017-07-09
        相关资源
        最近更新 更多