0

我已经成功训练了一个 XGBoost 模型,其中trainDF一个数据框包含两列:features并且label我们有 11k 1 和 57M 0(不平衡数据集)。一切正常。

val udnersample = 0.1
// Undersampling of 0's -- choosing 10%
val training1 = output1.filter($"datestr" < end_period1 && 
    $"label" === 1)
val training0 = output1.filter($"datestr" < end_period1 && 
    $"label" === 0).sample(
    false, undersample)
val training = training0.unionAll(training1)
val traindDF = training.select("label", 
    "features").toDF("label", "features")}
val paramMap = List("eta" -> 0.05,
                    "max_depth" -> 6,
                    "objective" -> "binary:logistic").toMap
val num_trees = 400
val num_cores = 200
val XGBModel = XGBoost.trainWithDataFrame(trainDF, 
                                          paramMap, 
                                          num_trees, 
                                          num_cores, 
                                          useExternalMemory = true)

然后,我想通过一些窗口来更改 y 标签,以便在每个组中,我可以更早地预测 y 标签。

val sum_label = "sum_label"
val label_window_length = 19
val sliding_window_label =  Window.partitionBy("id").orderBy(
    asc("timestamp")).rowsBetween(0, label_window_length)

val training_source = output1.filter($"datestr" < 
    end_period1).withColumn(
    sum_label, sum($"label").over(sliding_window_label)).drop(
    "label").withColumnRenamed(sum_label, "label")
val training1 = training_source.filter(col("label") === 1)
val training0 = training_source.filter(col("label") === 0).sample(false, 0.099685)
val training = training0.unionAll(training1)
val traindDF = training.select("label", 
    "features").toDF("label", "features")}

结果有 57M 的 0 和 214k 的 1(尽管行数大致相同)。的列中没有NAs并且类型仍然是。然后 xgboost 失败:"label"trainDFdouble (nullable=true)

Name: ml.dmlc.xgboost4j.java.XGBoostError
Message: XGBoostModel training failed
StackTrace:   at ml.dmlc.xgboost4j.scala.spark.XGBoost$.postTrackerReturnProcessing(XGBoost.scala:316)
at ml.dmlc.xgboost4j.scala.spark.XGBoost$.trainWithRDD(XGBoost.scala:293)
at ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator.train(XGBoostEstimator.scala:138)
at ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator.train(XGBoostEstimator.scala:35)
at org.apache.spark.ml.Predictor.fit(Predictor.scala:118)
at ml.dmlc.xgboost4j.scala.spark.XGBoost$.trainWithDataFrame(XGBoost.scala:169)

我可以根据需要包含日志。我的困惑是使用窗口功能并且实际上不更改任何其他设置会导致 XGB 失败。我将不胜感激对此的任何想法。

4

1 回答 1

0

事实证明,将表保存traindDF在 hive 中并将其重新加载到 Spark 中可以解决问题:

traindDF.write.mode("overwrite").saveAsTable("database.tablename")

然后,您可以轻松加载表格:

val traindDF = spark.sql("""select * from database.tablename""")

这个技巧解决了这个问题。似乎火花窗口功能有点不稳定,将结果保存到配置单元表中使其工作。

更好的方法是在 hive 中使用窗口函数而不是 Spark。

于 2018-07-17T17:36:29.127 回答