caffe模型转pytorch

pytorch/libtorch qq群: 1041467052

本文介绍的是直接读取caffe权重,并根据caffe网络一步一步的搭同样的pytorch网络。本文以分割网络segnet为例。
首先给出参考链接:
https://blog.csdn.net/DumpDoctorWang/article/details/88716962
绝大部分就是参考这位博主的。
首先是需要配环境,我这配好了segnet caffe的训练环境,还有跑推理的脚本,随便找的改一改确保可以跑就可以,当然配环境和跑前向脚本我也花费了不少时间。下面给出跑推理的脚本。
还有就是一定用pycharm,方便打断点调试。用pycharm还会报找不到cuda,然后点run -> Edit Configurations,在Environment variables添加 (Name)LD_LIBRARY_PATH (Value)/usr/local/cuda/lib64;/home/yhl/software_install/opencv3.2/lib

#-*- coding:utf-8 -*-
import sys,os

caffe_root='/data_1/Yang/project/caffe-segnet-2020'
sys.path.insert(0,os.path.join(caffe_root,'python'))

sys.path.insert(0,"/home/yhl/software_install/opencv3.2/lib")

import cv2
import caffe
import numpy as np
import matplotlib.pyplot as plt
import json
import argparse

model_def='/data_1/Yang/project/caffe-segnet-2020/myfile/segnet.prototxt'
model_weights='/data_1/Yang/project/caffe-segnet-2020/myfile/segnet.caffemodel'
image_file='/data_2/2019biaozhushuju/20190716_traindata/00.txt'


size_h=128
size_w=512

##order:R->G->B
color_segmentation =np.asarray(
[
        0,0,0,          ##nothing
        255,236,139,      ##0
        255,235,205,      ##1
        255,228,225,      ##2
        255,225,255,      ##3
        255,193,37,       ##4
        255,174,185,      ##5
        255,140,0,        ##6
        255,131,250,      ##7
        255,105,180,      ##8
        169,169,169,      ##9
        162,205,90,       ##A
        154,192,205,      ##B
        154,50,205,       ##C
        144,238,144,      ##D
        142,142,56,       ##E
        142,56,142,       ##F
        139,90,43,        ##G
        139,62,47,        ##H
        135,206,235,      ##J
        131,139,139,      ##K
        69,139,0,         ##L
        65,105,225,       ##M
        64,224,208,       ##N
        0,238,118,        ##P
        148,0,211,        ##Q
        0,255,255,        ##R
        0,238,238,        ##S
        110,110,110,      ##T
        108,166,205,      ##U
        139,26,26,        ##V
        176,48,96,        ##W
        154,205,50,       ##X/usr/local/cuda/lib64;/home/yhl/software_install/opencv3.2/lib
        192,255,62,       ##Y
        238,48,167,       ##Z
],dtype=np.uint8)

class Caffe_segnet_Segmentation:
    def __init__(self,gpu_id,model_def,model_weights,size_h,size_w):        
        caffe.set_mode_gpu()
        self.size_w=size_w
        self.size_h=size_h
        self.net=caffe.Net(model_def,model_weights,caffe.TEST)
        self.net.blobs['data'].reshape(1,3,size_h,size_w)                        

        # input preprocessing: 'data' is the name of the input blob == net.inputs[0]
        # self.transformer=caffe.io.Transformer({'data':self.net.blobs['data'].data.shape})
        self.transformer=caffe.io.Transformer({'data':self.net.blobs[self.net.inputs[0]].data.shape})
        

        self.transformer.set_transpose('data',(2,0,1))  ##set the input channel order for e.g. RGB to BGR conversion
        
        ##input_blob=input*scale.While Python represents images in [0, 1], certain Caffe models
        # like CaffeNet and AlexNet represent images in [0, 255] so the raw_scale
        # of these models must be 255.
        # self.transformer.set_raw_scale('data',255)    

        # Set the mean to subtract for centering the data.  
        # self.transformer.set_mean('data',np.array([123.68, 116.779, 103.939]))
        
        # Set the scale of preprocessed inputs s.t. the blob = blob * scale.
        # N.B. input_scale is done AFTER mean subtraction and other preprocessing
        # while raw_scale is done BEFORE.
        # self.transformer.set_input_scale('data',0.0078125)
        
        #Set the input channel order for e.g. RGB to BGR conversion
        # as needed for the reference ImageNet model.
        # N.B. this assumes the channels are the first dimension AFTER transpose.
        self.transformer.set_channel_swap('data',(2,1,0))
            

    def prdict(self,imagename,nclasses=34):
        # imagename = "/data_1/Yang/project/2020/chejian/test_data/model_test/seg_chejiahao/0113_E3752H_LSGDC82CX3S211458.jpeg"
        image=caffe.io.load_image(imagename.strip()) #type:np.float32,size:(HxWx3) or (HxWx1)
        
        ##preprocess:
        #        - convert to single
        #- resize to input dimensions (preserving number of channels)
        #- transpose dimensions to K x H x W
        # - reorder channels (for instance color to BGR)
        # - scale raw input (e.g. from [0, 1] to [0, 255] for ImageNet models)
        # - subtract mean
        # - scale feature
        #data:(HxWxK) ndarray
        #returns:caffe_in:(KxHxW) ndarray for input to a Net

        # [3,128,512]
        transformed_image=self.transformer.preprocess('data',image)
        ##这里发现上面预处理代码不能用,会把图片像素变成0-1之间
        transformed_image_1 = cv2.imread(imagename.strip())
        transformed_image_1 = np.float32(transformed_image_1)
        transformed_image_1 = cv2.resize(transformed_image_1,(512,128)) #[128,512,3]
        transformed_image_1 = transformed_image_1.transpose((2,0,1))
        # (3,128,512)
        transformed_image = transformed_image_1
        # cv2.imshow("11",transformed_image_1)
        # cv2.waitKey()


        self.net.blobs['data'].data[...]=transformed_image

        # (1,34,128,512)
        output=self.net.forward()


       #(34,128,512)
        output_prob=output[self.net.outputs[0]][0] 
        # print type(output_prob)  ##np.ndarray
        # print output_prob.shape  ##(28,473,473)

        merge_gray = None        
        feature_maps = None
        #(128,512,34)
        output_prob=output_prob.transpose((1,2,0))
       #(128,512)
        merge_gray=np.argmax(output_prob[:,:,...],axis=2)

        # merge_gray = np.argmax(output_prob, axis=2)

        merge_gray=merge_gray.astype(np.uint8)
        tmp = merge_gray.astype(np.float32) * 25
        cv2.imshow("tmp", tmp)
        cv2.waitKey(0)
        merge_color=np.zeros((self.size_h,self.size_w,3),dtype=np.uint8)
        #show img
        for i in range(nclasses):
            print (str(i), ': ', color_segmentation[i])            
            merge_color[np.where(merge_gray == i)[0], np.where(merge_gray == i)[1]] = (color_segmentation[i*3], color_segmentation[i*3+1], color_segmentation[i*3+2])        
        return merge_color  

