了解 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 上进行优化时,它都会在 类 上演管道,创建它们的新实例,并给它们新的、唯一的 uids 来跟踪它们。我怀疑缓存出错了,因为 Spark 没有为它创建的新 Transformer 实例提供唯一的 uid,这意味着每当缓存的新实例 Transformer 被创建。任何人都可以就如何为管道创建的阶段的每个实例生成唯一的随机 uid 提供任何指示吗?

干杯!

一步一步:

  • uidIdentifiable 特性所必需的(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)。它不仅解决了手头的问题,还解决了一个隐藏的问题,即在退出时释放资源。