我想用 Java 创建一个自定义的 Spark Transformer。
Transformer 是文本预处理器,其作用类似于 Tokenizer。它以一个输入列和一个输出列作为参数。
我环顾四周,发现了 2 个 Scala Traits HasInputCol 和 HasOutputCol。
如何创建一个扩展 Transformer 并实现 HasInputCol 和 OutputCol 的类?
我的目标是拥有这样的东西。
// Dataset that have a String column named "text"
DataSet<Row> dataset;
CustomTransformer customTransformer = new CustomTransformer();
customTransformer.setInputCol("text");
customTransformer.setOutputCol("result");
// result that have 2 String columns named "text" and "result"
DataSet<Row> result = customTransformer.transform(dataset);
最佳答案
作为SergGr建议,您可以扩展 UnaryTransformer
。然而这是相当棘手的。
注意:以下所有评论均适用于 Spark 2.2.0 版。
解决 SPARK-12606 中描述的问题,他们得到 "...Param null__inputCol does not belong to..."
,你应该像这样实现 String uid()
:
@Override
public String uid() {
return getUid();
}
private String getUid() {
if (uid == null) {
uid = Identifiable$.MODULE$.randomUID("mycustom");
}
return uid;
}
显然他们正在构造函数中初始化 uid。但问题是 UnaryTransformer 的 inputCol
(和 outputCol
)在继承类中初始化 uid
之前被初始化。请参阅 HasInputCol
:
final val inputCol: Param[String] = new Param[String](this, "inputCol", "input column name")
Param
是这样构造的:
def this(parent: Identifiable, name: String, doc: String) = this(parent.uid, name, doc)
因此,当 parent.uid
被评估时,自定义的 uid()
实现被调用,此时 uid
仍然是 null。通过使用延迟评估实现 uid()
,您可以确保 uid()
永远不会返回 null。
但是在你的情况下:
Param d7ac3108-799c-4aed-a093-c85d12833a4e__inputCol does not belong to fe3d99ba-e4eb-4e95-9412-f84188d936e3
好像有点不一样。因为 "d7ac3108-799c-4aed-a093-c85d12833a4e"!= "fe3d99ba-e4eb-4e95-9412-f84188d936e3"
,它看起来像您对 uid()
的实现方法在每次调用时返回一个新值。也许在您的情况下它是这样实现的:
@Override
public String uid() {
return Identifiable$.MODULE$.randomUID("mycustom");
}
顺便说一下,在扩展 UnaryTransformer
时,请确保转换函数是 Serializable
。
关于java - 在 Java spark ml 中创建自定义转换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44431563/