【问题标题】:java.lang.NoSuchMethodException: <Class>.<init>(java.lang.String) when copying custom Transformerjava.lang.NoSuchMethodException: <Class>.<init>(java.lang.String) 复制自定义 Transformer 时
【发布时间】:2018-03-19 05:45:45
【问题描述】:

目前正在使用 spark 2.0.1 和 2.2.1 在我的 spark-shell 中使用自定义转换器。

在编写自定义 ml 转换器时,为了将其添加到管道中,我注意到复制方法的覆盖存在问题。

在我的例子中,复制方法是由 TrainValidationSplit 的 fit 方法调用的。

我得到的错误:

java.lang.NoSuchMethodException: Custom.<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:718)
  at org.apache.spark.ml.PipelineStage.defaultCopy(Pipeline.scala:42)
  at Custom.copy(<console>:16)
  ... 48 elided

然后我尝试直接调用复制方法,但我仍然得到同样的错误。

这是我的班级和我执行的电话:

import org.apache.spark.ml.Transformer
import org.apache.spark.sql.{Dataset, DataFrame}
import org.apache.spark.sql.types.{StructField, StructType, DataTypes}
import org.apache.spark.ml.param.{Param, ParamMap}

// Simple DF
val doubles = Seq((0, 5d, 100d), (1, 4d,500d), (2, 9d,700d)).toDF("id", "rating","views")


class Custom(override val uid: String) extends org.apache.spark.ml.Transformer {
  def this() = this(org.apache.spark.ml.util.Identifiable.randomUID("custom"))

  def copy(extra: org.apache.spark.ml.param.ParamMap): Custom = {
    defaultCopy(extra)
  }

  override def transformSchema(schema: org.apache.spark.sql.types.StructType): org.apache.spark.sql.types.StructType = {
    schema.add(org.apache.spark.sql.types.StructField("trending", org.apache.spark.sql.types.IntegerType, false))
  }

   def transform(df: org.apache.spark.sql.Dataset[_]): org.apache.spark.sql.DataFrame = {

    df.withColumn("trending", (df.col("rating") > 4 && df.col("views") > 40))
  }
}


val mycustom = new Custom("Custom")
// This call throws the exception. 
mycustom.copy(new org.apache.spark.ml.param.ParamMap())

有谁知道这是否是一个已知问题?我似乎在任何地方都找不到它。

还有其他方法可以在自定义转换器中实现复制方法吗?

谢谢

【问题讨论】:

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


    【解决方案1】:

    以下是我要对您的自定义 Transformer 进行更改的几件事(也用于启用 PipelineModel 的 SerDe 操作):

    例如

    class Custom(override val uid: String) extends Transformer
        with DefaultParamsWritable {
          ...
          ...
    
    }
    object Custom extends DefaultParamsReadable[Custom]
    

    如果您只有 1 个输入/输出列,请查看 UnaryTransformer

    最后,到底需要什么mycustom.copy(new ParamMap())??

    【讨论】:

    • 你好@Gevorg,谢谢你的回复我尝试了companionobject并且它出错了。回答您关于使用副本的问题。我不直接需要它,我只把它放在这里,因为当我尝试创建管道并调用 fit 时会调用复制方法。
    猜你喜欢
    • 2018-09-08
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 2013-08-04
    相关资源
    最近更新 更多