4损失函数
损失函数作者选择使用的依旧是SSD的Smooth L1 Loss以及Cross Entropy Loss,其中Smooth L1 Loss用于边界框的回归,而Cross Entropy Loss则用于分类。
具体pytorch实现如下:
class MultiboxLoss(nn.Module): def __init__(self, priors, neg_pos_ratio, center_variance, size_variance, device): """Implement SSD Multibox Loss. Basically, Multibox loss combines classification loss and Smooth L1 regression loss. """ super(MultiboxLoss, self).__init__() self.neg_pos_ratio = neg_pos_ratio self.center_variance = center_variance self.size_variance = size_variance self.priors = priors self.priors.to(device) def forward(self, confidence, predicted_locations, labels, gt_locations): """Compute classification loss and smooth l1 loss. Args: confidence (batch_size, num_priors, num_classes): class predictions. locations (batch_size, num_priors, 4): predicted locations. labels (batch_size, num_priors): real labels of all the priors. boxes (batch_size, num_priors, 4): real boxes corresponding all the priors. """ num_classes = confidence.size(2) with torch.no_grad(): # derived from cross_entropy=sum(log(p)) loss = -F.log_softmax(confidence, dim=2)[:, :, 0] mask = box_utils.hard_negative_mining(loss, labels, self.neg_pos_ratio) confidence = confidence[mask, :] # 分类损失函数 classification_loss = F.cross_entropy(confidence.reshape(-1, num_classes), labels[mask], reduction='sum') pos_mask = labels > 0 predicted_locations = predicted_locations[pos_mask, :].reshape(-1, 4) gt_locations = gt_locations[pos_mask, :].reshape(-1, 4) # 边界框回归损失函数 smooth_l1_loss = F.smooth_l1_loss(predicted_locations, gt_locations, reduction='sum') # smooth_l1_loss # smooth_l1_loss = F.mse_loss(predicted_locations, gt_locations, reduction='sum') #l2 loss num_pos = gt_locations.size(0) return smooth_l1_loss / num_pos, classification_loss / num_pos
5结果预测
输入为:
输出为:
输入为:
输出为:
6模型转换
由于部署使用的是Tengine边缘推理框架,由于pytorch输出的模型无法直接转换到tmfile模型下,因此还是选择使用onnx中间件的形式进行过度,具体实现代码如下:
model_path = "models/pretrained/version-RFB-320.pth" net = create_Mb_Tiny_RFB_fd(len(class_names), is_test=True) net.load(model_path) net.eval() net.to("cuda") model_name = model_path.split("/")[-1].split(".")[0] model_path = f"models/onnx/{model_name}.onnx" dummy_input = torch.randn(1, 3, 240, 320).to("cuda") # dummy_input = torch.randn(1, 3, 480, 640).to("cuda") #if input size is 640*480 torch.onnx.export(net, dummy_input, model_path, verbose=False, input_names=['input'], output_names=['scores', 'boxes'])
得到onnx模型后便可以进行Tengine模型的转换和部署,该部分将在下一篇文章继续讨论。
7参考
[1].https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB
[2].https://github.com/onnx/onnx