def parse_args():
    '''parse args'''
    parser = argparse.ArgumentParser()
    parser.add_argument('--gpu_id', type=int, default=0, help='gpu id')
    parser.add_argument('--model_def',default=model_def)    
    parser.add_argument('--model_weights',default=model_weights)
    parser.add_argument('--size_w',default=size_w)
    parser.add_argument('--size_h',default=size_h)    
    parser.add_argument('--image_file',default=image_file)
    return parser.parse_args()

if __name__=='__main__':
    args=parse_args()
    prediction=Caffe_segnet_Segmentation(args.gpu_id,args.model_def,args.model_weights,args.size_h,args.size_w)
    
    if os.path.isdir(args.image_file):
        for image_name in os.listdir(args.image_file):
            image_name=os.path.join(args.image_file,image_name)
            colormat=prediction.prdict(image_name)
            img=cv2.imread(image_name)
            cv2.imshow('orgimg',img)
            cv2.imshow('colormat',colormat)
            cv2.waitKey()
    elif image_file.endswith('.txt'):
        with open(image_file,'r') as f:
            image_names=f.readlines()
        for image_name in image_names:
            image_name=image_name.split(' ')[0]
            img=cv2.imread(image_name.strip())
            colormat=prediction.prdict(image_name)
            # cv2.imwrite("/data_1/Yang/project/caffe-segnet-2020/myfile/color.jpg",colormat)

            cv2.imshow('orgimg',img)
            cv2.imshow("colormat",colormat)
            cv2.waitKey()
    else:
        colormat=prediction.prdict(args.image_file)
        img=cv2.imread(args.image_file)
        cv2.imshow('orgimg',img)
        cv2.imshow('colormat',colormat)
        cv2.waitKey()

这个脚本可以看到分割的效果图。下面来了解一下pycaffe的一些函数操作效果:

output=self.net.forward()
pool2 = self.net.blobs['pool2'].data[0]

这里,net.blobs['top name'],输入top name可以得到该层的输出,是ndarray类型的。如下图:

同时:

np.save('pool2.caffe.npy', pool2)

可以把ndarray类型保存在本地,后面可以和pytorch的结果做对比。

 for layer_name, blob in self.net.blobs.iteritems():
            print layer_name + '\t' + str(blob.data.shape)

可以打印出每层的feature map 名字和shape

data	(1, 3, 128, 512)
conv1_1	(1, 64, 128, 512)
conv1_2	(1, 64, 128, 512)
pool1	(1, 64, 64, 256)
pool1_mask	(1, 64, 64, 256)
conv2_1	(1, 64, 64, 256)
conv2_2	(1, 64, 64, 256)
pool2	(1, 64, 32, 128)
pool2_mask	(1, 64, 32, 128)
conv3_1	(1, 64, 32, 128)
conv3_2	(1, 64, 32, 128)
conv3_3	(1, 64, 32, 128)
pool3	(1, 64, 16, 64)
pool3_mask	(1, 64, 16, 64)
conv4_1	(1, 64, 16, 64)
conv4_2	(1, 64, 16, 64)
conv4_3	(1, 64, 16, 64)
pool4	(1, 64, 8, 32)
pool4_mask	(1, 64, 8, 32)
pool4_D	(1, 64, 16, 64)
conv4_3_D	(1, 64, 16, 64)
conv4_2_D	(1, 64, 16, 64)
conv4_1_D	(1, 64, 16, 64)
pool3_D	(1, 64, 32, 128)
conv3_3_D	(1, 64, 32, 128)
conv3_2_D	(1, 64, 32, 128)
conv3_1_D	(1, 64, 32, 128)
pool2_D	(1, 64, 64, 256)
conv2_2_D	(1, 64, 64, 256)
conv2_1_D	(1, 64, 64, 256)
pool1_D	(1, 64, 128, 512)
conv1_2_D	(1, 64, 128, 512)

权重与feature,得到的都是ndarray

 # [1,64,128,512]
feature_a = self.net.blobs['conv1_1'].data
# [64,3,3,3]
weights_a = self.net.params['conv1_1'][0].data
# [64,]
weights_b = self.net.params['conv1_1'][1].data

恩!介绍完了基本的pycaffe的函数操作,然后我们开始提取caffe权重,该脚本是基于上面的跑推理的脚本,把每层的名字和形状保存txt,同时整一个字典,层名字是key,权重是val。最后把字典保存在本地.pkl文件。

tiqu.py

#-*- coding:utf-8 -*-
import sys,os
caffe_root='/data_1/Yang/project/caffe-segnet-2020'
sys.path.insert(0,os.path.join(caffe_root,'python'))

sys.path.insert(0,"/home/yhl/software_install/opencv3.2/lib")
import cv2
import caffe
import numpy as np
import matplotlib.pyplot as plt
import json
import argparse
import pickle as pkl


model_def='/data_1/Yang/project/caffe-segnet-2020/myfile/segnet.prototxt'
model_weights='/data_1/Yang/project/caffe-segnet-2020/myfile/segnet.caffemodel'
image_file='/data_1/Yang/project/caffe-segnet-2020/myfile/list.txt'

size_h=128
size_w=512

##order:R->G->B
color_segmentation =np.asarray(
[
        0,0,0,          ##nothing
        255,236,139,      ##0
        255,235,205,      ##1
        255,228,225,      ##2
        255,225,255,      ##3
        255,193,37,       ##4
        255,174,185,      ##5
        255,140,0,        ##6
        255,131,250,      ##7
        255,105,180,      ##8
        169,169,169,      ##9
        162,205,90,       ##A
        154,192,205,      ##B
        154,50,205,       ##C
        144,238,144,      ##D
        142,142,56,       ##E
        142,56,142,       ##F
        139,90,43,        ##G
        139,62,47,        ##H
        135,206,235,      ##J
        131,139,139,      ##K
        69,139,0,         ##L
        65,105,225,       ##M
        64,224,208,       ##N
        0,238,118,        ##P
        148,0,211,        ##Q
        0,255,255,        ##R
        0,238,238,        ##S
        110,110,110,      ##T
        108,166,205,      ##U
        139,26,26,        ##V
        176,48,96,        ##W
        154,205,50,       ##X
        192,255,62,       ##Y
        238,48,167,       ##Z
],dtype=np.uint8)

