yolov3 05节(03)基本完成
序
中途帮老师搞什么新的课题,耽误了这么久,但好在yolov3之前无法检测的bug已经修复完成了,通过3-4天的非连续debug和思考,我感觉自己对yolov3的检测框架有了更加深刻的认识,包括pytorch数据的格式、darknet网络中数据的传输、检测框的实现等等,历经15多天去复现yolov3感觉还是有所收获,等后续有空可以写一篇简单的文章记录一下。
bug修复
上次跟踪到了darknet模块中,即获得的前向传播结果prediction就是错的
with torch.no_grad(): prediction = model(batch, CUDA) # 前向传播获得的结果
继续跟进后,在darknet的forward前向传播方法当中,第一次执行conv卷积块可以获得结果,但是进行第二次的时候,所有结果均会成为nan,包括weight权重当中的值也变成立nan;
这时候问题必然出现在load_weight方法中,因为第二次卷积紧接着第一次的结果,其中没有其他方法变量干涉,除了最开始加载的weights
反复对比结果,最后我发现自己把加载conv权重的代码,写进了加载conv偏执里去了,最终导致结果错误,还是得细心才行。
if module_type == "convolutional": model = self.module_list[i] try: batch_normalize = int(self.blocks[i + 1]["batch_normalize"]) except: batch_normalize = 0 conv = model[0] if batch_normalize: # 存在bn的情况 bn = model[1] # bn层权重数量 num_bn_biases = bn.bias.numel() # 加载bn权重 bn_biases = torch.from_numpy(weights[ptr:ptr+num_bn_biases]) ptr+=num_bn_biases bn_weights = torch.from_numpy(weights[ptr: ptr + num_bn_biases]) ptr += num_bn_biases bn_running_mean = torch.from_numpy(weights[ptr: ptr + num_bn_biases]) ptr += num_bn_biases bn_running_var = torch.from_numpy(weights[ptr: ptr + num_bn_biases]) ptr += num_bn_biases # 设置权重到相同的dims bn_biases = bn_biases.view_as(bn.bias.data) bn_weights = bn_weights.view_as(bn.weight.data) bn_running_mean = bn_running_mean.view_as(bn.running_mean) bn_running_var = bn_running_var.view_as(bn.running_var) # copy数据到模型 bn.bias.data.copy_(bn_biases) bn.weight.data.copy_(bn_weights) bn.running_mean.copy_(bn_running_mean) bn.running_var.copy_(bn_running_var) else: # 卷积层偏执 num_biases = conv.bias.numel() conv_biases = torch.from_numpy(weights[ptr:ptr+num_biases]) ptr+=num_biases conv_biases = conv_biases.view_as(conv.bias.data) # 对应维度 conv.bias.data.copy_(conv_biases) # 加载卷积层权重 num_weights = conv.weight.numel() conv_weights = torch.from_numpy(weights[ptr:ptr + num_weights]) ptr = ptr + num_weights conv_weights = conv_weights.view_as(conv.weight.data) conv.weight.data.copy_(conv_weights)
排除了这个bug后,剩下的一个大bug是位于write_result方法当中,即将prediction预测结果转为coco的80个类别部分出错了。
此处bug带来的问题是一次只能检测出一个种类,而且检测框绘制的范围也不正确,有偏差。
针对这个问题,考虑到prediction结果系正确的:
1)那么可能是在多个检测结果cat成一个大张量的过程中,后面的张量把前面的覆盖掉了,没有形成正确的cat;
2)或者是提前结束了检测过程,导致数据缺失
这样也能解释检测框位置偏差的问题。最终通过逐步debug,发现了在NMS当中,选择最佳边界框的代码出现了问题,简单且隐蔽,简单来说就是犯了(1)中的错误,但也同样产生了(2)中的后果
检测结果
完成了代码不跑几个图片玩玩怎么合适?所以我从网上随便搞了几个图片进行了测试
性能大概就是这样
很有趣,据说yolov3在 810平台?可以达到30帧/s的速度,使用c++应该会更快一些,所以对视频检测方面也可以适用,就是第一张图片检测耗时之外,后续图片就非常快了,不愧是工业上争相搭建的框架,
我都怀疑学校旁边的超市发入口的体温检测都是这个框架做的了。
当然教程中也有关于视频检测的方面,我还没有复现,后续再补上,而且训练部分都还没写呢。
作为个人第一次实现的深度学习项目,个人觉得yolov3是个非常好的入门教程,寒假有空希望自己能独立看论文复现出yolov4,好耶。