关于Matconvnet中模型发布与共享的思考:https://blog.csdn.net/shenziheng1/article/details/81316760
前面讨论了,如何利用vl_simplenn应用训练好的模型。有一些朋友问我,明明可以直接通过net.val评估函数进行处理,为什么还要单独发布模型,是不是多此一举?
其实,采用模型直接进行评估,或者采用网络裁剪后应用,完全看个人所需。就我自己而言,训练多分支结构用于跟踪领域,如果采用网络直接进行评估是非常消耗时间的。但是,在跟踪领域,跟踪的速度是一个非常重要的的指标!但是,既然有朋友指出来了,我直接对两种测试网络方式都放在这里,需要那种可以直接用。
netStruct = load('net_name.mat');
net = dagnn.DagNN.loadobj(netStruct.net);
net.mode = 'test'; % 非常重要
net.move('gpu');
net.conserveMemory = false;
im = rand(32,32,1,'single'); % 测试数据
net.eval({'data_rand',gpuArray(im)}); % 测试数据索引
result = gather(net.vars(net.getVarIndex(('G3x'))).value);
function simple_net = deployNet(net)
% keep single branch network, then called L2 norm to calculate similarity
input = 'target';
output = 'block3x';
simple_net = [];
simple_net.layers = [];
simple_net.meta = net.meta;
while ~strcmp(input,output)
for i = 1:numel(net.layers)
if numel(net.layers(i).inputs) == 1 && strcmp(net.layers(i).inputs{1},input)
input = net.layers(i).outputs{1};
if isa(net.layers(i).block,'dagnn.Conv')
simple_net.layers{end+1} = struct(...
'name', net.layers(i).name, ...
'type', 'conv', ...
'weights', {{net.params(net.getParamIndex(net.layers(i).params{1,1})).value,...
net.params(net.getParamIndex(net.layers(i).params{1,2})).value}}, ...
'pad', net.layers(i).block.pad, ...
'stride', net.layers(i).block.stride,...
'dilate',net.layers(i).block.dilate) ;
elseif isa(net.layers(i).block,'dagnn.BatchNorm')
simple_net.layers{end+1} = struct(...
'name', deal(net.layers(i).name), ...
'type', 'bnorm',...
'weights',{{net.params(net.getParamIndex(net.layers(i).params{1,1})).value,...
net.params(net.getParamIndex(net.layers(i).params{1,2})).value,...
net.params(net.getParamIndex(net.layers(i).params{1,3})).value}} ) ;
elseif isa(net.layers(i).block,'dagnn.ReLU')
simple_net.layers{end+1} = struct(...
'name', deal(net.layers(i).name), ...
'type', 'relu') ;
elseif isa(net.layers(i).block,'dagnn.Pooling')
simple_net.layers{end+1} = struct(...
'name', deal(net.layers(i).name), ...
'method',deal(net.layers(i).block.method),...
'pool', deal(net.layers(i).block.poolSize),...
'stride',deal(net.layers(i).block.stride),...
'pad', deal(net.layers(i).block.pad),...
'type', 'pool');
elseif isa(net.layers(i).block,'dagnn.LRN')
simple_net.layers{end+1} = struct(...
'name', deal(net.layers(i).name), ...
'type', 'lrn',...
'param',net.layers(i).block.param) ;
else
error('No such layer!');
end
continue;
end
end
end
这段代码可以直接调用。之前发布的那个版本由于没有添加BatchNorm层,这个版本涵盖了所有成分。
我亲自用孪生网络测试过,利用裁剪后的网络要比利用完整网络跟踪速度提升477%。
Double_V_博主维护的https://blog.csdn.net/qq_25737169/article/details/79048516 (基础 | batchnorm原理及代码详解)质量非常高。这里,引用一下他的工作作为参考。
1. BatchNorm到底涉及到哪些参数?
Batchnorm(x, gamma, beta, bn_param):
"""
param:x : 输入数据,设shape(B,L)
param:gama : 缩放因子 γ
param:beta : 平移因子 β
param:bn_param : batchnorm所需要的一些参数
eps : 接近0的数,防止分母出现0
momentum : 动量参数,一般为0.9, 0.99, 0.999
running_mean :滑动平均的方式计算新的均值,训练时计算,为测试数据做准备
running_var : 滑动平均的方式计算新的方差,训练时计算,为测试数据做准备
"""
这里需要额外说明的是bn的学习参数,使用MatConvNet的都知道,我们学习好BatchNorm层之后会返回三个参数值,bn_f / bn_b / bn_c。 如果前面两个用来表征Batch的均值和标准差,那第三个参数是什么?
其实,BatchNorm的原理就是用一系列Batch去评估整个数据集整体的均值和方差。这其实是有有偏估计,最简单的方法就是引入时间平滑。
2. BatchNorm到底有对多大用?是不是有了BatchNorm就一定能够避免过拟合?
不是这样的,小心做好自己的训练集。争取使得训练集可以做到独立同分布。否则极其容易过拟合(现象:训练集的误差非常小,然而验证集的误差很大)。