class Caffe_segnet_Segmentation:
    def __init__(self,gpu_id,model_def,model_weights,size_h,size_w):        
        caffe.set_mode_gpu()
        self.size_w=size_w
        self.size_h=size_h
        self.net=caffe.Net(model_def,model_weights,caffe.TEST)
        self.net.blobs['data'].reshape(1,3,size_h,size_w)                        

        # input preprocessing: 'data' is the name of the input blob == net.inputs[0]
        # self.transformer=caffe.io.Transformer({'data':self.net.blobs['data'].data.shape})
        self.transformer=caffe.io.Transformer({'data':self.net.blobs[self.net.inputs[0]].data.shape})
        

        self.transformer.set_transpose('data',(2,0,1))  ##set the input channel order for e.g. RGB to BGR conversion
        
        ##input_blob=input*scale.While Python represents images in [0, 1], certain Caffe models
        # like CaffeNet and AlexNet represent images in [0, 255] so the raw_scale
        # of these models must be 255.
        # self.transformer.set_raw_scale('data',255)    

        # Set the mean to subtract for centering the data.  
        # self.transformer.set_mean('data',np.array([123.68, 116.779, 103.939]))
        
        # Set the scale of preprocessed inputs s.t. the blob = blob * scale.
        # N.B. input_scale is done AFTER mean subtraction and other preprocessing
        # while raw_scale is done BEFORE.
        # self.transformer.set_input_scale('data',0.0078125)
        
        #Set the input channel order for e.g. RGB to BGR conversion
        # as needed for the reference ImageNet model.
        # N.B. this assumes the channels are the first dimension AFTER transpose.
        self.transformer.set_channel_swap('data',(2,1,0))
            

    def prdict(self,imagename,nclasses=34):
        image=caffe.io.load_image(imagename.strip()) #type:np.float32,size:(HxWx3) or (HxWx1)
        
        ##preprocess:
        #        - convert to single
        #- resize to input dimensions (preserving number of channels)
        #- transpose dimensions to K x H x W
        # - reorder channels (for instance color to BGR)
        # - scale raw input (e.g. from [0, 1] to [0, 255] for ImageNet models)
        # - subtract mean
        # - scale feature
        #data:(HxWxK) ndarray
        #returns:caffe_in:(KxHxW) ndarray for input to a Net

        # [3,128,512]
        transformed_image=self.transformer.preprocess('data',image)

        transformed_image_1 = cv2.imread(imagename.strip())
        transformed_image_1 = cv2.resize(transformed_image_1,(512,128)) #[128,512,3]
        transformed_image_1 = transformed_image_1.transpose((2,0,1))

        transformed_image = transformed_image_1
        # cv2.imshow("11",transformed_image_1)
        # cv2.waitKey()

        self.net.blobs['data'].data[...]=transformed_image



        for layer_name, blob in self.net.blobs.iteritems():
            print layer_name + '\t' + str(blob.data.shape)


        ############################################################################
        ############################################################################
        name_weights = {}
        # 保存每层的参数信息
        keys = open('keys.txt', 'w')
        keys.write('generated by SfSNet-Caffe/convert_to_pkl.py\n\n')
        # 遍历每一网络层
        for param_name in self.net.params.keys():
            name_weights[param_name] = {}
            # 得到此层的参数
            layer_params = self.net.params[param_name]
            if len(layer_params) == 1:
                # 如果参数只有一个,则说明是反卷积层,
                # SfSNet整个模型里就只有反卷积层只有一组weight参数
                weight = layer_params[0].data
                name_weights[param_name]['weight'] = weight

                print('%s:\n\t%s (weight)' % (param_name, weight.shape))
                keys.write('%s:\n\t%s (weight)\n' % (param_name, weight.shape))
            elif len(layer_params) == 2:
                # 如果参数有两个,则说明是卷积层或者全连接层。
                # 卷积层或者全连接层都有两组参数:weight和bias
                # 权重参数
                weight = layer_params[0].data
                name_weights[param_name]['weight'] = weight
                # 偏置参数
                bias = layer_params[1].data
                name_weights[param_name]['bias'] = bias

                print('%s:\n\t%s (weight)' % (param_name, weight.shape))
                print('\t%s (bias)' % str(bias.shape))
                keys.write('%s:\n\t%s (weight)\n' % (param_name, weight.shape))
                keys.write('\t%s (bias)\n' % str(bias.shape))
            elif len(layer_params) == 3:
                # 如果有三个,则说明是BatchNorm层。
                # BN层共有三个参数,分别是:running_mean、running_var和一个缩放参数。
                running_mean = layer_params[0].data  # running_mean
                name_weights[param_name]['running_mean'] = running_mean / layer_params[2].data
                running_var = layer_params[1].data  # running_var
                name_weights[param_name]['running_var'] = running_var / layer_params[2].data

                print('%s:\n\t%s (running_var)' % (param_name, running_var.shape),)
                print('\t%s (running_mean)' % str(running_mean.shape))
                keys.write('%s:\n\t%s (running_var)\n' % (param_name, running_var.shape))
                keys.write('\t%s (running_mean)\n' % str(running_mean.shape))
            else:
                # 如果报错,大家要检查自己模型哈
                raise RuntimeError("还有参数个数超过3个的层,别漏了兄dei!!!\n")
        keys.close()
        # 保存name_weights
        with open('weights.pkl', 'wb') as f:
            pkl.dump(name_weights, f, protocol=2)

        ############################################################################
        ############################################################################

        # print(type(output))
        # while True:
        #     pass

        ##returns:{blob_name:blob_ndarray} dict
        output=self.net.forward()
        # print(type(output))
        # while True:
        #     pass

        # print self.net.outputs[0]  ##conv9_interp
        output_prob=output[self.net.outputs[0]][0] 
        # print type(output_prob)  ##np.ndarray
        # print output_prob.shape  ##(28,473,473)

        merge_gray = None        
        feature_maps = None
        output_prob=output_prob.transpose((1,2,0))
        aaaaa = output_prob[:, :, ...]

        merge_gray=np.argmax(output_prob[:,:,...],axis=2)

        # merge_gray = np.argmax(output_prob, axis=2)

        merge_gray=merge_gray.astype(np.uint8)
        tmp = merge_gray.astype(np.float32) * 25
        cv2.imshow("tmp", tmp)
        cv2.waitKey(0)
        merge_color=np.zeros((self.size_h,self.size_w,3),dtype=np.uint8)
        #show img
        for i in range(nclasses):
            print (str(i), ': ', color_segmentation[i])            
            merge_color[np.where(merge_gray == i)[0], np.where(merge_gray == i)[1]] = (color_segmentation[i*3], color_segmentation[i*3+1], color_segmentation[i*3+2])        
        return merge_color  

