二进制分类未正确训练
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 这正常吗?我预计准确度会缓慢增加,而不是像我们在这里看到的那样呈锯齿状上下增加
也许可以尝试学习率较低的亚当优化器,我认为振荡会更少。我认为这不正常,实际上可能与您的数据有关。根据我的建议,模型应该没有问题。如果答案有帮助,如果您能接受,我会很高兴。以上是关于二进制分类未正确训练的主要内容,如果未能解决你的问题,请参考以下文章
当测试和训练数据集来自不同来源时,为啥测试准确性保持不变并且不会增加二进制分类
在训练 Bert 二进制分类模型时,Huggingface 变形金刚返回“ValueError:要解包的值太多(预期为 2)”