scala.MatchError:在spark RDD上为null

时间:2014-07-09 11:30:00

标签: scala apache-spark rdd apache-spark-mllib collaborative-filtering

我对spark和scala都比较新。 我试图在spark上使用scala实现协同过滤。 以下是代码

import org.apache.spark.mllib.recommendation.ALS
import org.apache.spark.mllib.recommendation.Rating

val data = sc.textFile("/user/amohammed/CB/input-cb.txt")

val distinctUsers = data.map(x => x.split(",")(0)).distinct().map(x => x.toInt)

val distinctKeywords = data.map(x => x.split(",")(1)).distinct().map(x => x.toInt)

val ratings = data.map(_.split(',') match {
  case Array(user, item, rate) => Rating(user.toInt,item.toInt, rate.toDouble)
})

val model = ALS.train(ratings, 1, 20, 0.01)

val keywords = distinctKeywords collect
  distinctUsers.map(x => {(x, keywords.map(y => model.predict(x,y)))}).collect()

抛出 scala.MatchError:null         org.apache.spark.rdd.PairRDDFunctions.lookup(PairRDDFunctions.scala:571)在最后一行 如果我将distinctUsers rdd收集到一个数组中并执行相同的代码,那么Thw代码工作正常:

val users = distinctUsers collect
  users.map(x => {(x, keywords.map(y => model.predict(x, y)))})

在处理RDD时,我在哪里弄错了?

Spark版本:1.0.0 Scala版本:2.10.4

1 个答案:

答案 0 :(得分:1)

在堆栈跟踪中进一步回调,MatrixFactorizationModel来源的第43行说:

val userVector = new DoubleMatrix(userFeatures.lookup(user).head)

请注意userFeatures的{​​{1}}字段本身就是另一个RDD;我相信当匿名功能块关闭model时,它没有正确序列化,因此它上面的model方法失败了。我也尝试将lookupmodel放入广播变量中,但这也不起作用。

不要回到Scala集合并失去Spark的好处,最好坚持使用RDD并利用其他方法来转换它们。

我从这开始:

keywords

然后,我们不是逐个计算每个预测,而是可以获得所有可能的用户 - 关键字对的笛卡尔乘积作为RDD,并使用MatrixFactorizationModel中的另一个val ratings = data.map(_.split(',') match { case Array(user, keyword, rate) => Rating(user.toInt, keyword.toInt, rate.toDouble) }) // instead of parsing the original RDD's strings three separate times, // you can map the "user" and "product" fields of the Rating case class val distinctUsers = ratings.map(_.user).distinct() val distinctKeywords = ratings.map(_.product).distinct() val model = ALS.train(ratings, 1, 20, 0.01) 方法,该方法采用这样的对的RDD作为其论点。

predict

现在val userKeywords = distinctUsers.cartesian(distinctKeywords) val predictions = model.predict(userKeywords).map { case Rating(user, keyword, rate) => (user, Map(keyword -> rate)) }.reduceByKey { _ ++ _ } 为每个用户提供了一个不可变的映射,可以查询特定关键字的预测评级。如果您在原始示例中特别需要数组,则可以执行以下操作:

predictions

警告:我使用Spark 1.0.1测试了这个,因为它是我安装的,但它也应该与1.0.0一起使用。