MIDV 500 文档本地化:适配问题
MIDV 500 document localization: fitting problem
我一直在试验 MIDV 500 数据集的一部分,试图将文档定位为四边形。
所以,我的输出是一个由 8 个浮点数组成的向量。
RGB 图像被缩放到 960 x 540 像素(960、540、3),像素值被缩放到 [0..1]。
目标向量也缩放到 [0..1](简单地除以图像暗淡)
我的第一种方法是从 Keras 应用程序(尝试过 EfficientNetB0-2)使用以下 Dense head 预训练 CNN(+ 微调):
effnet = EfficientNetB0(weights="imagenet", include_top=False, input_shape=(540, 960, 3))
# effnet.trainable = False
for layer in effnet.layers:
if 'block7a' not in layer.name and 'top' not in layer.name:
layer.trainable = False
model = Sequential()
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(64, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(32, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(8, activation='sigmoid'))
opt = Nadam(learning_rate=0.001)
model.compile(metrics=[iou_metric], loss=iou_loss, optimizer=opt)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.6, patience=10)
early_stopping = EarlyStopping(monitor='val_loss', patience=25)
添加了一些回调,使用 Nadam 作为优化器,使用 Jaccard 分数作为损失和指标。
Loss graph
从损失图中可以看出,训练损失在训练过程中减少了。虽然,val 损失表现得很奇怪。
在 ~30 个时期后 model.predict() 给出了一组相同的向量 ([0., 0., 1., 1., 0., 0., 0., 1.] * shape of val_x)。我不确定它是过拟合还是欠拟合(不过似乎是错误的方法)。
那么,你能告诉我我做错了什么吗?我尝试了几种不同的损失函数,在缩放到 [0..1] 之前和之后仔细检查了我的数据。将尝试使用 UNet 之类的方法进行分段,但本地化似乎是正确的。
两件事:
- 请检查您使用的是哪个版本的 TensorFlow (TF)。我相信从 2.5 开始,您不需要将输入图像重新缩放到范围 [0-1]。网络需要 [0-255] 的张量。 https://keras.io/api/applications/efficientnet/
- 你的模型架构和回调看起来没问题(不过我不是这个优化器 + 损失方面的专家)。因此,我假设问题可能来自您的数据输入。您是否使用 ImageDataGenerator 作为输入并将数据从训练和验证中分离出来?如果没有,可能值得一试。您可以指定验证子集,生成器将为您拆分数据。更多信息在这里:https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
descent。最后,健康的梯度下降。
所以,解决方案:
- 正如@Nicolas Perez de Olaguer 之前提到的,我应该使用 non-scaled 图像数据(具有 3 个通道的常规 RBG 图像缩放到 [0..255])
- 我一直在尝试解决定位问题,这是四边形回归,您可以在其中预测四边形节点坐标(不同于 bbox 回归,您在其中预测矢量为 4)。我决定使用现代 IOU 损失(Jaccard 损失),它通常用于 bbox 回归并期望向量 4 作为输入,尽管我的向量有 8 个元素并且 由于具体问题,损失函数计算不正确。
- 另外,我的模型有一些你们应该学习的设计流程。首先,我添加了很多密集层,1 或 2 层就足够了(更多只会减慢训练过程)。其次,我选择了太大的图像分辨率,这再次只会减慢训练过程(大的白色四边形定位对于那么大的分辨率来说是一个过于简单的问题)。最后,我还没有考虑 ImageNet 权重,它有时可能会由于高度非典型数据而降低训练质量(如果您尝试在它从未见过的对象上使用预训练的 CNN)。
感谢您的关注和帮助。我会将此答案标记为解决方案。
我一直在试验 MIDV 500 数据集的一部分,试图将文档定位为四边形。 所以,我的输出是一个由 8 个浮点数组成的向量。
RGB 图像被缩放到 960 x 540 像素(960、540、3),像素值被缩放到 [0..1]。 目标向量也缩放到 [0..1](简单地除以图像暗淡)
我的第一种方法是从 Keras 应用程序(尝试过 EfficientNetB0-2)使用以下 Dense head 预训练 CNN(+ 微调):
effnet = EfficientNetB0(weights="imagenet", include_top=False, input_shape=(540, 960, 3))
# effnet.trainable = False
for layer in effnet.layers:
if 'block7a' not in layer.name and 'top' not in layer.name:
layer.trainable = False
model = Sequential()
model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(64, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(32, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(8, activation='sigmoid'))
opt = Nadam(learning_rate=0.001)
model.compile(metrics=[iou_metric], loss=iou_loss, optimizer=opt)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.6, patience=10)
early_stopping = EarlyStopping(monitor='val_loss', patience=25)
添加了一些回调,使用 Nadam 作为优化器,使用 Jaccard 分数作为损失和指标。
Loss graph
从损失图中可以看出,训练损失在训练过程中减少了。虽然,val 损失表现得很奇怪。
在 ~30 个时期后 model.predict() 给出了一组相同的向量 ([0., 0., 1., 1., 0., 0., 0., 1.] * shape of val_x)。我不确定它是过拟合还是欠拟合(不过似乎是错误的方法)。
那么,你能告诉我我做错了什么吗?我尝试了几种不同的损失函数,在缩放到 [0..1] 之前和之后仔细检查了我的数据。将尝试使用 UNet 之类的方法进行分段,但本地化似乎是正确的。
两件事:
- 请检查您使用的是哪个版本的 TensorFlow (TF)。我相信从 2.5 开始,您不需要将输入图像重新缩放到范围 [0-1]。网络需要 [0-255] 的张量。 https://keras.io/api/applications/efficientnet/
- 你的模型架构和回调看起来没问题(不过我不是这个优化器 + 损失方面的专家)。因此,我假设问题可能来自您的数据输入。您是否使用 ImageDataGenerator 作为输入并将数据从训练和验证中分离出来?如果没有,可能值得一试。您可以指定验证子集,生成器将为您拆分数据。更多信息在这里:https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
descent。最后,健康的梯度下降。 所以,解决方案:
- 正如@Nicolas Perez de Olaguer 之前提到的,我应该使用 non-scaled 图像数据(具有 3 个通道的常规 RBG 图像缩放到 [0..255])
- 我一直在尝试解决定位问题,这是四边形回归,您可以在其中预测四边形节点坐标(不同于 bbox 回归,您在其中预测矢量为 4)。我决定使用现代 IOU 损失(Jaccard 损失),它通常用于 bbox 回归并期望向量 4 作为输入,尽管我的向量有 8 个元素并且 由于具体问题,损失函数计算不正确。
- 另外,我的模型有一些你们应该学习的设计流程。首先,我添加了很多密集层,1 或 2 层就足够了(更多只会减慢训练过程)。其次,我选择了太大的图像分辨率,这再次只会减慢训练过程(大的白色四边形定位对于那么大的分辨率来说是一个过于简单的问题)。最后,我还没有考虑 ImageNet 权重,它有时可能会由于高度非典型数据而降低训练质量(如果您尝试在它从未见过的对象上使用预训练的 CNN)。
感谢您的关注和帮助。我会将此答案标记为解决方案。