2016-11-28 36 views
0

我正在構建一個spark的自定義估計器。不幸的是,在我如何訪問估計器的默認參數方面似乎有些不妥。以下是將TransformerEstimator進行比較的最小示例。它可以訪問相同的參數Spark自定義估計器訪問Param [T]

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/218683c6b0f91bc76f71cb652cd746b8https://github.com/geoHeil/sparkEstimatorProblem(包括build.sbt文件更容易重現該問題)

這裏有什麼問題?

編輯

我正在使用spark 2.0.2。

作爲@叔gawęda指出可以設定默認參數時被固定的誤差。但這不應該是必要的,因爲我稱之爲新的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

+0

時總是空這裏是帶有相同類型參數的代碼:https://github.com/apache/spark/blob/master/mllib/src/main/scala/org/apache/spark/ml/param/params.scala#L436 –

+0

@T.Gawęda聽起來不錯,但不幸的是我還不清楚。請,你能再解釋一下嗎?非常感謝。 –

回答

3

嘗試增加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) 
} 

爲什麼?

看看如何PARAMS地圖創建:

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[_]]) 
} 

星火掃描在類的所有方法和搜索方法有:

  • public修飾符
  • 沒有參數
  • 有返回類型爲亞型帕拉姆

Spark啓動這些方法並將值放入參數映射中。當你讀到參數值,然後星火看這個圖,而不是執行干將

的完整代碼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)) 

創建模型後,你沒有複製的參數值模型對象 - 這就是爲什麼它評估模型

+0

非常感謝。這裏是固定代碼https://gist.github.com/geoHeil/d4e123a6d8fea073591d666379075724請你能解釋爲什麼setDefault/getter是必需的嗎?對我來說,設置默認值就足以解決問題。 –

+0

@GeorgHeiler請參閱更新:) Spark緩存參數數據 –

+0

再次感謝。爲什麼設置默認是強制性的? –