【问题标题】:How to adjust Model for rare binary outcome with Tensorflow or GBM如何使用 Tensorflow 或 GBM 调整模型以获得罕见的二元结果
【发布时间】:2019-12-21 19:09:26
【问题描述】:

我目前正在处理具有罕见二元结果的数据,即响应向量大部分包含 0,只有少数 1(大约 1.5% 的)。我有大约 20 个连续的解释变量。我尝试使用 GBM、随机森林、TensorFlow 和 Keras 后端来训练模型。

无论我使用哪种方法,我都观察到模型的特殊行为:

准确度很高 (~98%),但模型预测所有结果的“0”类概率为 ~98.5%,“1”类的概率约为 1.5%。

如何防止这种行为?

我正在使用 RStudio。例如,带有 Keras 的 TF 模型将是:

model <- keras_model_sequential()

model %>%
  layer_dense(units = 256, activation = "relu", input_shape = c(20)) %>%
  layer_dense(units = 256, activation = "relu") %>%
  layer_dense(units = 2, activation = "sigmoid")

parallel_model <- multi_gpu_model(model, gpus=2)
parallel_model %>% compile(
  optimizer = "adam",             
  loss = "binary_crossentropy",
  metrics = "binary_accuracy")

histroy <- parallel_model %>% fit(
  x_train, y_train,
  batch_size = 64,
  epochs = 100,
  class_weight = list("0"=1,"1"=70),
  verbose = 1,
  validation_split = 0.2
)

但我的观察不仅限于 TF。这使我的问题更加笼统。我不是要求对上述模型进行具体调整,而是想讨论在什么时候所有结果都被赋予相同的概率。

我可以猜到,问题与损失函数有关。 我知道没有办法将 AUC 用作损失函数,因为它不可微。如果我用未知数据测试 AUC 模型,结果并不比随机猜测好。

我不介意用 Python 代码回答问题,因为这不是关于编码的问题,而是关于一般行为和算法的问题。

【问题讨论】:

  • 我看到你有两个班级,每个班级的值可以是 0 或 1。我不确定班级权重是否正确考虑了事情。问题:样本中的“两个类”是否都正确?或者它是一个严格的分类问题(只有一个类是正确的)。
  • @DanielMöller 结果是 0 或 1。永远不会发生 1,1 或 0,0。我从来没有想过这个。这将如何影响模型?
  • 所以,我的回答如下。最重要的是拥有大批量(我会说 >200)并使用适当的指标。

标签: tensorflow machine-learning keras xgboost gbm


【解决方案1】:

当你的问题有不平衡的类时,我建议在训练模型之前使用 SMOTE(仅在训练数据上!!!永远不要在测试数据上使用 smote!!!)。

例如:

from imblearn.over_sampling import SMOTE
X_trn_balanced, Y_trn_balanced = SMOTE(random_state=1, ratio=1).fit_sample(X_trn, Y_trn)
#next fit the model with the balanced data
model.fit(X_trn_balanced, Y_trn_balanced )

【讨论】:

    【解决方案2】:

    在我(不是那么大)在 AUC 问题和罕见阳性方面的经验中,我看到模型具有一类(而不是二类)。要么是“结果为正 (1)”,要么是“结果为负 (0)”。

    准确度等指标对这些问题毫无用处,您应该使用基于 AUC 的大批量指标。

    对于这些问题,结果概率是否太小并不重要,只要它们之间存在差异即可。 (Forests、GBM等确实会输出这些小值,但这不是问题)

    对于神经网络,您可以尝试使用类权重来增加输出概率。但是请注意,如果您将结果分成两个单独的类(考虑只有一个类应该是正数),则使用权重无关紧要,因为:

    • 对于第一类,低权重:预测所有的都是好的
    • 对于第二类,高权重:预测全零是好的(加权到非常好)

    因此,作为初始解决方案,您可以:

    • 使用'softmax' 激活(以确保您的模型只有一个正确的输出)和'categorical_crossentropy' 损失。
    • (或者,最好)使用只有一个类的模型并将'sigmoid''binary_crossentropy' 保持一致。

    我总是使用上述首选选项。在这种情况下,如果您使用大到足以包含一两个正样本的批量大小(您的批量大小约为 100),甚至可能会丢弃权重。如果批量太小并且很多批次不包含正面结果,那么您可能有太多的权重更新到纯零,这是不好的。

    您还可以对数据进行重新采样,例如,将正样本的数量乘以 10,这样您的批次包含更多正样本,训练变得更容易。

    用于确定训练何时结束的 AUC 指标示例:

    #in python - considering outputs with only one class
    def aucMetric(true, pred):
        true= K.flatten(true)
        pred = K.flatten(pred)
    
        totalCount = K.shape(true)[0]
    
        values, indices = tf.nn.top_k(pred, k = totalCount)        
        sortedTrue = K.gather(true, indices)
    
        tpCurve = K.cumsum(sortedTrue)
        negatives = 1 - sortedTrue
        auc = K.sum(tpCurve * negatives)
    
        totalCount = K.cast(totalCount, K.floatx())
        positiveCount = K.sum(true)
        negativeCount = totalCount - positiveCount
        totalArea = positiveCount * negativeCount
        return  auc / totalArea
    

    【讨论】:

      猜你喜欢
      • 2014-11-17
      • 2019-08-23
      • 2014-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2019-03-29
      • 2019-05-01
      相关资源
      最近更新 更多