def parse_args():
    '''parse args'''
    parser = argparse.ArgumentParser()
    parser.add_argument('--gpu_id', type=int, default=0, help='gpu id')
    parser.add_argument('--model_def',default=model_def)    
    parser.add_argument('--model_weights',default=model_weights)
    parser.add_argument('--size_w',default=size_w)
    parser.add_argument('--size_h',default=size_h)    
    parser.add_argument('--image_file',default=image_file)
    return parser.parse_args()

if __name__=='__main__':
    args=parse_args()
    prediction=Caffe_segnet_Segmentation(args.gpu_id,args.model_def,args.model_weights,args.size_h,args.size_w)
    
    if os.path.isdir(args.image_file):
        for image_name in os.listdir(args.image_file):
            image_name=os.path.join(args.image_file,image_name)
            colormat=prediction.prdict(image_name)
            img=cv2.imread(image_name)
            cv2.imshow('orgimg',img)
            cv2.imshow('colormat',colormat)
            cv2.waitKey()
    elif image_file.endswith('.txt'):
        with open(image_file,'r') as f:
            image_names=f.readlines()
        for image_name in image_names:
            image_name=image_name.split(' ')[0]
            img=cv2.imread(image_name)
            colormat=prediction.prdict(image_name)
            cv2.imwrite("/data_1/Yang/project/caffe-segnet-2020/myfile/color.jpg",colormat)

            # cv2.imshow('orgimg',img)
            # cv2.imshow("colormat",colormat)
            # cv2.waitKey()
    else:
        colormat=prediction.prdict(args.image_file)
        img=cv2.imread(args.image_file)
        cv2.imshow('orgimg',img)
        cv2.imshow('colormat',colormat)
        cv2.waitKey()

如图,会得到keys.txt,weights.pkl两个文件

至此,caffe层面的转换就完成了,后面需要把提取的权重导入pytorch。

pytorch加载caffe权重

首先需要仿照caffe的prototxt搭同样的网络。比如第一层是卷积和bn和relu。就先搭个只有卷积的

# coding=utf-8
from __future__ import absolute_import, division, print_function
import torch
import torchvision
import pickle as pkl
from torch import nn
import torch.nn.functional as F

import pickle as pkl
import cv2
import numpy as np



class segnet_my(nn.Module):  # SfSNet = PS-Net in SfSNet_deploy.prototxt
    def __init__(self):
        super(segnet_my, self).__init__()
        self.conv1_1 = nn.Conv2d(3, 64, 3, 1, 1)
        self.bn1_1 = nn.BatchNorm2d(64)
    

     def forward(self,inputs):
        #x = self.conv1_1(inputs)
        x = F.relu(self.bn1_1(self.conv1_1(inputs)))
        return x

if __name__ == '__main__':
    net = segnet_my()
    # net.eval()

    index = 0
    print("*" * 50)
    for name, param in list(net.named_parameters()):
        print(str(index) + ':', name, param.size())
        index += 1
    print("*" * 50)

    for k, v in net.state_dict().items():
        print(k)
        print(v.shape)
        # print(k,v)
    print("@" * 50)

上面两种都是打印出pytorch权重名和形状,只是下面这种可以更全,上面不会打印bn层的running_mean,running_var
0: conv1_1.weight (64, 3, 3, 3)
1: conv1_1.bias (64,)
2: bn1_1.weight (64,)
3: bn1_1.bias (64,)
########################################################################################
conv1_1.weight
(64, 3, 3, 3)
conv1_1.bias
(64,)
bn1_1.weight
(64,)
bn1_1.bias
(64,)
bn1_1.running_mean
(64,)
bn1_1.running_var
(64,)
bn1_1.num_batches_tracked
()

这个只是打印出pytorch权重形状,要和caffe的比较看是不是一样的。
下面是从pkl加载权重,并且检查权重是否一致

if __name__ == '__main__':
    net = segnet_my()
    # net.eval()

    index = 0
    print("*" * 50)
    for name, param in list(net.named_parameters()):
        print(str(index) + ':', name, param.size())
        index += 1
    print("*" * 50)

    for k, v in net.state_dict().items():
        print(k)
        print(v.shape)
        # print(k,v)
    print("@" * 50)



    from torch import from_numpy

    with open('/data_1/Yang/project/caffe-segnet-2020/myfile/weights.pkl', 'rb') as wp:
        name_weights = pkl.load(wp)
        state_dict = {}

        state_dict['conv1_1.weight'] = from_numpy(name_weights['conv1_1']['weight'])
        state_dict['conv1_1.bias'] = from_numpy(name_weights['conv1_1']['bias'])
        state_dict['bn1_1.running_var'] = from_numpy(name_weights['conv1_1_bn_standard']['running_var'])
        state_dict['bn1_1.running_mean'] = from_numpy(name_weights['conv1_1_bn_standard']['running_mean'])
        state_dict['bn1_1.weight'] = from_numpy(name_weights['conv1_1_scale']['weight'])
        state_dict['bn1_1.bias'] = from_numpy(name_weights['conv1_1_scale']['bias'])

 ##########检测pkl读取的权重和加载到pytorch net的权重是否一致#####################################################################################
        # for k, v in net.state_dict().items():
        #     print(k)
        #     print(v.shape)
        #     print(k,v)
        #
        # # params = dict(net.named_parameters())
        # # print("*"*100)
        # print(params['bn1.running_var'].detach().numpy())
        #
        # f = open('/data_1/Yang/project/caffe-segnet-2020/myfile/weights.pkl', 'rb')
        # name_weights_1 = pkl.load(f)
        # f.close()
        # print("#" * 100)
        # print(name_weights_1['conv1_1_bn_standard']['running_var'])
        #
        # print("*" * 100)
        ###############################################################################################

