了解 UID 在 Spark MLLib 转换器中的作用
Understanding the role of UID in a Spark MLLib Transformer
我正在使用 Apache Spark 和 Scala 来创建机器学习管道。我管道中的一个 Transformer 在此过程的早期进行了一项代价高昂的 join
操作。由于我的 ParamGrid
中有很多功能,这意味着程序必须在优化网格中的每个功能的同时在内存中保存这个巨大的连接 DataFrame
。
为了尝试解决这个问题,我创建了一个自定义 Transformer
,通过将它写入 S3 中的镶木地板并返回从镶木地板读取的 DataFrame 来缓存这个大的中间 DataFrame
。这运作良好并提高了模型的速度 直到 我向 ParamGrid
添加了在缓存阶段之前上演的功能。当我将 parquet 写入 S3 时,我使用由以下因素确定的路径:
class Cacher(override val uid: String) extends Transformer {
// the cachePath variable determines the path within the S3 bucket
lazy val cachePath = Identifiable.randomUID(uid + "transformer-cache")
// ...
我想我误解了 uid
是如何工作的...我相信每当 Spark 在 ParamGrid
上进行优化时,它都会在 类 上演管道,创建它们的新实例,并给它们新的、唯一的 uid
s 来跟踪它们。我怀疑缓存出错了,因为 Spark 没有为它创建的新 Transformer
实例提供唯一的 uid
,这意味着每当缓存的新实例 Transformer
被创建。任何人都可以就如何为管道创建的阶段的每个实例生成唯一的随机 uid
提供任何指示吗?
干杯!
一步一步:
uid
是 Identifiable
特性所必需的(Transformer
扩展了 PipelineStage
,扩展了 Params
,扩展了 Identifiable
)。
根据 Identifiable
文档 uid
is:
An immutable unique ID for the object and its derivatives.
总的来说:
Params
是可变的。设置参数 returns this
不影响 uid
.
import org.apache.spark.ml.feature.OneHotEncoder
val enc = new OneHotEncoder()
val enc_ = enc.setInputCol("foo")
enc == enc_
Boolean = true
enc.uid == enc_.uid
Boolean = true
copying
Params
创建一个新实例但保持不变 uid
(请参阅前一点引述中强调的部分)。
val encCopy = enc.copy(new org.apache.spark.ml.param.ParamMap())
encCopy == enc
Boolean = false
encCopy.uid == enc.uid
Boolean = true
您可以尝试覆盖 copy
method to avoid copying parent uid
但它似乎与制作 Params
Identifiable
.
[ 背后的整个想法相冲突=66=]
可能的解决方案:
- 根本不要使用转换器
uid
或使路径依赖于当前的参数集。
- 不要手动写入缓存文件,使用内置缓存机制(
Dataset.persist
)。它不仅解决了手头的问题,还解决了一个隐藏的问题,即在退出时释放资源。
我正在使用 Apache Spark 和 Scala 来创建机器学习管道。我管道中的一个 Transformer 在此过程的早期进行了一项代价高昂的 join
操作。由于我的 ParamGrid
中有很多功能,这意味着程序必须在优化网格中的每个功能的同时在内存中保存这个巨大的连接 DataFrame
。
为了尝试解决这个问题,我创建了一个自定义 Transformer
,通过将它写入 S3 中的镶木地板并返回从镶木地板读取的 DataFrame 来缓存这个大的中间 DataFrame
。这运作良好并提高了模型的速度 直到 我向 ParamGrid
添加了在缓存阶段之前上演的功能。当我将 parquet 写入 S3 时,我使用由以下因素确定的路径:
class Cacher(override val uid: String) extends Transformer {
// the cachePath variable determines the path within the S3 bucket
lazy val cachePath = Identifiable.randomUID(uid + "transformer-cache")
// ...
我想我误解了 uid
是如何工作的...我相信每当 Spark 在 ParamGrid
上进行优化时,它都会在 类 上演管道,创建它们的新实例,并给它们新的、唯一的 uid
s 来跟踪它们。我怀疑缓存出错了,因为 Spark 没有为它创建的新 Transformer
实例提供唯一的 uid
,这意味着每当缓存的新实例 Transformer
被创建。任何人都可以就如何为管道创建的阶段的每个实例生成唯一的随机 uid
提供任何指示吗?
干杯!
一步一步:
uid
是Identifiable
特性所必需的(Transformer
扩展了PipelineStage
,扩展了Params
,扩展了Identifiable
)。根据
Identifiable
文档uid
is:An immutable unique ID for the object and its derivatives.
总的来说:
Params
是可变的。设置参数 returnsthis
不影响uid
.import org.apache.spark.ml.feature.OneHotEncoder val enc = new OneHotEncoder() val enc_ = enc.setInputCol("foo") enc == enc_
Boolean = true
enc.uid == enc_.uid
Boolean = true
copying
Params
创建一个新实例但保持不变uid
(请参阅前一点引述中强调的部分)。val encCopy = enc.copy(new org.apache.spark.ml.param.ParamMap()) encCopy == enc
Boolean = false
encCopy.uid == enc.uid
Boolean = true
您可以尝试覆盖
[ 背后的整个想法相冲突=66=]copy
method to avoid copying parentuid
但它似乎与制作Params
Identifiable
.
可能的解决方案:
- 根本不要使用转换器
uid
或使路径依赖于当前的参数集。 - 不要手动写入缓存文件,使用内置缓存机制(
Dataset.persist
)。它不仅解决了手头的问题,还解决了一个隐藏的问题,即在退出时释放资源。