2016-11-29 5 views
3

Я использую Apache Spark с Scala для создания ML-конвейера. Один из трансформаторов, которые у меня есть в моем конвейере, на самом деле стоит дорогостоящей операцией join. Поскольку у меня есть много функций в моем ParamGrid, это означает, что программа должна удерживать этот огромный, объединенный DataFrame в памяти, в то время как он оптимизирует каждую функцию в сетке.Понимать роль UID в Spark MLLib Transformer

Чтобы решить эту проблему, я создал обычай Transformer, который кэширует этот большой промежуточный DataFrame, написав его на паркет в S3 и вернув DataFrame, который читается с паркета. Это хорошо работало и увеличивало скорость модели до Я добавил функции к ParamGrid, которые были поставлены перед стадией кеширования. Когда я пишу паркет 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 работаю ... моя вера была, что всякий раз, когда искра оптимизирована над ParamGrid, потребовалось бы то ни было классами были поставлены в этот момент в конвейере, создали новые экземпляры их и дали им новые уникальные uid s, чтобы отслеживать их. Я подозреваю, что кэширование идет наперекосяк, потому что Spark не дает уникального uid новым экземплярам Transformer, которые он создает, что означает, что кешированный паркет постоянно перезаписывается всякий раз, когда создается новый экземпляр кэша Transformer. Может ли кто-нибудь дать указатели на то, как создавать уникальные случайные uid s для каждого экземпляра этапа, который создает конвейер?

Cheers!

ответ

2

Шаг за шагом:

  • uid требуется по Identifiable признака (Transformer расширяет PipelineStage, который проходит Params, который проходит Identifiable).
  • Согласно Identifiable Документах uid is:

    Непреложным уникальный идентификатор для объекта и его производных .

  • В общем:

    • Params изменчивы. Параметры настройки возвращают 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 
      
    • copyingParams создает новый экземпляр, но сохраняет тот же uid (см подчеркивается часть цитаты из предыдущего пункта).

      val encCopy = enc.copy(new org.apache.spark.ml.param.ParamMap()) 
      
      encCopy == enc 
      
      Boolean = false 
      
      encCopy.uid == enc.uid 
      
      Boolean = true 
      
  • Вы могли бы попытаться переопределить copy method, чтобы избежать copying parent uid, но это, кажется, противоречит всей идее позади создания ParamsIdentifiable.

Возможные решения:

  • Не используйте трансформатор uid вообще или сделать путь в зависимости от текущего набора параметров.
  • Не записывайте файлы кеша вручную и используйте встроенный механизм кеширования (Dataset.persist). Он не только решает проблему, но и устраняет скрытую проблему, которая освобождает ресурсы при выходе.

 Смежные вопросы

  • Нет связанных вопросов^_^