在caffe模型实际落地时,局限于硬件的问题,有时候训练好的网络结构需要进行微调,最近碰到NT98528输出不支持的问题,需要临时将1*1 conv改fc,先改prototxt,对应改下类型名称即可:
#caffe 卷积层
layer {
name: "fc_1"
type: "Convolution"
bottom: "pool5"
top: "fc_1"
param {
lr_mult: 1
}
param {
lr_mult: 1
}
convolution_param {
num_output: 3
kernel_size: 1
weight_filler {
type: "msra"
}
bias_filler {
type: "constant"
value: 0
}
}
}
#caffe 全连接层
layer {
name: "fc_1"
type: "InnerProduct"
bottom: "pool5"
top: "fc_1"
param {
lr_mult: 1
}
param {
lr_mult: 1
}
inner_product_param {
num_output: 3
weight_filler {
type: "msra"
}
bias_filler {
type: "constant"
value: 0
}
}
}
1*1 conv和FC相互转化 代码如下:
# -*- coding: utf-8 -*-
#encoding: utf-8
import sys
import cv2
import math
import numpy as np
import os
from PIL import Image
import io
caffe_path = r'../../python'
sys.path.insert(0, caffe_path)
import caffe
params = ['fc_1', 'fc_2']
params_full_conv=params
def convert_full_conv(model_define, model_weight, model_define_fc, model_weight_fc):
'''
@breif: convert fc to conv
@param: model_define, src_prototxt
@param: model_weight, src_model
@param: model_define_fc, dst_prototxt
@param: model_weight_fc, dst_model
'''
net = caffe.Net(model_define, model_weight, caffe.TEST)
fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}
net_fc = caffe.Net(model_define_fc, caffe.TEST)
conv_params = {pr: (net_fc.params[pr][0].data, net_fc.params[pr][1].data) for pr in params_full_conv}
for fc in params:
print ('{} weights are {} dimensional and biases are {} dimensional'.format(fc, fc_params[fc][0].shape, fc_params[fc][1].shape))
for conv in params_full_conv:
print ('{} weights are {} dimensional and biases are {} dimensional'.format(conv, conv_params[conv][0].shape, conv_params[conv][1].shape))
for pr, pr_conv in zip(params, params_full_conv):
conv_params[pr_conv][0].flat = fc_params[pr][0].flat # flat unrolls the arrays
conv_params[pr_conv][1][...] = fc_params[pr][1]
net_fc.save(model_weight_fc)
print ('convert done!')
return net_fc
if __name__ == '__main__':
file = 'lenet.prototxt'#原始的prototxt名称
model = 'lenet.caffemodel'#原始的caffemodel名称
conv_file = 'lenet_conv.prototxt' #修改后的prototxt
conv_model = 'lenet_conv.caffemodel'#最终得到的结果
convert_full_conv(file, model, conv_file, conv_model)
验证参数:
file = 'lenet.prototxt'#原始的prototxt名称
model = 'lenet.caffemodel'#原始的caffemodel名称
conv_file = 'lenet_conv.prototxt' #修改后的prototxt
conv_model = 'lenet_conv.caffemodel'#最终得到的结果
net = caffe.Net(file, model, caffe.TEST)
fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}
net_fc = caffe.Net(conv_file, conv_model, caffe.TEST)
conv_params = {pr: (net_fc.params[pr][0].data, net_fc.params[pr][1].data) for pr in params_full_conv}
for pr, pr_conv in zip(params, params_full_conv):
print(fc_params[pr][0].flat)
print(conv_params[pr][0].flat)
print(fc_params[pr][1])
print(conv_params[pr][1])
底层硬件限制是真特么多,诸如卷积层通道不能超过2048,pool层尺寸不能大于6*6,pool输出不能超过16个等等,芯片厂商自己搞自己的,模型换平台每次都改,气死偶来。
参考文档:
https://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/net_surgery.ipynb
https://blog.csdn.net/andeyeluguo/article/details/79219709
|