Keras:将逻辑回归性能与顺序神经网络匹配?

数据挖掘 分类 r 喀拉斯
2021-10-02 03:45:17

假设一个二元分类问题和一个相对较小的数据集 (R5000×39)。通过使用常见的 ML 技术,从逻辑回归开始,我能够在验证样本上达到 ~0.76-0.79 AUC,具体取决于模型。因此,显然有一些重要的信号需要从模型中提取。

然而,即使是最简单的顺序神经网络,它也根本不会学习。

即,使用 R 中的 keras:(注意:AFAIK 语言不应该是问题,因为它只是 R 的包装器)

model <- keras_model_sequential() %>%
         layer_dense(units = 48,
                     activation = "sigmoid",
                     input_shape = 39) %>%
         layer_dense(units = 48, activation = "sigmoid") %>%
         layer_dense(units = 2, activation = "sigmoid")


model %>% compile(
  optimizer = "rmsprop",
  loss = "categorical_crossentropy",
  metrics = c("accuracy")
)

history <- model %>% keras::fit(
  x_train,
  y_train,
  epochs = 500,
  batch_size = 16,
  validation_split = 0.7, shuffle = T
)

然而,无论历元数或批量大小,模型根本不会学习,验证准确度对应于目标变量的分布(预测全部为 1)。

我究竟做错了什么?带有 sigmoid 激活的小型一/二层神经网络不应该至少达到逻辑回归的性能吗?关于如何至少复制逻辑回归结果的任何建议?或者也许我错过了代码中的一些步骤?

任何见解都会很棒!

2个回答

调试神经网络是一项非常有经验的任务。您是否尝试过以下技术之一:

  • 减少神经网络的层数和神经元。逻辑回归模型有 39 个特征需要优化,而人工网络的形状有 40*48 + 49*48 + 49 * 2 = 4370 个参数。
  • 添加一些正则化,例如 dropout。

更详细一点,sigmoid 激活函数现在越来越少使用。更动态的激活函数(例如 RELU)通常会给出更好的结果。

只有最后一个问题可以确定。我想您的数据在正负类之间分布不均。我对吗 ?

您可能需要考虑的一些问题:

你的数据集够大吗?它是什么样的数据?时间序列?你应该洗牌吗?你使用什么学习率?您可以更改它并查看对学习曲线的影响:plot(history)输出吗?


对于您的模型,您通常只通过线性激活连接最后连接的层(即不使用激活函数,只使用单位矩阵)。您一直使用 sigmoid,这很好,但不适用于最后一层!我已经通过不包括这样的非线性来纠正这个问题,而是使用 softmax 激活,它将所有值压缩到 [0, 1] 的范围内,因此它们可以被解释为概率。

我增加了初始层中的层数和神经元的数量,并交换了首选的非线性:整流线性单元 (ReLU)我建议您快速阅读一下斯坦福 CS231n 课程的介绍,其中涵盖了一些最佳实践。此外,请在此处查看执行分类的大型网络示例,了解如何最好地使用 R Keras。

对以下代码进行测试,并绘制历史以更直观地了解训练的进展情况:可能需要多少个 epoch,是否过度拟合或欠拟合等。

model <- keras_model_sequential() %>%
    layer_dense(units = 200, activation = "relu", input_shape = 39) %>%
    layer_dense(units = 100, activation = "relu") %>%
    layer_dense(units = 100, activation = "relu") %>%
    layer_dense(units = 50, activation = "relu") %>%
    layer_dense(units = 2, activation = "softmax")


model %>% compile(
              optimizer = "rmsprop",
              loss = "categorical_crossentropy",
              metrics = c("accuracy")
          )

history <- model %>% keras::fit(
                                x_train,
                                y_train,
                                epochs = 500,
                                batch_size = 16,
                                validation_split = 0.7, shuffle = T
                            )


plot(history)                           # Are we overfitting?

免责声明:如果你没有太多数据,这个模型可能比你原来的模型更糟糕 - 或者你将大量过度拟合并获得 100% 的训练准确度和糟糕的验证/测试准确度。

很可能是您的数据只是用更简单的模型更好地建模,或者您没有足够的数据来让神经网络在其优化中磨练出一个很好的最优值。