Mask-RCNN 的哪些参数控制掩码召回?
Which parameters of Mask-RCNN control mask recall?
我对微调我用于实例分割的 Mask-RCNN 模型很感兴趣。目前我已经训练了6个epoch的模型,各种Mask-RCNN损失如下:
我停止的原因是 COCO 评估指标似乎在上一个时期有所下降:
我知道这是一个影响深远的问题,但我希望获得一些直觉,了解如何理解哪些参数对改进评估指标的影响最大。我明白要考虑三个地方:
- 我是否应该查看批量大小、学习率和动量,这使用学习率为 1e-4 且批量大小为 2 的 SGD 优化器?
- 我是否应该考虑使用更多的训练数据或添加增强(我目前没有使用任何数据)并且我的数据集当前是相当大的 40K 图像?
- 我应该查看具体的 MaskRCNN 参数吗?
我想我可能会被问到更具体的问题,我想改进什么,所以让我说我想提高个别口罩的召回率。该模型表现良好,但并未完全捕捉到我想要的全部内容。我也遗漏了具体学习问题的细节,因为我想获得一般如何处理这个问题的直觉。
一些注意事项:
- 即使您使用预先训练的网络,6 个时期对于网络来说也是一个收敛的方式。尤其是resnet50这么大的。我认为你至少需要 50 个纪元。在预训练的 resnet18 上,我在 30 个时期后开始获得良好的结果,resnet34 需要 +10-20 个时期,而你的 resnet50 + 40k 训练集图像 - 肯定需要比 6 个更多的时期;
- 绝对使用预训练网络;
- 根据我的经验,我未能通过 SGD 获得我喜欢的结果。我开始使用 AdamW + ReduceLROnPlateau 调度程序。网络收敛得非常快,比如 50-60% 的 AP 在第 7-8 个时期,但在 50-60 个时期之后它达到 80-85,使用从一个时期到另一个时期的非常小的改进,前提是 LR 足够小。您必须熟悉梯度下降概念。我曾经认为它好像你有更多的增强,你的“山丘”覆盖着你必须能够绕过的“巨石”,这只有在你控制 LR 时才有可能。此外,AdamW 有助于解决过度拟合问题。
我就是这样做的。对于具有更高输入分辨率的网络(您输入的图像由网络本身在输入时缩放),我使用更高的 lr。
init_lr = 0.00005
weight_decay = init_lr * 100
optimizer = torch.optim.AdamW(params, lr=init_lr, weight_decay=weight_decay)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, verbose=True, patience=3, factor=0.75)
for epoch in range(epochs):
# train for one epoch, printing every 10 iterations
metric_logger = train_one_epoch(model, optimizer, train_loader, scaler, device,
epoch, print_freq=10)
scheduler.step(metric_logger.loss.global_avg)
optimizer.param_groups[0]["weight_decay"] = optimizer.param_groups[0]["lr"] * 100
# scheduler.step()
# evaluate on the test dataset
evaluate(model, test_loader, device=device)
print("[INFO] serializing model to '{}' ...".format(args["model"]))
save_and_print_size_of_model(model, args["model"], script=False)
找到这样的 lr 和权重衰减,使训练在训练结束时将 lr 耗尽到一个非常小的值,例如初始 lr 的 1/10。如果您的平台太频繁,调度程序会迅速将其调至非常小的值,并且网络将在所有剩余的 epoch 中学习不到任何东西。
您的绘图表明您的 LR 在训练的某个时刻过高,网络停止训练,然后 AP 下降。您需要不断改进,即使是很小的改进。网络训练得越多,它了解的有关您领域的细微细节就越多,学习率就越小。恕我直言,常量 LR 不允许正确执行此操作。
锚生成器设置。这是我初始化网络的方式。
def get_maskrcnn_resnet_model(name, num_classes, pretrained, res='normal'):
print('Using maskrcnn with {} backbone...'.format(name))
backbone = resnet_fpn_backbone(name, pretrained=pretrained, trainable_layers=5)
sizes = ((4,), (8,), (16,), (32,), (64,))
aspect_ratios = ((0.25, 0.5, 1.0, 2.0, 4.0),) * len(sizes)
anchor_generator = AnchorGenerator(
sizes=sizes, aspect_ratios=aspect_ratios
)
roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0', '1', '2', '3'],
output_size=7, sampling_ratio=2)
default_min_size = 800
default_max_size = 1333
if res == 'low':
min_size = int(default_min_size / 1.25)
max_size = int(default_max_size / 1.25)
elif res == 'normal':
min_size = default_min_size
max_size = default_max_size
elif res == 'high':
min_size = int(default_min_size * 1.25)
max_size = int(default_max_size * 1.25)
else:
raise ValueError('Invalid res={} param'.format(res))
model = MaskRCNN(backbone, min_size=min_size, max_size=max_size, num_classes=num_classes,
rpn_anchor_generator=anchor_generator, box_roi_pool=roi_pooler)
model.roi_heads.detections_per_img = 512
return model
我需要在这里找到小对象,为什么我使用这样的锚参数。
- 类 平衡问题。如果你只有你的对象和 bg - 没问题。如果您有更多 类,那么请确保您的训练拆分(80% 用于训练,20% 用于测试)或多或少精确地应用于您特定训练中使用的所有 类。
祝你好运!
我对微调我用于实例分割的 Mask-RCNN 模型很感兴趣。目前我已经训练了6个epoch的模型,各种Mask-RCNN损失如下:
我停止的原因是 COCO 评估指标似乎在上一个时期有所下降:
我知道这是一个影响深远的问题,但我希望获得一些直觉,了解如何理解哪些参数对改进评估指标的影响最大。我明白要考虑三个地方:
- 我是否应该查看批量大小、学习率和动量,这使用学习率为 1e-4 且批量大小为 2 的 SGD 优化器?
- 我是否应该考虑使用更多的训练数据或添加增强(我目前没有使用任何数据)并且我的数据集当前是相当大的 40K 图像?
- 我应该查看具体的 MaskRCNN 参数吗?
我想我可能会被问到更具体的问题,我想改进什么,所以让我说我想提高个别口罩的召回率。该模型表现良好,但并未完全捕捉到我想要的全部内容。我也遗漏了具体学习问题的细节,因为我想获得一般如何处理这个问题的直觉。
一些注意事项:
- 即使您使用预先训练的网络,6 个时期对于网络来说也是一个收敛的方式。尤其是resnet50这么大的。我认为你至少需要 50 个纪元。在预训练的 resnet18 上,我在 30 个时期后开始获得良好的结果,resnet34 需要 +10-20 个时期,而你的 resnet50 + 40k 训练集图像 - 肯定需要比 6 个更多的时期;
- 绝对使用预训练网络;
- 根据我的经验,我未能通过 SGD 获得我喜欢的结果。我开始使用 AdamW + ReduceLROnPlateau 调度程序。网络收敛得非常快,比如 50-60% 的 AP 在第 7-8 个时期,但在 50-60 个时期之后它达到 80-85,使用从一个时期到另一个时期的非常小的改进,前提是 LR 足够小。您必须熟悉梯度下降概念。我曾经认为它好像你有更多的增强,你的“山丘”覆盖着你必须能够绕过的“巨石”,这只有在你控制 LR 时才有可能。此外,AdamW 有助于解决过度拟合问题。
我就是这样做的。对于具有更高输入分辨率的网络(您输入的图像由网络本身在输入时缩放),我使用更高的 lr。
init_lr = 0.00005
weight_decay = init_lr * 100
optimizer = torch.optim.AdamW(params, lr=init_lr, weight_decay=weight_decay)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, verbose=True, patience=3, factor=0.75)
for epoch in range(epochs):
# train for one epoch, printing every 10 iterations
metric_logger = train_one_epoch(model, optimizer, train_loader, scaler, device,
epoch, print_freq=10)
scheduler.step(metric_logger.loss.global_avg)
optimizer.param_groups[0]["weight_decay"] = optimizer.param_groups[0]["lr"] * 100
# scheduler.step()
# evaluate on the test dataset
evaluate(model, test_loader, device=device)
print("[INFO] serializing model to '{}' ...".format(args["model"]))
save_and_print_size_of_model(model, args["model"], script=False)
找到这样的 lr 和权重衰减,使训练在训练结束时将 lr 耗尽到一个非常小的值,例如初始 lr 的 1/10。如果您的平台太频繁,调度程序会迅速将其调至非常小的值,并且网络将在所有剩余的 epoch 中学习不到任何东西。
您的绘图表明您的 LR 在训练的某个时刻过高,网络停止训练,然后 AP 下降。您需要不断改进,即使是很小的改进。网络训练得越多,它了解的有关您领域的细微细节就越多,学习率就越小。恕我直言,常量 LR 不允许正确执行此操作。
锚生成器设置。这是我初始化网络的方式。
def get_maskrcnn_resnet_model(name, num_classes, pretrained, res='normal'): print('Using maskrcnn with {} backbone...'.format(name)) backbone = resnet_fpn_backbone(name, pretrained=pretrained, trainable_layers=5) sizes = ((4,), (8,), (16,), (32,), (64,)) aspect_ratios = ((0.25, 0.5, 1.0, 2.0, 4.0),) * len(sizes) anchor_generator = AnchorGenerator( sizes=sizes, aspect_ratios=aspect_ratios ) roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0', '1', '2', '3'], output_size=7, sampling_ratio=2) default_min_size = 800 default_max_size = 1333 if res == 'low': min_size = int(default_min_size / 1.25) max_size = int(default_max_size / 1.25) elif res == 'normal': min_size = default_min_size max_size = default_max_size elif res == 'high': min_size = int(default_min_size * 1.25) max_size = int(default_max_size * 1.25) else: raise ValueError('Invalid res={} param'.format(res)) model = MaskRCNN(backbone, min_size=min_size, max_size=max_size, num_classes=num_classes, rpn_anchor_generator=anchor_generator, box_roi_pool=roi_pooler) model.roi_heads.detections_per_img = 512 return model
我需要在这里找到小对象,为什么我使用这样的锚参数。
- 类 平衡问题。如果你只有你的对象和 bg - 没问题。如果您有更多 类,那么请确保您的训练拆分(80% 用于训练,20% 用于测试)或多或少精确地应用于您特定训练中使用的所有 类。
祝你好运!