#!/usr/bin/env python# -*- coding: utf-8 -*-"""After SegNet has been trained, run compute_bn_statistics.py script and then BN-absorber.py.For inference batch normalization layer can be merged into convolutional kernels, tospeed up the network. Both layers applies a linear transformation. For that reasonthe batch normalization layer can be absorbed in the previous convolutional layerby modifying its weights and biases. That is exactly what the script does."""import osimport numpy as npfrom argparse import ArgumentParserfrom os.path import joinimport argparseimport syscaffe_root = '/SegNet/caffe-segnet-cudnn5/' # Change this to the absolute directory to SegNet Caffesys.path.insert(0, caffe_root + 'python')import caffefrom caffe.proto import caffe_pb2from google.protobuf import text_format__author__ = 'Timo Sämann'__university__ = 'Aschaffenburg University of Applied Sciences'__email__ = 'Timo.Saemann@gmx.de'__data__ = '6th May, 2017'def copy_double(data):return np.array(data, copy=True, dtype=np.double)def bn_absorber_weights(model, weights):# load the prototxt file as a protobuf messagewith open(model) as f:str2 = f.read()msg = caffe_pb2.NetParameter()text_format.Merge(str2, msg)# load netnet = caffe.Net(model, weights, caffe.TEST)# iterate over all layers of the networkfor i, layer in enumerate(msg.layer):# check if conv layer exist right before bn layer, otherwise merging is not possible and skipif not layer.type == 'BN':continueif not msg.layer[i-1].type == 'Convolution':continue# get the name of the bn and conv layerbn_layer = msg.layer[i].nameconv_layer = msg.layer[i-1].name# get some necessary sizeskernel_size = 1shape_of_kernel_blob = net.params[conv_layer][0].data.shapenumber_of_feature_maps = list(shape_of_kernel_blob[0:1])shape_of_kernel_blob = list(shape_of_kernel_blob[1:4])for x in shape_of_kernel_blob:kernel_size *= xweight = copy_double(net.params[conv_layer][0].data)bias = copy_double(net.params[conv_layer][1].data)# receive new_gamma and new_beta which was already calculated by the compute_bn_statistics.py scriptnew_gamma = net.params[bn_layer][0].data[...]new_beta = net.params[bn_layer][1].data[...]# manipulate the weights and biases over all feature maps:# weight_new = weight * gamma_new# bias_new = bias * gamma_new + beta_new# for more information see https://github.com/alexgkendall/caffe-segnet/issues/109for j in xrange(number_of_feature_maps[0]):net.params[conv_layer][0].data[j] = weight[j] * np.repeat(new_gamma.item(j), kernel_size).reshape(net.params[conv_layer][0].data[j].shape)net.params[conv_layer][1].data[j] = bias[j] * new_gamma.item(j) + new_beta.item(j)# set the no longer needed bn params to zeronet.params[bn_layer][0].data[:] = 0net.params[bn_layer][1].data[:] = 0return netdef bn_absorber_prototxt(model):# load the prototxt file as a protobuf messagewith open(model) as k:str1 = k.read()msg1 = caffe_pb2.NetParameter()text_format.Merge(str1, msg1)# search for bn layer and remove themfor l in msg1.layer:if l.type == "BN":msg1.layer.remove(l)return msg1def make_parser():parser = argparse.ArgumentParser()parser.add_argument('--model', type=str, required=True, help='.prototxt file which you want to use for inference')parser.add_argument('--weights', type=str, required=True, help='.caffemodel file in which the batch normalization ''and convolutional layer should be merged')parser.add_argument('--out_dir', type=str, required=True,help='output directory in which the modified model and weights should be stored')parser.add_argument('--gpu', type=str, default='0', help='0: gpu mode active, else gpu mode inactive')return parserif __name__ == '__main__':parser1 = make_parser()args = parser1.parse_args()if args.gpu == 0:caffe.set_mode_gpu()else:caffe.set_mode_cpu()# check if output directory existif not os.path.exists(args.out_dir):os.makedirs(args.out_dir)network = bn_absorber_weights(args.model, args.weights) # merge bn layer into conv kernelmsg_proto = bn_absorber_prototxt(args.model) # remove bn layer from prototxt file# save prototxt for inferenceprint "Saving inference prototxt file..."path = os.path.join(args.out_dir, "bn_conv_merged_model.prototxt")with open(path, 'w') as m:m.write(text_format.MessageToString(msg_proto))# save weightsprint "Saving new weights..."network.save(os.path.join(args.out_dir, "bn_conv_merged_weights.caffemodel"))print "Done!"
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。