最关键的是caffe和pytorch经过一层的feature map的结果是否一致。首先是确保送进网络的图片预处理一样,下面给出完整代码

# coding=utf-8
from __future__ import absolute_import, division, print_function
import torch
import torchvision
import pickle as pkl
from torch import nn
import torch.nn.functional as F

import pickle as pkl
import cv2
import numpy as np



class segnet_my(nn.Module):  # SfSNet = PS-Net in SfSNet_deploy.prototxt
    def __init__(self):
        super(segnet_my, self).__init__()

       #################################################################################
        self.conv1_1 = nn.Conv2d(3, 64, 3, 1, 1)
        self.bn1_1 = nn.BatchNorm2d(64) ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv1_2 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn1_2 = nn.BatchNorm2d(64)
        self.pool1 = nn.MaxPool2d(kernel_size=2,stride=2)
        #################################################################################

        #################################################################################
        self.conv2_1 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn2_1 = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv2_2 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn2_2 = nn.BatchNorm2d(64)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        #################################################################################

        #################################################################################
        self.conv3_1 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn3_1 = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv3_2 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn3_2 = nn.BatchNorm2d(64)
        self.conv3_3 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn3_3 = nn.BatchNorm2d(64)
        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)
        #################################################################################

        #################################################################################
        self.conv4_1 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn4_1 = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv4_2 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn4_2 = nn.BatchNorm2d(64)
        self.conv4_3 = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn4_3 = nn.BatchNorm2d(64)
        self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)
        #################################################################################

        self.upsample4 = nn.Upsample(scale_factor=2, mode='nearest')

        #################################################################################
        self.conv4_3_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn4_3_D = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv4_2_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn4_2_D = nn.BatchNorm2d(64)
        self.conv4_1_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn4_1_D = nn.BatchNorm2d(64)
        #################################################################################

        ##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
        #################################################################################
        self.conv3_3_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn3_3_D = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv3_2_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn3_2_D = nn.BatchNorm2d(64)
        self.conv3_1_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn3_1_D = nn.BatchNorm2d(64)
        #################################################################################

        ##1111111
        #################################################################################
        self.conv2_2_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn2_2_D = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        self.conv2_1_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn2_1_D = nn.BatchNorm2d(64)
        #################################################################################

        ##2222
        #################################################################################
        self.conv1_2_D = nn.Conv2d(64, 64, 3, 1, 1)
        self.bn1_2_D = nn.BatchNorm2d(64)  ##self.bn1 = nn.BatchNorm2d(64,affine=False)
        #################################################################################

        ##last
        #################################################################################
        self.conv1_1_D = nn.Conv2d(64, 34, 3, 1, 1)
        #################################################################################

    def forward(self,inputs):

        # x = self.conv1_1(inputs)
        # x = self.bn1(x)

        x = F.relu(self.bn1_1(self.conv1_1(inputs)))
        x = F.relu(self.bn1_2(self.conv1_2(x)))
        pool1, pool1_mask = F.max_pool2d(x, kernel_size=2, stride=2, return_indices=True)


        x = F.relu(self.bn2_1(self.conv2_1(pool1)))
        x = F.relu(self.bn2_2(self.conv2_2(x)))
        pool2, pool2_mask = F.max_pool2d(x, kernel_size=2, stride=2, return_indices=True)


        x = F.relu(self.bn3_1(self.conv3_1(pool2)))
        x = F.relu(self.bn3_2(self.conv3_2(x)))
        x = F.relu(self.bn3_3(self.conv3_3(x)))
        pool3, pool3_mask = F.max_pool2d(x, kernel_size=2, stride=2, return_indices=True)

        x = F.relu(self.bn4_1(self.conv4_1(pool3)))
        x = F.relu(self.bn4_2(self.conv4_2(x)))
        x = F.relu(self.bn4_3(self.conv4_3(x)))
        pool4, pool4_mask = F.max_pool2d(x, kernel_size=2, stride=2, return_indices=True)

        pool4_D = F.max_unpool2d(pool4, pool4_mask, kernel_size=2, stride=2)

        x = F.relu(self.bn4_3_D(self.conv4_3_D(pool4_D)))
        x = F.relu(self.bn4_2_D(self.conv4_2_D(x)))
        x = F.relu(self.bn4_1_D(self.conv4_1_D(x)))
        pool3_D = F.max_unpool2d(x, pool3_mask, kernel_size=2, stride=2)

        x = F.relu(self.bn3_3_D(self.conv3_3_D(pool3_D)))
        x = F.relu(self.bn3_2_D(self.conv3_2_D(x)))
        x = F.relu(self.bn3_1_D(self.conv3_1_D(x)))
        pool2_D = F.max_unpool2d(x, pool2_mask, kernel_size=2, stride=2)

        x = F.relu(self.bn2_2_D(self.conv2_2_D(pool2_D)))
        x = F.relu(self.bn2_1_D(self.conv2_1_D(x)))
        pool1_D = F.max_unpool2d(x, pool1_mask, kernel_size=2, stride=2)

        x = F.relu(self.bn1_2_D(self.conv1_2_D(pool1_D)))

        x = self.conv1_1_D(x)

        return x




