(9)训练时报错KeyError: ‘conv1.1.0.weight‘

将B_mobilenet_yolov4_lite的PANet改为原来的3x3卷积,命名为L_mobilenet-yolov4_VOC,即将B_yolov4的主干网络换为mobilenet,训练时报错:

Traceback (most recent call last):
  File "/home/PycharmProjects/yolov4/L_mobilenet-yolov4_VOC_0717/train.py", line 221, in 
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if np.shape(model_dict[k]) == np.shape(v)}
  File "/home/PycharmProjects/yolov4/L_mobilenet-yolov4_VOC_0717/train.py", line 221, in 
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if np.shape(model_dict[k]) == np.shape(v)}
KeyError: 'conv1.1.0.weight'

该问题的错误原因:加载的模型pretrained_dict文件中没有conv1.1.0.weight这个权重内容,打印网络模型和预训练模型的键值,发现键值不同。检查确定所有函数中的主干和权重等选择的都是同一个模型,且加载预训练权重也是mobilenet,即:网络结构一样,但结构命名不同。

尝试1:将220-222这三行代码注释掉,程序可以运行,但不知道会不会对结果造成影响。猜测:隐约记得所使用代码的主人在哪里说过,如果不加载主干权重默认加载他在VOC数据集上训练得到的权重,如果是这样的话再训练VOC数据集就。。。(将这三行注释掉后,打印model_dict好像是没有权重?也就是全是0或者1,这部分后续待探索)

尝试2:按照diudiu~bo的博客“Mobilenet-yolov4代码调试”记录,将

pretrained_dict = {k: v for k, v in pretrained_dict.items() if np.shape(model_dict[k]) ==  np.shape(v)}

替换为

pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}

结果:程序不再报错,可以运行,但貌似没有载入预训练权重,因为按照这样运行,在执行完

model_dict.update(pretrained_dict)后,打印model_dict,结果为空字典。

尝试3:分析预训练网络和当前网络,结构相同但命名不同,即对应的每一层名字不同,shape相同,因此,通过对比shape/size来载入预训练权重。参考https://blog.csdn.net/feizai1208917009/article/details/103598233#commentBox的方法一,将那一行代码替换为以下代码块:

# 取出预训练网络的参数字典
keys = []
    for k, v in pretrained_dict.items():
        keys.append(k)
    i = 0

    # 自己网络和预训练网络结构一致的层,使用预训练网络对应层的参数初始化
    for k, v in model_dict.items():
        if v.size() == pretrained_dict[keys[i]].size():
            model_dict[k] = pretrained_dict[keys[i]]
            i = i + 1
  
   # print(model_dict)

将打印的model_dict的键值与预训练网络权重和原始model_dict对比,发现已正确载入预训练权重,即打印的结果为:model_dict的键和预训练网络权重的值。

但运行最后在if v.size() == pretrained_dict[keys[i]].size():这行报错:

IndexError: list index out of range

考虑是因为代码最后有i=i+1,在遍历完pretrained_dict之后,i又增加1,所以在下次循环时报错列表超出范围,因此,需要给i加个条件使遍历完pretrained_dict之后不进入循环,直接结束for循环,将代码改为如下格式:

# 取出预训练网络的参数字典
    keys = []
    j = 0
    for k, v in pretrained_dict.items():
        keys.append(k)
        j = j + 1
    # print(j)
    i = 0

    # 自己网络和预训练网络结构一致的层,使用预训练网络对应层的参数初始化
    for k, v in model_dict.items():
        if v.size() == pretrained_dict[keys[i]].size():
            model_dict[k] = pretrained_dict[keys[i]]
            i = i + 1
            if i >= j:
                break

    # print(model_dict)

增加k为pretrained_dict中键值对的数量,i应该不大于j,否则就要退出循环,成功运行程序,并打印正确的载入的权重。

心得总结:在优化程序时,debug不能直观的看到所有数据,因此应该及时打印网络参数及shape进行分析,更直观。

你可能感兴趣的:(pytorch,深度学习,神经网络)