如果用户id是字符串而不是连续的整数,如何使用mllib.recommendation?

shi*_*eng 11 recommendation-engine apache-spark apache-spark-mllib

我想使用Spark的mllib.recommendation库来构建原型推荐系统.但是,我所拥有的用户数据的格式是以下格式:

AB123XY45678
CD234WZ12345
EF345OOO1234
GH456XY98765
....
Run Code Online (Sandbox Code Playgroud)

如果我想使用该mllib.recommendation库,根据Rating类的API ,用户ID必须是整数(也必须是连续的?)

看起来真实用户ID和Spark使用的数字之间必须进行某种转换.但是我该怎么做呢?

Eug*_*nev 11

Spark并不真正需要数字ID,它只需要一些独特的值,但为了实现它们选择了Int.

您可以为userId进行简单的来回转换:

  case class MyRating(userId: String, product: Int, rating: Double)

  val data: RDD[MyRating] = ???

  // Assign unique Long id for each userId
  val userIdToInt: RDD[(String, Long)] = 
    data.map(_.userId).distinct().zipWithUniqueId()

  // Reverse mapping from generated id to original
  val reverseMapping: RDD[(Long, String)]
    userIdToInt map { case (l, r) => (r, l) }

  // Depends on data size, maybe too big to keep
  // on single machine
  val map: Map[String, Int] = 
    userIdToInt.collect().toMap.mapValues(_.toInt)

  // Transform to MLLib rating
  val rating: RDD[Rating] = data.map { r =>
    Rating(userIdToInt.lookup(r.userId).head.toInt, r.product, r.rating)
    // -- or
    Rating(map(r.userId), r.product, r.rating)
  }

  // ... train model

  // ... get back to MyRating userId from Int

  val someUserId: String = reverseMapping.lookup(123).head
Run Code Online (Sandbox Code Playgroud)

您也可以尝试'data.zipWithUniqueId()',但我不确定在这种情况下.即使数据集大小很小,.toInt也将是安全转换.

  • `lookup`方法不是有效的Spark代码.它会编译,但会打击运行时.你可以修复(删除)吗? (2认同)

Gan*_*nan 5

您需要在所有用户ID上运行StringIndexer,以将字符串转换为唯一的整数索引。它们不必是连续的。

我们将此用于https://www.aihello.com中的商品推荐引擎

df是(用户:字符串,产品,等级)

  val stringindexer = new StringIndexer()
      .setInputCol("user")
      .setOutputCol("userNumber")
  val modelc = stringindexer.fit(df)
  val  df = modelc.transform(df)
Run Code Online (Sandbox Code Playgroud)