if __name__ == '__main__':
    net = segnet_my()
    # net.eval()

    index = 0
    print("*" * 50)
    for name, param in list(net.named_parameters()):
        print(str(index) + ':', name, param.size())
        index += 1
    print("*" * 50)

    for k, v in net.state_dict().items():
        print(k)
        print(v.shape)
        # print(k,v)
    print("@" * 50)



    from torch import from_numpy

    with open('/data_1/Yang/project/caffe-segnet-2020/myfile/weights.pkl', 'rb') as wp:
        name_weights = pkl.load(wp)
        state_dict = {}

        state_dict['conv1_1.weight'] = from_numpy(name_weights['conv1_1']['weight'])
        state_dict['conv1_1.bias'] = from_numpy(name_weights['conv1_1']['bias'])
        state_dict['bn1_1.running_var'] = from_numpy(name_weights['conv1_1_bn_standard']['running_var'])
        state_dict['bn1_1.running_mean'] = from_numpy(name_weights['conv1_1_bn_standard']['running_mean'])
        state_dict['bn1_1.weight'] = from_numpy(name_weights['conv1_1_scale']['weight'])
        state_dict['bn1_1.bias'] = from_numpy(name_weights['conv1_1_scale']['bias'])
        state_dict['conv1_2.weight'] = from_numpy(name_weights['conv1_2']['weight'])
        state_dict['conv1_2.bias'] = from_numpy(name_weights['conv1_2']['bias'])
        state_dict['bn1_2.running_var'] = from_numpy(name_weights['conv1_2_bn_standard']['running_var'])
        state_dict['bn1_2.running_mean'] = from_numpy(name_weights['conv1_2_bn_standard']['running_mean'])
        state_dict['bn1_2.weight'] = from_numpy(name_weights['conv1_2_scale']['weight'])
        state_dict['bn1_2.bias'] = from_numpy(name_weights['conv1_2_scale']['bias'])


        state_dict['conv2_1.weight'] = from_numpy(name_weights['conv2_1']['weight'])
        state_dict['conv2_1.bias'] = from_numpy(name_weights['conv2_1']['bias'])
        state_dict['bn2_1.running_var'] = from_numpy(name_weights['conv2_1_bn_standard']['running_var'])
        state_dict['bn2_1.running_mean'] = from_numpy(name_weights['conv2_1_bn_standard']['running_mean'])
        state_dict['bn2_1.weight'] = from_numpy(name_weights['conv2_1_scale']['weight'])
        state_dict['bn2_1.bias'] = from_numpy(name_weights['conv2_1_scale']['bias'])
        state_dict['conv2_2.weight'] = from_numpy(name_weights['conv2_2']['weight'])
        state_dict['conv2_2.bias'] = from_numpy(name_weights['conv2_2']['bias'])
        state_dict['bn2_2.running_var'] = from_numpy(name_weights['conv2_2_bn_standard']['running_var'])
        state_dict['bn2_2.running_mean'] = from_numpy(name_weights['conv2_2_bn_standard']['running_mean'])
        state_dict['bn2_2.weight'] = from_numpy(name_weights['conv2_2_scale']['weight'])
        state_dict['bn2_2.bias'] = from_numpy(name_weights['conv2_2_scale']['bias'])


        state_dict['conv3_1.weight'] = from_numpy(name_weights['conv3_1']['weight'])
        state_dict['conv3_1.bias'] = from_numpy(name_weights['conv3_1']['bias'])
        state_dict['bn3_1.running_var'] = from_numpy(name_weights['conv3_1_bn_standard']['running_var'])
        state_dict['bn3_1.running_mean'] = from_numpy(name_weights['conv3_1_bn_standard']['running_mean'])
        state_dict['bn3_1.weight'] = from_numpy(name_weights['conv3_1_scale']['weight'])
        state_dict['bn3_1.bias'] = from_numpy(name_weights['conv3_1_scale']['bias'])
        #
        state_dict['conv3_2.weight'] = from_numpy(name_weights['conv3_2']['weight'])
        state_dict['conv3_2.bias'] = from_numpy(name_weights['conv3_2']['bias'])
        state_dict['bn3_2.running_var'] = from_numpy(name_weights['conv3_2_bn_standard']['running_var'])
        state_dict['bn3_2.running_mean'] = from_numpy(name_weights['conv3_2_bn_standard']['running_mean'])
        state_dict['bn3_2.weight'] = from_numpy(name_weights['conv3_2_scale']['weight'])
        state_dict['bn3_2.bias'] = from_numpy(name_weights['conv3_2_scale']['bias'])
        #
        state_dict['conv3_3.weight'] = from_numpy(name_weights['conv3_3']['weight'])
        state_dict['conv3_3.bias'] = from_numpy(name_weights['conv3_3']['bias'])
        state_dict['bn3_3.running_var'] = from_numpy(name_weights['conv3_3_bn_standard']['running_var'])
        state_dict['bn3_3.running_mean'] = from_numpy(name_weights['conv3_3_bn_standard']['running_mean'])
        state_dict['bn3_3.weight'] = from_numpy(name_weights['conv3_3_scale']['weight'])
        state_dict['bn3_3.bias'] = from_numpy(name_weights['conv3_3_scale']['bias'])

        ###layer 4############################################################
        state_dict['conv4_1.weight'] = from_numpy(name_weights['conv4_1']['weight'])
        state_dict['conv4_1.bias'] = from_numpy(name_weights['conv4_1']['bias'])
        state_dict['bn4_1.running_var'] = from_numpy(name_weights['conv4_1_bn_standard']['running_var'])
        state_dict['bn4_1.running_mean'] = from_numpy(name_weights['conv4_1_bn_standard']['running_mean'])
        state_dict['bn4_1.weight'] = from_numpy(name_weights['conv4_1_scale']['weight'])
        state_dict['bn4_1.bias'] = from_numpy(name_weights['conv4_1_scale']['bias'])
        #
        state_dict['conv4_2.weight'] = from_numpy(name_weights['conv4_2']['weight'])
        state_dict['conv4_2.bias'] = from_numpy(name_weights['conv4_2']['bias'])
        state_dict['bn4_2.running_var'] = from_numpy(name_weights['conv4_2_bn_standard']['running_var'])
        state_dict['bn4_2.running_mean'] = from_numpy(name_weights['conv4_2_bn_standard']['running_mean'])
        state_dict['bn4_2.weight'] = from_numpy(name_weights['conv4_2_scale']['weight'])
        state_dict['bn4_2.bias'] = from_numpy(name_weights['conv4_2_scale']['bias'])
        #
        state_dict['conv4_3.weight'] = from_numpy(name_weights['conv4_3']['weight'])
        state_dict['conv4_3.bias'] = from_numpy(name_weights['conv4_3']['bias'])
        state_dict['bn4_3.running_var'] = from_numpy(name_weights['conv4_3_bn_standard']['running_var'])
        state_dict['bn4_3.running_mean'] = from_numpy(name_weights['conv4_3_bn_standard']['running_mean'])
        state_dict['bn4_3.weight'] = from_numpy(name_weights['conv4_3_scale']['weight'])
        state_dict['bn4_3.bias'] = from_numpy(name_weights['conv4_3_scale']['bias'])

        ###layer 4 D ############################################################
        state_dict['conv4_3_D.weight'] = from_numpy(name_weights['conv4_3_D']['weight'])
        state_dict['conv4_3_D.bias'] = from_numpy(name_weights['conv4_3_D']['bias'])
        state_dict['bn4_3_D.running_var'] = from_numpy(name_weights['conv4_3_D_bn_standard']['running_var'])
        state_dict['bn4_3_D.running_mean'] = from_numpy(name_weights['conv4_3_D_bn_standard']['running_mean'])
        state_dict['bn4_3_D.weight'] = from_numpy(name_weights['conv4_3_D_scale']['weight'])
        state_dict['bn4_3_D.bias'] = from_numpy(name_weights['conv4_3_D_scale']['bias'])
        #
        state_dict['conv4_2_D.weight'] = from_numpy(name_weights['conv4_2_D']['weight'])
        state_dict['conv4_2_D.bias'] = from_numpy(name_weights['conv4_2_D']['bias'])
        state_dict['bn4_2_D.running_var'] = from_numpy(name_weights['conv4_2_D_bn_standard']['running_var'])
        state_dict['bn4_2_D.running_mean'] = from_numpy(name_weights['conv4_2_D_bn_standard']['running_mean'])
        state_dict['bn4_2_D.weight'] = from_numpy(name_weights['conv4_2_D_scale']['weight'])
        state_dict['bn4_2_D.bias'] = from_numpy(name_weights['conv4_2_D_scale']['bias'])
        #
        state_dict['conv4_1_D.weight'] = from_numpy(name_weights['conv4_1_D']['weight'])
        state_dict['conv4_1_D.bias'] = from_numpy(name_weights['conv4_1_D']['bias'])
        state_dict['bn4_1_D.running_var'] = from_numpy(name_weights['conv4_1_D_bn_standard']['running_var'])
        state_dict['bn4_1_D.running_mean'] = from_numpy(name_weights['conv4_1_D_bn_standard']['running_mean'])
        state_dict['bn4_1_D.weight'] = from_numpy(name_weights['conv4_1_D_scale']['weight'])
        state_dict['bn4_1_D.bias'] = from_numpy(name_weights['conv4_1_D_scale']['bias'])

        ###layer 3 D ############################################################
        state_dict['conv3_3_D.weight'] = from_numpy(name_weights['conv3_3_D']['weight'])
        state_dict['conv3_3_D.bias'] = from_numpy(name_weights['conv3_3_D']['bias'])
        state_dict['bn3_3_D.running_var'] = from_numpy(name_weights['conv3_3_D_bn_standard']['running_var'])
        state_dict['bn3_3_D.running_mean'] = from_numpy(name_weights['conv3_3_D_bn_standard']['running_mean'])
        state_dict['bn3_3_D.weight'] = from_numpy(name_weights['conv3_3_D_scale']['weight'])
        state_dict['bn3_3_D.bias'] = from_numpy(name_weights['conv3_3_D_scale']['bias'])
        #
        state_dict['conv3_2_D.weight'] = from_numpy(name_weights['conv3_2_D']['weight'])
        state_dict['conv3_2_D.bias'] = from_numpy(name_weights['conv3_2_D']['bias'])
        state_dict['bn3_2_D.running_var'] = from_numpy(name_weights['conv3_2_D_bn_standard']['running_var'])
        state_dict['bn3_2_D.running_mean'] = from_numpy(name_weights['conv3_2_D_bn_standard']['running_mean'])
        state_dict['bn3_2_D.weight'] = from_numpy(name_weights['conv3_2_D_scale']['weight'])
        state_dict['bn3_2_D.bias'] = from_numpy(name_weights['conv3_2_D_scale']['bias'])
        #
        state_dict['conv3_1_D.weight'] = from_numpy(name_weights['conv3_1_D']['weight'])
        state_dict['conv3_1_D.bias'] = from_numpy(name_weights['conv3_1_D']['bias'])
        state_dict['bn3_1_D.running_var'] = from_numpy(name_weights['conv3_1_D_bn_standard']['running_var'])
        state_dict['bn3_1_D.running_mean'] = from_numpy(name_weights['conv3_1_D_bn_standard']['running_mean'])
        state_dict['bn3_1_D.weight'] = from_numpy(name_weights['conv3_1_D_scale']['weight'])
        state_dict['bn3_1_D.bias'] = from_numpy(name_weights['conv3_1_D_scale']['bias'])

        ###layer 2 D ############################################################
        state_dict['conv2_2_D.weight'] = from_numpy(name_weights['conv2_2_D']['weight'])
        state_dict['conv2_2_D.bias'] = from_numpy(name_weights['conv2_2_D']['bias'])
        state_dict['bn2_2_D.running_var'] = from_numpy(name_weights['conv2_2_D_bn_standard']['running_var'])
        state_dict['bn2_2_D.running_mean'] = from_numpy(name_weights['conv2_2_D_bn_standard']['running_mean'])
        state_dict['bn2_2_D.weight'] = from_numpy(name_weights['conv2_2_D_scale']['weight'])
        state_dict['bn2_2_D.bias'] = from_numpy(name_weights['conv2_2_D_scale']['bias'])
        #
        state_dict['conv2_1_D.weight'] = from_numpy(name_weights['conv2_1_D']['weight'])
        state_dict['conv2_1_D.bias'] = from_numpy(name_weights['conv2_1_D']['bias'])
        state_dict['bn2_1_D.running_var'] = from_numpy(name_weights['conv2_1_D_bn_standard']['running_var'])
        state_dict['bn2_1_D.running_mean'] = from_numpy(name_weights['conv2_1_D_bn_standard']['running_mean'])
        state_dict['bn2_1_D.weight'] = from_numpy(name_weights['conv2_1_D_scale']['weight'])
        state_dict['bn2_1_D.bias'] = from_numpy(name_weights['conv2_1_D_scale']['bias'])


        ####layer 1_2
        state_dict['conv1_2_D.weight'] = from_numpy(name_weights['conv1_2_D']['weight'])
        state_dict['conv1_2_D.bias'] = from_numpy(name_weights['conv1_2_D']['bias'])
        state_dict['bn1_2_D.running_var'] = from_numpy(name_weights['conv1_2_D_bn_standard']['running_var'])
        state_dict['bn1_2_D.running_mean'] = from_numpy(name_weights['conv1_2_D_bn_standard']['running_mean'])
        state_dict['bn1_2_D.weight'] = from_numpy(name_weights['conv1_2_D_scale']['weight'])
        state_dict['bn1_2_D.bias'] = from_numpy(name_weights['conv1_2_D_scale']['bias'])

        ##last
        state_dict['conv1_1_D.weight'] = from_numpy(name_weights['conv1_1_D']['weight'])
        state_dict['conv1_1_D.bias'] = from_numpy(name_weights['conv1_1_D']['bias'])


        net.load_state_dict(state_dict)
        net.cuda()
        net.eval()

        torch.save(net.state_dict(), './model.pth')



        ###############################################################################################
        # for k, v in net.state_dict().items():
        #     print(k)
        #     print(v.shape)
        #     print(k,v)
        #
        # # params = dict(net.named_parameters())
        # # print("*"*100)
        # print(params['bn1.running_var'].detach().numpy())
        #
        # f = open('/data_1/Yang/project/caffe-segnet-2020/myfile/weights.pkl', 'rb')
        # name_weights_1 = pkl.load(f)
        # f.close()
        # print("#" * 100)
        # print(name_weights_1['conv1_1_bn_standard']['running_var'])
        #
        # print("*" * 100)
        ###############################################################################################
    #
    #
    #
    #
        imagename = "/data_1/Yang/project/2020/example.jpeg"

        transformed_image_1 = cv2.imread(imagename.strip())
        transformed_image_1 = np.array(transformed_image_1, dtype=np.float32)
        transformed_image_1 = cv2.resize(transformed_image_1, (512, 128))  # [128,512,3]
        transformed_image_1 = transformed_image_1.transpose((2, 0, 1))


        transformed_image = from_numpy(transformed_image_1)

        transformed_image = torch.unsqueeze(transformed_image,0).cuda()

        # np.save('img.pytorch.npy', transformed_image[0].detach().numpy())
        # xx = torch.randn(1, 3, 320, 320)

        output = net(transformed_image)
        aa5 = 0

        # import sys
        # traced_script_module = torch.jit.trace(net, transformed_image)
        # traced_script_module.save("/data_1/Yang/project/caffe-segnet-2020/myfile/pytorch/00000.pt")
        # print("sys.exit(1)")
        # sys.exit(1)

        output_prob = output[0].cpu().detach().numpy()

        # np.save('output_prob.pytorch.npy', output_prob)

        merge_gray = None
        feature_maps = None
        output_prob = output_prob.transpose((1, 2, 0))
        aaaaa = output_prob[:, :, ...]

        merge_gray = np.argmax(output_prob[:, :, ...], axis=2)

        # merge_gray = np.argmax(output_prob, axis=2)

        merge_gray = merge_gray.astype(np.uint8)
        tmp = merge_gray.astype(np.float32) * 25

        img_src = cv2.imread(imagename)
        cv2.imshow("img_src", img_src)
        cv2.imshow("tmp", tmp)
        cv2.waitKey(0)

        # np.save('bn1-relu.pytorch.npy', bb[0].detach().numpy())

