二进制分类未正确训练

Posted

技术标签:

【中文标题】二进制分类未正确训练【英文标题】:Binary classification not training correctly 【发布时间】:2021-07-25 06:49:47 【问题描述】:

我一直在研究可以对两组天文数据进行分类的神经网络。我相信我的神经网络正在苦苦挣扎,因为这两组数据非常相似,但即使对数据进行了重大更改,准确度历史似乎仍然不像我想象的那样表现。

这些是来自每个数据集的示例图像:

我目前使用每种类型的 10,000 张图像,其中 20% 用于验证数据,因此 16,000 个训练图像和 4,000 个验证图像。由于内存限制,我无法增加更多数据集。

这是我目前的模型:

model.add(layers.Conv2D(64, (3, 3), padding="valid", activation='relu', input_shape=(192, 192, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (7, 7), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (9, 9), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (7, 7), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(2, activation="sigmoid"))

我正在编译:

opt = SGD(lr=0.1)
model.compile(optimizer=opt,
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

并使用以下方法进行拟合:

history = model.fit(train, train_labels, batch_size=200, epochs=15, validation_data=(validation, validation_labels))

如果我在数据中添加一些东西以使数据集不切实际地不同(例如,在数据中间添加一个随机矩形,或者为一个而不是另一个添加一个掩码),我会得到一个看起来像这样的准确度历史记录:

(请注意,训练数据的准确度历史记录向左移动了半个纪元,以说明所测量的训练准确度,平均而言,在验证准确度之前半个纪元。)

如果我使数据集非常相似(例如,不向数据集添加任何内容或对两者应用相同的掩码),我会得到如下所示的准确度历史记录:

或者偶尔在一个 epoch 的验证准确度上会出现大幅飙升,如下所示:

查看不同的网站和其他 *** 页面,我尝试过:

更改过滤器的数量和大小 增加或减少卷积层 更改优化器函数(它最初是“adam”,因此它具有自适应学习率,我将其切换为上述,以便手动调整学习率) 增加批量大小 增加数据集(最初每个只有 5,000 张图像,而不是 10,000 张), 增加 epoch 的数量(从 10 到 15) 在卷积层中添加或减去填充 改变最后一层的激活函数

我错过了什么吗?这些数据集是否太相似而无法实现二元分类网络?

【问题讨论】:

【参考方案1】:

如果这是一个二元分类,那么你需要改变:

model.add(layers.Dense(2, activation="sigmoid"))

进入:

model.add(layers.Dense(1, activation="sigmoid"))

Sigmoid 表示如果输出大于某个阈值(大多数时候为 0.5),则它属于第二类等。此外,您确实不需要使用 from_logits = True,因为您在最后一个密集中指定了激活层。

回想一下,您的损失也应该是:

tf.keras.losses.BinaryCrossentropy(from_logits = False)

如果你想设置from_logits = True,那么你的最后一个密集层应该是这样的:

model.add(layers.Dense(1)) # no activation, linear.

您也可以在最后一个密集层中使用 2 个神经元,但随后您需要使用带有分类损失的 softmax 激活。

【讨论】:

感谢您的回复!我已将最后的图层切换为layers.Dense(1)。我尝试使用 from_logits=False 和 sigmoid 激活函数运行它,然后再次使用 from_logits=True 和没有激活函数,但两者都返回了与上述相似的验证准确度,验证准确度在所有时期都保持在 50%,训练准确度跳跃100% 到 50% 之间 0.1 LR 太高了,我先试试降低它。然后随着图像尺寸的减小,增加 CNN 中过滤器的大小和数量。喜欢Conv2D(32,(3,3)) .. Conv2D(64,(3,3)等。 谢谢!!这看起来好多了。最后一个问题,所以我明白发生了什么:验证准确度仍然会在 50% 到 100% 准确度之间跳跃,然后才能达到 100% 准确度。我把它放在here 这正常吗?我预计准确度会缓慢增加,而不是像我们在这里看到的那样呈锯齿状上下增加 也许可以尝试学习率较低的亚当优化器,我认为振荡会更少。我认为这不正常,实际上可能与您的数据有关。根据我的建议,模型应该没有问题。如果答案有帮助,如果您能接受,我会很高兴。

以上是关于二进制分类未正确训练的主要内容,如果未能解决你的问题,请参考以下文章

请帮助我选择正确的分类器

如何从 CSV 文件训练和测试一个简单的二进制分类器?

当测试和训练数据集来自不同来源时,为啥测试准确性保持不变并且不会增加二进制分类

在训练 Bert 二进制分类模型时,Huggingface 变形金刚返回“ValueError:要解包的值太多(预期为 2)”

仅具有正数和未标记数据集的二进制半监督分类

具有季节性类别变化的日期文档的二进制分类