RPN 的训练问题
我正在尝试为区域提议训练一个网络,就像在Pascal VOC 2012 训练数据上的Faster R-CNN中的锚框概念一样。
我正在使用一个预训练的Resnet 101主干,三层弹出。弹出的图层是conv5_x layer, average pooling layer
和softmax layer
。
因此,对于大小为 600*600 的图像,我输入到 RPN 头的卷积特征图的空间分辨率为 37 x 37,具有 1024 个通道。
我已将仅块 conv4_x 的梯度设置为可训练的。从那里我使用 torchvision.models.detection rpn 代码来使用 rpn.AnchorGenerator、rpn.RPNHead 和最终 rpn.RegionProposalNetwork 类。调用 forward 会返回两个损失,即对象损失和回归损失。
我遇到的问题是我的模型训练非常非常缓慢(因为损失的改善非常缓慢)。在 Girschick 的原始论文中,他说他训练了超过 80K 小批量(自 Pascal VOC 2012 数据集有大约 11000 张图像以来大约 8 个时期),其中每个小批量是具有 256 个锚框的单个图像,但我的网络从一个时期到另一个时期改善了它的损失非常缓慢,我正在训练 30 多个 epoch。
下面是我的网络课程代码。
class ResnetRegionProposalNetwork(torch.nn.Module):
def __init__(self):
super(ResnetRegionProposalNetwork, self).__init__()
self.resnet_backbone = torch.nn.Sequential(*list(models.resnet101(pretrained=True).children())[:-3])
non_trainable_backbone_layers = 5
counter = 0
for child in self.resnet_backbone:
if counter < non_trainable_backbone_layers:
for param in child.parameters():
param.requires_grad = False
counter += 1
else:
break
anchor_sizes = ((32,), (64,), (128,), (256,), (512,))
aspect_ratios = ((0.5, 1.0, 2.0),) * len(anchor_sizes)
self.rpn_anchor_generator = rpn.AnchorGenerator(
anchor_sizes, aspect_ratios
)
out_channels = 1024
self.rpn_head = rpn.RPNHead(
out_channels, self.rpn_anchor_generator.num_anchors_per_location()[0]
)
rpn_pre_nms_top_n = {"training": 2000, "testing": 1000}
rpn_post_nms_top_n = {"training": 2000, "testing": 1000}
rpn_nms_thresh = 0.7
rpn_fg_iou_thresh = 0.7
rpn_bg_iou_thresh = 0.2
rpn_batch_size_per_image = 256
rpn_positive_fraction = 0.5
self.rpn = rpn.RegionProposalNetwork(
self.rpn_anchor_generator, self.rpn_head,
rpn_fg_iou_thresh, rpn_bg_iou_thresh,
rpn_batch_size_per_image, rpn_positive_fraction,
rpn_pre_nms_top_n, rpn_post_nms_top_n, rpn_nms_thresh)
def forward(self,
images, # type: ImageList
targets=None # type: Optional[List[Dict[str, Tensor]]]
):
feature_maps = self.resnet_backbone(images)
features = {"0": feature_maps}
image_sizes = getImageSizes(images)
image_list = il.ImageList(images, image_sizes)
return self.rpn(image_list, features, targets)
我正在使用具有以下参数的亚当优化器:
optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, ResnetRPN.parameters()), lr=0.01, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
我的训练循环在这里:
for epoch_num in range(epochs): # will train epoch number of times per execution of this program
loss_per_epoch = 0.0
dl_iterator = iter(P.getPascalVOC2012DataLoader())
current_epoch = epoch + epoch_num
saveModelDuringTraining(current_epoch, ResnetRPN, optimizer, running_loss)
batch_number = 0
for image_batch, ground_truth_box_batch in dl_iterator:
#print(batch_number)
optimizer.zero_grad()
boxes, losses = ResnetRPN(image_batch, ground_truth_box_batch)
losses = losses["loss_objectness"] + losses["loss_rpn_box_reg"]
losses.backward()
optimizer.step()
running_loss += float(losses)
batch_number += 1
if batch_number % 100 == 0: # print the loss on every batch of 100 images
print('[%d, %5d] loss: %.3f' %
(current_epoch + 1, batch_number + 1, running_loss))
string_to_print = "\n epoch number:" + str(epoch + 1) + ", batch number:" \
+ str(batch_number + 1) + ", running loss: " + str(running_loss)
printToFile(string_to_print)
loss_per_epoch += running_loss
running_loss = 0.0
print("finished Epoch with epoch loss " + str(loss_per_epoch))
printToFile("Finished Epoch: " + str(epoch + 1) + " with epoch loss: " + str(loss_per_epoch))
loss_per_epoch = 0.0
我正在考虑尝试以下想法来非常缓慢地修复网络训练:
- 尝试各种学习率(尽管我已经尝试过 0.01、0.001、0.003 的结果相似
- 各种批次大小(到目前为止,最好的结果是 4 个批次(4 张图像 * 每张图像 256 个锚点)
- 冻结更多/更少的 Resnet-101 主干层
- 完全使用不同的优化器
- 损失函数的不同权重
非常感谢我的方法有任何明显错误的提示或事情。我很乐意向任何可以提供帮助的人提供更多信息。
编辑:我的网络在快速 GPU 上进行训练,图像和边界框作为火炬张量。