如上,output = net(transformed_image)就是输出的feature map可以和caffe的feature map做对比。
写了一个same.py脚本,就是加载npy文件,做对比。下面的脚本只要看aa就可以了,我转完的segnet的最后一层的feature map两者之间的差是10的-7次方。基本没有问题。

# coding=utf-8
import numpy as np
def same(arr1, arr2):
    # type: (np.ndarray, np.ndarray) -> bool
    # 判断shape是否相同
    assert arr1.shape == arr2.shape
    # 对应元素相减求绝对值
    diff = np.abs(arr1 - arr2)

    aa = np.average(diff)
    # 判断是否有任意一个两元素之差大于阈值1e-5
    return aa,(diff > 1e-5).any()


def compare(layer, params, name_weights):
    # type: (str, dict, dict) -> tuple[bool, bool]
    # 判断权重
    w = same(params[layer+'.weight'].detach().numpy(), name_weights[layer]['weight'])
    # 判断偏置
    b = same(params[layer+'.bias'].detach().numpy(), name_weights[layer]['bias'])
    return w, b


if __name__ == '__main__':
    caffe_result = np.load('/data_1/Yang/project/caffe-segnet-2020/myfile/conv1_1_D.caffe.npy')
    torch_result = np.load('/data_1/Yang/project/caffe-segnet-2020/myfile/pytorch/output_prob.pytorch.npy')
    # same函数之前有提到
    print(same(caffe_result, torch_result))

