Элемент поля не существует при использовании конвейера Spark MLlib для ALS

Я тренирую рекомендательную систему с ALS (версия Spark: 1.3.1). Теперь я хочу использовать Pipeline для выбора модели с помощью перекрестной проверки. В качестве первого шага я попытался адаптировать пример кода и придумал это:

val conf = new SparkConf().setAppName("ALS").setMaster("local")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
import sqlContext.implicits._

val ratings: RDD[org.apache.spark.mllib.recommendation.Rating] = // ...
val als = new ALS().setMaxIter(10).setRank(10).setRegParam(0.01)
val pipeline = new Pipeline().setStages(Array(als))
val model = pipeline.fit(ratings.toDF)

Когда я запускаю его, последняя строка завершается с ошибкой:

Exception in thread "main" java.lang.IllegalArgumentException: Field "item" does not exist.
at org.apache.spark.sql.types.StructType$$anonfun$apply$25.apply(dataTypes.scala:1032)
at org.apache.spark.sql.types.StructType$$anonfun$apply$25.apply(dataTypes.scala:1032)
at scala.collection.MapLike$class.getOrElse(MapLike.scala:128)
at scala.collection.AbstractMap.getOrElse(Map.scala:58)
at org.apache.spark.sql.types.StructType.apply(dataTypes.scala:1031)
at org.apache.spark.ml.recommendation.ALSParams$class.validateAndTransformSchema(ALS.scala:148)
at org.apache.spark.ml.recommendation.ALS.validateAndTransformSchema(ALS.scala:229)
at org.apache.spark.ml.recommendation.ALS.transformSchema(ALS.scala:304)
at org.apache.spark.ml.Pipeline$$anonfun$transformSchema$4.apply(Pipeline.scala:142)
at org.apache.spark.ml.Pipeline$$anonfun$transformSchema$4.apply(Pipeline.scala:142)
at scala.collection.IndexedSeqOptimized$class.foldl(IndexedSeqOptimized.scala:51)
at scala.collection.IndexedSeqOptimized$class.foldLeft(IndexedSeqOptimized.scala:60)
at scala.collection.mutable.ArrayOps$ofRef.foldLeft(ArrayOps.scala:108)
at org.apache.spark.ml.Pipeline.transformSchema(Pipeline.scala:142)
at org.apache.spark.ml.PipelineStage.transformSchema(Pipeline.scala:58)
at org.apache.spark.ml.Pipeline.fit(Pipeline.scala:100)
at org.apache.spark.ml.Pipeline.fit(Pipeline.scala:79)
at org.apache.spark.ml.Estimator.fit(Estimator.scala:44)
...

Я нигде в своем коде не использую строку "item", поэтому я предполагаю, что это какое-то значение по умолчанию. Когда я добавляю .setItemCol("itemId") к als, сообщение об исключении изменяется соответственно.

Что означает "item"? Как заставить конвейер работать?


person stholzm    schedule 09.05.2015    source источник


Ответы (1)


Хорошо, решение было на самом деле очень простым: используйте org.apache.spark.ml.recommendation.ALS.Rating вместо org.apache.spark.mllib.recommendation.Rating, и оно просто сработает.

В противном случае .setItemCol("product") делает свое дело, потому что org.apache.spark.mllib.recommendation.Rating имеет поле под названием «продукт», тогда как org.apache.spark.ml.recommendation.ALS.Rating называет соответствующее поле «товар». Должно быть какое-то волшебство, которое, учитывая строку, обращается к некоторому полю класса case (отражение?).

person stholzm    schedule 09.05.2015
comment
ИМХО, не следует сопоставлять класс org.apache.spark.ml.recommendation.ALS.Rating, поскольку вы выполняете двойную работу. code внутренне сопоставляет DataFrame с RDD Rating для вас :). Итак, вы переходите от Rating к Dataframe обратно к Rating. Как вы узнали, кажется, что использование setUserCol и setItemCol — это способ использования нового Spark ML API. - person RAbraham; 10.12.2015