【问题标题】:Apache Spark - NoSuchMethodException: <Class>.<init>(java.lang.String) when copying custom TransformerApache Spark - NoSuchMethodException: <Class>.<init>(java.lang.String) 复制自定义 Transformer 时
【发布时间】:2018-09-08 03:16:59
【问题描述】:

我按照 Holden Karau 在https://www.oreilly.com/learning/extend-spark-ml-for-your-own-modeltransformer-types 的教程定制了一个玩具估算器“SimpleIndexer”。问题是在“CrossValidator”中使用它时出错。

错误是

Exception in thread "main" java.lang.NoSuchMethodException: ....SimpleIndexerModel.<init>(java.lang.String)
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at org.apache.spark.ml.param.Params$class.defaultCopy(params.scala:846)
    at org.apache.spark.ml.PipelineStage.defaultCopy(Pipeline.scala:42)
    at com.nextperf.feature.SimpleIndexerModel.copy(SimpleIndexer.scala:63)

之前有人问过类似的问题 - java.lang.NoSuchMethodException: <Class>.<init>(java.lang.String) when copying custom Transformer。显然问题来自“复制”方法。但是我尝试了帖子中提到的解决方案,但它不起作用。

  • “SimpleIndexerModel”扩展了 DefaultParamsWritable 特征
  • 添加扩展 DefaultParamsReadable 接口的 Companion 对象

class SimpleIndexerModel(override val uid: String, words: Array[String]) extends Model[SimpleIndexerModel] with SimpleIndexerParams with DefaultParamsWritable{ ... ... } object SimpleIndexerModel extends DefaultParamsReadable[SimpleIndexerModel]

这个玩具示例的 spark 官方实现是“StringIndexer”。我找不到线索。有谁知道它为什么会发生,以及如何解决这个问题?

//"StringIndexerModel" works fine
val indexer1 = new StringIndexerModel("abc",Array("a"))
val m1 = indexer1.copy(new ParamMap())
//
//"SimpleIndexerModel" fails
val indexer2 = new SimpleIndexerModel("abc",Array("a"))
// This call throws the exception. 
val m2 = indexer2.copy(new ParamMap())

【问题讨论】:

    标签: scala apache-spark apache-spark-mllib


    【解决方案1】:

    查看Params.defaultCopy的实现:https://github.com/apache/spark/blob/master/mllib/src/main/scala/org/apache/spark/ml/param/params.scala#L845

    此方法需要一个只有一个字符串参数(uid)的构造函数。因此,您可以通过向 SimpleIndexerModel 类添加构造函数来解决您的问题。

    def this(uid: String) = {...}
    

    【讨论】:

    • 感谢您指出问题!但是我发现 Spark 的“StringIndexerModel”模型没有def this(uid: String) = {...},但是它有def this(labels: Array[String]) = this(Identifiable.randomUID("strIdx"), labels)
    • @user1269298 是的,但是StringIndexerModel 覆盖copy 方法并且根本不调用defaultCopy。你也可以重写copy 方法来避免这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    相关资源
    最近更新 更多