还有一个疑惑是,caffe的网络层有一些是in place操作,比如一般是卷积、bn、relu他们的top都是叫一个名字,导致下面的运算会覆盖上面的结果。比如:

layer {
  bottom: "data"
  top: "conv1_1"  ########################################################
  name: "conv1_1"
  type: "Convolution"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    weight_filler {
      type: "msra"
    }
    bias_filler {
      type: "constant"
    }
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}

layer {
  bottom: "conv1_1"
  top: "conv1_1" ########################################################
  name: "conv1_1_bn_standard"
  type: "BatchNorm"
  batch_norm_param {
    use_global_stats: true
    #moving_average_fraction: 0.9
  }
}

layer {
    bottom: "conv1_1"
    top: "conv1_1" ########################################################
    name: "conv1_1_scale"
    type: "Scale"
    scale_param {
        bias_term: true
    }
}

layer {
  bottom: "conv1_1"
  top: "conv1_1"  ########################################################
  name: "relu1_1"
  type: "ReLU"
}

因为只能通过top看feature的,forward之后只保留了最后一个的feature的结果,即只保留了relu层之后的结果。那么,如果要看conv1_1_bn_standard这一层的输出怎么办?
答案是修改 top: "conv1_1"名字,确保下面的bottom和上面的top一致就可以!不影响权重加载,因为加载只看name加载权重。
至于,可能会遇到caffe有的算子,pytorch没有。比如这里的上采样,弄了很久,然后xiao hu提醒我去找segnet的pytorch实现,果真找到了上采样的函数:
https://github.com/delta-onera/segnet_pytorch

x5p, id5 = F.max_pool2d(x53,kernel_size=2, stride=2,return_indices=True)
x5d = F.max_unpool2d(x5p, id5, kernel_size=2, stride=2)

至于还会有不一样的算子的话,那就需要再研究研究怎么弄了。。。

posted @ 2020-06-11 21:39  无左无右  阅读(563)  评论(0编辑  收藏  举报