图像分类。初始训练期间验证损失卡住 (v1)
Image Classification. Validation loss stuck during training with inception (v1)
我构建了一个小型自定义图像分类 training/val 数据集,其中包含 4 类。
训练数据集有大约 110.000 张图像。
验证数据集有 ~ 6.000 张图像。
我遇到的问题是,在训练期间,训练准确度(以最后训练样本的平均准确度衡量)和训练损失都有所提高,而验证准确度和损失保持不变。
这仅在我使用 inception 和 resnet 模型时发生,如果我在相同的训练和验证数据上使用 alexnet 模型,验证损失和准确性会提高
在我的实验中,我通过从 tensorflow.contrib.slim.nets
导入它们来使用几个卷积架构
代码组织如下:
...
images, labels = preprocessing(..., train=True)
val_images, val_labels = preprocessing(..., train=False)
...
# AlexNet model
with slim.arg_scope(alexnet.alexnet_v2_arg_scope()):
logits, _ = alexnet.alexnet_v2(images, ..., is_training=True)
tf.get_variable_scope().reuse_variables()
val_logits, _ = alexnet.alexnet_v2(val_images, ..., is_training=False)
# Inception v1 model
with slim.arg_scope(inception_v1_arg_scope()):
logits, _ = inception_v1(images, ..., is_training=True)
val_logits, _ = inception_v1(val_images, ..., is_training=False, reuse=True)
loss = my_stuff.loss(logits, labels)
val_loss = my_stuff.loss(val_logits, val_labels)
training_accuracy_op = tf.nn.in_top_k(logits, labels, 1)
top_1_op = tf.nn.in_top_k(val_logits, val_labels, 1)
train_op = ...
...
我没有使用单独的 eval 脚本,而是 运行 每个 epoch 结束时的验证步骤,并且出于调试目的,我 运行 是早期的 val 步骤(训练前),我通过对最后 x 步的训练预测进行平均来检查训练精度。
当我使用 Inception v1 模型(注释掉 alexnet 模型)时,记录器在 1 个纪元后输出如下:
early Validation Step
precision @ 1 = 0.2440 val loss = 1.39
Starting epoch 0
step 50, loss = 1.38, training_acc = 0.3250
...
step 1000, loss = 0.58, training_acc = 0.6725
...
step 3550, loss = 0.45, training_acc = 0.8063
Validation Step
precision @ 1 = 0.2473 val loss = 1.39
如图所示,训练准确率和损失在一个epoch后提高了很多,但验证损失根本没有变化。这已经测试了至少 10 次,结果总是一样的。我会理解验证损失是否由于过度拟合而变得更糟,但在这种情况下它根本没有改变。
为了排除验证数据的任何问题,我还展示了使用 slim 中的 AlexNet 实现进行训练时的结果。使用 alexnet 模型进行训练会产生以下输出:
early Validation Step
precision @ 1 = 0.2448 val loss = 1.39
Starting epoch 0
step 50, loss = 1.39, training_acc = 0.2587
...
step 350, loss = 1.38, training_acc = 0.2919
...
step 850, loss = 1.28, training_acc = 0.3898
Validation Step
precision @ 1 = 0.4069 val loss = 1.25
使用 alexnet 模型时,训练数据和测试数据中的准确性和验证损失都得到了正确改进,并且在随后的迭代中不断改进。
我不明白问题的原因是什么,以及为什么在使用 inception/resnet 模型时会出现问题,但在使用 alexnet 进行训练时却不会。
有没有人有想法?
您似乎在使用 logits 来计算验证损失;使用预测,它可能会有所帮助。
val_logits, _ = inception_v1(val_images, ..., is_training=False, reuse=True)
val_logits = tf.nn.softmax(val_logits)
通过论坛搜索、阅读各种帖子并进行试验后,我找到了问题的根源。
使用基本上从另一个示例回收的 train_op 是问题所在,它在 alexnet 模型上运行良好,但在其他模型上不起作用,因为它缺少批量规范化更新。
为了解决这个问题,我不得不使用
optimizer = tf.train.GradientDescentOptimizer(0.005)
train_op = slim.learning.create_train_op(total_loss, optimizer)
或
train_op = tf.contrib.layers.optimize_loss(total_loss, global_step, .005, 'SGD')
这似乎可以处理正在完成的 batchnorm 更新。
由于移动平均线更新缓慢,问题仍然存在于短期训练运行中。
默认的 slim arg_scope 将衰减设置为 0.9997,这是稳定的,但显然需要很多步骤才能收敛。使用相同的 arg_scope 但将衰减设置为 0.99 或 0.9 在这个简短的训练场景中确实有所帮助。
我构建了一个小型自定义图像分类 training/val 数据集,其中包含 4 类。 训练数据集有大约 110.000 张图像。 验证数据集有 ~ 6.000 张图像。
我遇到的问题是,在训练期间,训练准确度(以最后训练样本的平均准确度衡量)和训练损失都有所提高,而验证准确度和损失保持不变。
这仅在我使用 inception 和 resnet 模型时发生,如果我在相同的训练和验证数据上使用 alexnet 模型,验证损失和准确性会提高
在我的实验中,我通过从 tensorflow.contrib.slim.nets
导入它们来使用几个卷积架构代码组织如下:
...
images, labels = preprocessing(..., train=True)
val_images, val_labels = preprocessing(..., train=False)
...
# AlexNet model
with slim.arg_scope(alexnet.alexnet_v2_arg_scope()):
logits, _ = alexnet.alexnet_v2(images, ..., is_training=True)
tf.get_variable_scope().reuse_variables()
val_logits, _ = alexnet.alexnet_v2(val_images, ..., is_training=False)
# Inception v1 model
with slim.arg_scope(inception_v1_arg_scope()):
logits, _ = inception_v1(images, ..., is_training=True)
val_logits, _ = inception_v1(val_images, ..., is_training=False, reuse=True)
loss = my_stuff.loss(logits, labels)
val_loss = my_stuff.loss(val_logits, val_labels)
training_accuracy_op = tf.nn.in_top_k(logits, labels, 1)
top_1_op = tf.nn.in_top_k(val_logits, val_labels, 1)
train_op = ...
...
我没有使用单独的 eval 脚本,而是 运行 每个 epoch 结束时的验证步骤,并且出于调试目的,我 运行 是早期的 val 步骤(训练前),我通过对最后 x 步的训练预测进行平均来检查训练精度。
当我使用 Inception v1 模型(注释掉 alexnet 模型)时,记录器在 1 个纪元后输出如下:
early Validation Step
precision @ 1 = 0.2440 val loss = 1.39
Starting epoch 0
step 50, loss = 1.38, training_acc = 0.3250
...
step 1000, loss = 0.58, training_acc = 0.6725
...
step 3550, loss = 0.45, training_acc = 0.8063
Validation Step
precision @ 1 = 0.2473 val loss = 1.39
如图所示,训练准确率和损失在一个epoch后提高了很多,但验证损失根本没有变化。这已经测试了至少 10 次,结果总是一样的。我会理解验证损失是否由于过度拟合而变得更糟,但在这种情况下它根本没有改变。
为了排除验证数据的任何问题,我还展示了使用 slim 中的 AlexNet 实现进行训练时的结果。使用 alexnet 模型进行训练会产生以下输出:
early Validation Step
precision @ 1 = 0.2448 val loss = 1.39
Starting epoch 0
step 50, loss = 1.39, training_acc = 0.2587
...
step 350, loss = 1.38, training_acc = 0.2919
...
step 850, loss = 1.28, training_acc = 0.3898
Validation Step
precision @ 1 = 0.4069 val loss = 1.25
使用 alexnet 模型时,训练数据和测试数据中的准确性和验证损失都得到了正确改进,并且在随后的迭代中不断改进。
我不明白问题的原因是什么,以及为什么在使用 inception/resnet 模型时会出现问题,但在使用 alexnet 进行训练时却不会。
有没有人有想法?
您似乎在使用 logits 来计算验证损失;使用预测,它可能会有所帮助。
val_logits, _ = inception_v1(val_images, ..., is_training=False, reuse=True)
val_logits = tf.nn.softmax(val_logits)
通过论坛搜索、阅读各种帖子并进行试验后,我找到了问题的根源。
使用基本上从另一个示例回收的 train_op 是问题所在,它在 alexnet 模型上运行良好,但在其他模型上不起作用,因为它缺少批量规范化更新。
为了解决这个问题,我不得不使用
optimizer = tf.train.GradientDescentOptimizer(0.005)
train_op = slim.learning.create_train_op(total_loss, optimizer)
或
train_op = tf.contrib.layers.optimize_loss(total_loss, global_step, .005, 'SGD')
这似乎可以处理正在完成的 batchnorm 更新。
由于移动平均线更新缓慢,问题仍然存在于短期训练运行中。
默认的 slim arg_scope 将衰减设置为 0.9997,这是稳定的,但显然需要很多步骤才能收敛。使用相同的 arg_scope 但将衰减设置为 0.99 或 0.9 在这个简短的训练场景中确实有所帮助。