如何在spark中映射DataFrame以提取RowData并使用h2o mojo模型进行预测

时间:2017-12-15 08:34:05

标签: scala apache-spark h2o sparkling-water

我有一个以mojo格式保存的h2o模型,现在我正在尝试加载它并使用它来对新数据集(df)进行预测,作为用scala编写的spark应用程序的一部分。理想情况下,我希望在包含基于此模型的类概率的现有DataFrame中添加一个新行。

我可以看到如何将mojo应用于已经采用RowData格式的单个行(根据答案here),但我不确定如何映射现有的DataFrame以使其位于右侧使用mojo模型进行预测的格式。我曾经使用过DataFrames,但从未使用过底层的RDD。

此外,该模型是否应该序列化/广播,以便预测可以在群集上并行完成,还是作为地图的一部分可供所有执行者使用?

我已经走到了这一步:

# load mojo model and create easy predict model wrapper
val mojo = MojoModel.load("loca/path/to/mojo/mojo.zip")
val easyModel = new EasyPredictModelWrapper(mojo)

# map over spark DataFrame, converty to rdd, and make predictions on each row:
df.rdd.map { row =>
   val prediction = easyModel.predictBinomial(row).classProbabilities
   println(prediction)
   }

但我的row变量的格式不正确。有关下一步尝试的建议吗?

编辑:我的DataFrame由70个预测特征列组成,它们是整数和类别/因子列的混合。一个非常简单的示例DataFrame:

val df = Seq(
  (0, 3, "cat1"),
  (1, 2, "cat2"),
  (2, 6, "cat1")
).toDF("id", "age", "category")

2 个答案:

答案 0 :(得分:1)

使用此函数准备H2O所需的RowData对象:

def rowToRowData(df: DataFrame, row: Row): RowData = {
  val rowAsMap = row.getValuesMap[Any](df.schema.fieldNames)
  val rowData = rowAsMap.foldLeft(new RowData()) { case (rd, (k,v)) => 
    if (v != null) { rd.put(k, v.toString) }
    rd
  }
  rowData
}

答案 1 :(得分:0)

我在这里有一个完整的答案:https://stackoverflow.com/a/47898040/9120484 您可以直接在df上调用map而不是在rdd上调用。