解析caffe prototxt(2):合并卷积层与BN层

融合卷积与BN的理论计算:
解析caffe prototxt(2):合并卷积层与BN层_第1张图片

一、修改prototxt基本操作

deploy1='../deploy-pool.prototxt'
model1='../snapshots/pool_iter_5000.caffemodel'
f=open(deploy1,'r')
model = caffe.proto.caffe_pb2.NetParameter()
##model类型:
pb.text_format.Merge(f.read(), model) #把内容读进model
f.close()
layers=model.layer 
print(layers) #显示如下图
##layers类型:
接下

只截取了最后的部分作为示例
解析caffe prototxt(2):合并卷积层与BN层_第2张图片

二、解析的基本操作

第一个卷积层如下图

接上
for i,l in enumerate(layers):
        print(l) #l类型:
        print l.name,'\n' #
        print l.type,'\n' # 
        print l.bottom,'\n' #
        #可视为列表类型,因为bottom可以有多个值
        print l.top,'\n' #
        print l.param,'\n' #
        print l.convolution_param,'\n' #
        print l.convolution_param.num_output,'\n' #
        print l.convolution_param.pad,'\n' #
        print l.convolution_param.kernel_size,'\n' #
        print l.convolution_param.stride,'\n' #
        break

结果如下:
解析caffe prototxt(2):合并卷积层与BN层_第3张图片

三、由于要合并BN层,就需要去掉BN层,并将剩下层bottom、top对应上

以下是完整代码

create-proto.py

#coding=UTF-8
import sys
sys.path.insert(0,'/home/cdli/ECO/caffe_3d/python')
import caffe
import numpy as np
import cv2
import scipy.io as sio
import google.protobuf as pb
import google.protobuf.text_format
import os
caffe.set_device(0)
caffe.set_mode_gpu()

deploy='../deploy-pool-group.prototxt'
model='../parse/after.caffemodel'

f=open(deploy,'r')
model = caffe.proto.caffe_pb2.NetParameter() #
model_new=caffe.proto.caffe_pb2.NetParameter()
pb.text_format.Merge(f.read(), model) #把内容读进model
f.close()
layers=model.layer #理解为list

#写入新prototxt
f=open('deploy-pool-group-no-bn.prototxt','w')
if len(model.name) > 0:
	print 'name:"{}"\n'.format(model.name)
	f.write('name:"{}"\n'.format(model.name))
for input_name in model.input:
	print 'input:"{}"\n'.format(input_name)
	f.write('input:"{}"\n'.format(input_name))
for input_dim in model.input_dim:
	print "input_dim:{}\n".format(input_dim)
	f.write("input_dim:{}\n".format(input_dim))
for i in range(0,len(layers)):
	if i==555:
		break
	if layers[i].type != "BN": #此处仅针对ECO,具体网络具体修改
		if layers[i].type=='ReLU':
			layers[i].bottom[0]=layers[i].bottom[0].split('_bn')[0]
		f.write('layer{\n'+'{}'.format(pb.text_format.MessageToString(layers[i]))+'}\n')
f.close()

merge-weights.py
#coding=UTF-8
import sys
sys.path.insert(0,'/home/cdli/ECO4/caffe_3d/python')
import caffe
import numpy as np
import cv2
import scipy.io as sio
import google.protobuf as pb
import google.protobuf.text_format
import os

caffe.set_device(0)
caffe.set_mode_gpu()

deploy='../deploy-pool-group.prototxt'
deploy_new='deploy-pool-group-no-bn.prototxt'
model='../parse/after.caffemodel'

net=caffe.Net(deploy,model,caffe.TEST)
net_new=caffe.Net(deploy_new,caffe.TEST)
layers_new=net_new.params.keys()
print layers_new
for l in layers_new[:-1]:
	print l
	conv_new=net_new.params[l] #合并后
	weight_new=conv_new[0].data #(64, 3, 7, 7)
	bias_new=conv_new[1].data #(64,)

	conv=net.params[l] #原
	weight=conv[0].data #(64, 3, 7, 7)
	bias=conv[1].data
	if (l=='res3a_2n') or (l=='res3b_2'):
		l_bn='res3b_bn'
	elif (l=='res4a_2') or (l=='res4a_down'):
		l_bn='res4a_bn'
	elif l=='res4b_2':
		l_bn='res4b_bn'
	elif (l=='res5a_2') or (l=='res5a_down'):
		l_bn='res5a_bn'
	elif l=='res5b_2':
		l_bn='res5b_bn'
	else:
		l_bn=l+'_bn'
	bn=net.params[l_bn]
	alpha_=bn[0].data.reshape((-1,)) #(64,)       #BN参数
	beta_=bn[1].data.reshape((-1,))
	mean_=bn[2].data.reshape((-1,))
	var_=bn[3].data.reshape((-1,))
	
	#合并
	for i in range(0,len(conv_new[0].data)):
		weight_new[i]=weight[i,:,:,:]*alpha_[i]/np.sqrt(var_[i])
		bias_new[i]=alpha_[i]*(bias[i]-mean_[i])/np.sqrt(var_[i])+beta_[i]
#全连接层
conv_new=net_new.params['fc8u'] 
conv=net.params['fc8u'] 
conv_new[0].data[:]=conv[0].data[:] #weight
conv_new[1].data[:]=conv[1].data[:] #bias

'''检查用
input1=np.zeros(shape=(224,224,3,8),dtype=np.float64)
input2=np.zeros(shape=(240,320,3),dtype=np.float64)

d = sio.loadmat("../rgb_mean.mat")
image_mean = d['image_mean']  # 224 224 3
lis=[]

for i in range(0,8):
        img=cv2.imread('img/img_000'+str(i+1)+'.jpg')
        img_reshape=img[16:240,60:284,:]-image_mean
        input1[:,:,:,i]=img_reshape
        lis.append(img_reshape)
        if i==0:
                input2=img_reshape
        else:
                input2=np.append(input2,img_reshape,axis=2)
#input1=np.zeros((224,224,3,8))

# 输入数据确定
p=8
input2=input2[...,None]
input1=np.transpose(input1[:,:,:,:],(3,2,1,0)) #8 3 224 224
input2=np.transpose(input2[:,:,:,:],(3,2,1,0)) #1 24 224 224
input_minus=(input1[p-1,:,:,:]-input2[0,3*(p-1):3*p,:,:]).sum()
net.blobs['data'].data[...]=input2
net_new.blobs['data'].data[...]=input2

output1=net.forward()
output2=net_new.forward()

b_name1='conv1_7x7_s2_bn'
b_name2='conv1_7x7_s2_bn'
blob1=net.blobs[b_name1].data
blob2=net_new.blobs[b_name1].data
print blob1.shape
print blob2.shape
print 'minus=',(blob1-blob2).sum()

print 'out1=',output1
print 'out2=',output2
'''
net_new.save('pool-group-no-bn.caffemodel')

你可能感兴趣的:(caffe,深度学习)