Рекомендация - создание нового кадра данных с условиями - PullRequest
0 голосов
/ 13 апреля 2020

Я некоторое время изучал Spark, но сегодня я застрял, я работаю в модели Рекомендации, используя набор данных Audioscrobbler.

Моя модель основана на ALS и следующее определение для создания рекомендации:

def makeRecommendations(model: ALSModel, userID: Int,howMany: Int): DataFrame = {
  val toRecommend = model.itemFactors.select($"id".as("artist")).withColumn("user", lit(userID))
     model.transform(toRecommend).
        select("artist", "prediction", "user").
        orderBy($"prediction".desc).
        limit(howMany)
}

Он генерирует ожидаемый результат, но теперь я хотел бы создать новый список фреймов данных, используя DF прогнозирования и данные пользователя DF.

Пример DataFrame

Новый список DF, состоящий из значения Predicted из "Predictions DF" и "Listened", которое будет равно 0, если пользователь не прослушивал исполнителя, или 1, если пользователь слушал, что-то вроде этого:

Ожидаемый DF

Я попробовал следующее решение:

val recommendationsSeq = someUsers.map { userID =>
     //Gets the artists from user in testData
   val artistsOfUser = testData.where($"user".===(userID)).select("artist").rdd.map(r => r(0)).collect.toList
     // Recommendations for each user
   val recoms        = makeRecommendations(model, userID, numRecom)
     //Insert a column listened with 1 if the artist in the test set for the user and 0 otherwise
   val recomOutput   = recoms.withColumn("listened", when($"artist".isin(artistsOfUser: _*), 1.0).otherwise(0.0)).drop("artist")
     (recomOutput)
}.toSeq

Но оно занимает очень много времени, когда рекомендация имеет более 30 пользователей. Я считаю, что есть лучший способ сделать это,

Может кто-нибудь дать какую-нибудь идею?

Спасибо,

1 Ответ

1 голос
/ 13 апреля 2020

Вы можете попробовать объединить данные, затем goupby и считать:

scala> val df1 = Seq((1205,0.9873411,1000019)).toDF("artist","prediction","user")
scala> df1.show()
+------+----------+-------+
|artist|prediction|   user|
+------+----------+-------+
|  1205| 0.9873411|1000019|
+------+----------+-------+

scala> val df2 = Seq((1000019,1205,40)).toDF("user","artist","playcount")
scala> df2.show()
+-------+------+---------+
|   user|artist|playcount|
+-------+------+---------+
|1000019|  1205|       40|
+-------+------+---------+

scala> df1.join(df2,Seq("artist","user")).groupBy('prediction).count().show()
+----------+-----+
|prediction|count|
+----------+-----+
| 0.9873411|    1|
+----------+-----+
...