Spark 自定义估算器访问 Param[T]
Spark custom estimator access to Param[T]
我正在为 spark 构建自定义估算器。不幸的是,我访问估算器的 Param[T]
默认参数的方式似乎有问题。这是一个比较 Transformer
和 Estimator
的最小示例。可以访问相同参数的 Estimator
trait PreprocessingParam2s extends Params {
final val isInList = new Param[Array[String]](this, "isInList", "list of isInList items")
}
被称为
new ExampleEstimator().setIsInList(Array("def", "ABC")).fit(dates).transform(dates).show
为了执行
dataset
.withColumn("isInList", when('ISO isin ($(isInList): _*), 1).otherwise(0))
但与工作正常的 Transformer
不同,Estimator
失败并显示 java.util.NoSuchElementException: Failed to find a default value for isInList
https://gist.github.com/geoHeil/218683c6b0f91bc76f71cb652cd746b8 or https://github.com/geoHeil/sparkEstimatorProblem(包括 build.sbt 文件以便更容易重现问题)
这里有什么问题?
编辑
我正在使用 spark 2.0.2.
正如@t-gawęda 指出的,错误可以在设置默认参数时修复。但这不是必需的,因为我称之为 new ExampleEstimator().setIsInList(Array("def", "ABC"))
。那么为什么没有设置参数呢?
如果我设置默认参数,它们将用作后备。但这不是我想要实现的语义。而不是正确的输出(Transformer
)
+----------+---+--------+
| dates|ISO|isInList|
+----------+---+--------+
|2016-01-01|ABC| 1|
|2016-01-02|ABC| 1|
|2016-01-03|POL| 0|
|2016-01-04|ABC| 1|
|2016-01-05|POL| 0|
|2016-01-06|ABC| 1|
|2016-01-07|POL| 0|
|2016-01-08|ABC| 1|
|2016-01-09|def| 1|
|2016-01-10|ABC| 1|
+----------+---+--------+
+--------+
|isInList|
+--------+
| 1|
| 0|
+--------+
我明白了
+----------+---+--------+
| dates|ISO|isInList|
+----------+---+--------+
|2016-01-01|ABC| 0|
|2016-01-02|ABC| 0|
|2016-01-03|POL| 0|
|2016-01-04|ABC| 0|
|2016-01-05|POL| 0|
|2016-01-06|ABC| 0|
|2016-01-07|POL| 0|
|2016-01-08|ABC| 0|
|2016-01-09|def| 0|
|2016-01-10|ABC| 0|
+----------+---+--------+
+--------+
|isInList|
+--------+
| 0|
+--------+
明显错误的地方,例如仅使用默认参数。我存储参数的方法有什么问题?
请参阅设置默认参数的工作示例 https://github.com/geoHeil/sparkEstimatorProblem。
尝试在您的参数中添加 getter 和 setDefault:
trait PreprocessingParam2s extends Params {
final val isInList = new Param[Array[String]](this, "isInList", "list of isInList items")
setDefault(isInList, /* here put default value */)
/** @group getParam */
final def getIsInList: Array[String] = $(isInList)
}
为什么?
看看参数映射是如何创建的:
lazy val params: Array[Param[_]] = {
val methods = this.getClass.getMethods
methods.filter { m =>
Modifier.isPublic(m.getModifiers) &&
classOf[Param[_]].isAssignableFrom(m.getReturnType) &&
m.getParameterTypes.isEmpty
}.sortBy(_.getName)
.map(m => m.invoke(this).asInstanceOf[Param[_]])
}
Spark 扫描 class 中的所有方法并搜索方法:
- public修饰符
- 无参数
- 那里return类型是Param
的子类型
Spark 启动这些方法并将值放入参数映射中。当您读取参数值时,Spark 会查看此映射,而不是执行 getters
完整代码是here
说明:在模型中你必须有:
def setIsInList(value : Array[String]): this.type = {
set(isInList, value)
this
}
以及估算器的拟合方法:
override def fit(dataset: Dataset[_]): ExampleTransModel = new ExampleTransModel(uid, 1.0).setIsInList($(this.isInList))
创建模型后,您没有将参数值复制到模型对象 - 这就是为什么在评估模型时它始终为空的原因
我正在为 spark 构建自定义估算器。不幸的是,我访问估算器的 Param[T]
默认参数的方式似乎有问题。这是一个比较 Transformer
和 Estimator
的最小示例。可以访问相同参数的 Estimator
trait PreprocessingParam2s extends Params {
final val isInList = new Param[Array[String]](this, "isInList", "list of isInList items")
}
被称为
new ExampleEstimator().setIsInList(Array("def", "ABC")).fit(dates).transform(dates).show
为了执行
dataset
.withColumn("isInList", when('ISO isin ($(isInList): _*), 1).otherwise(0))
但与工作正常的 Transformer
不同,Estimator
失败并显示 java.util.NoSuchElementException: Failed to find a default value for isInList
https://gist.github.com/geoHeil/218683c6b0f91bc76f71cb652cd746b8 or https://github.com/geoHeil/sparkEstimatorProblem(包括 build.sbt 文件以便更容易重现问题)
这里有什么问题?
编辑
我正在使用 spark 2.0.2.
正如@t-gawęda 指出的,错误可以在设置默认参数时修复。但这不是必需的,因为我称之为 new ExampleEstimator().setIsInList(Array("def", "ABC"))
。那么为什么没有设置参数呢?
如果我设置默认参数,它们将用作后备。但这不是我想要实现的语义。而不是正确的输出(Transformer
)
+----------+---+--------+
| dates|ISO|isInList|
+----------+---+--------+
|2016-01-01|ABC| 1|
|2016-01-02|ABC| 1|
|2016-01-03|POL| 0|
|2016-01-04|ABC| 1|
|2016-01-05|POL| 0|
|2016-01-06|ABC| 1|
|2016-01-07|POL| 0|
|2016-01-08|ABC| 1|
|2016-01-09|def| 1|
|2016-01-10|ABC| 1|
+----------+---+--------+
+--------+
|isInList|
+--------+
| 1|
| 0|
+--------+
我明白了
+----------+---+--------+
| dates|ISO|isInList|
+----------+---+--------+
|2016-01-01|ABC| 0|
|2016-01-02|ABC| 0|
|2016-01-03|POL| 0|
|2016-01-04|ABC| 0|
|2016-01-05|POL| 0|
|2016-01-06|ABC| 0|
|2016-01-07|POL| 0|
|2016-01-08|ABC| 0|
|2016-01-09|def| 0|
|2016-01-10|ABC| 0|
+----------+---+--------+
+--------+
|isInList|
+--------+
| 0|
+--------+
明显错误的地方,例如仅使用默认参数。我存储参数的方法有什么问题? 请参阅设置默认参数的工作示例 https://github.com/geoHeil/sparkEstimatorProblem。
尝试在您的参数中添加 getter 和 setDefault:
trait PreprocessingParam2s extends Params {
final val isInList = new Param[Array[String]](this, "isInList", "list of isInList items")
setDefault(isInList, /* here put default value */)
/** @group getParam */
final def getIsInList: Array[String] = $(isInList)
}
为什么?
看看参数映射是如何创建的:
lazy val params: Array[Param[_]] = {
val methods = this.getClass.getMethods
methods.filter { m =>
Modifier.isPublic(m.getModifiers) &&
classOf[Param[_]].isAssignableFrom(m.getReturnType) &&
m.getParameterTypes.isEmpty
}.sortBy(_.getName)
.map(m => m.invoke(this).asInstanceOf[Param[_]])
}
Spark 扫描 class 中的所有方法并搜索方法:
- public修饰符
- 无参数
- 那里return类型是Param 的子类型
Spark 启动这些方法并将值放入参数映射中。当您读取参数值时,Spark 会查看此映射,而不是执行 getters
完整代码是here 说明:在模型中你必须有:
def setIsInList(value : Array[String]): this.type = {
set(isInList, value)
this
}
以及估算器的拟合方法:
override def fit(dataset: Dataset[_]): ExampleTransModel = new ExampleTransModel(uid, 1.0).setIsInList($(this.isInList))
创建模型后,您没有将参数值复制到模型对象 - 这就是为什么在评估模型时它始终为空的原因