1. 前言
现阶段还坚持使用Matconvnet工具箱的一定是MATLAB的死粉。与TensorFlow、Keras相比,matconvnet的便捷性不够。但是,matlab与matconvnet提供了良好的交互调试功能,使得算法开发可以非常迅速得到验证。对于一个训练好的模型,如何迅速的进行测试,这篇博客会开放我对这类问题的处理方法和代码。
2. SimpleNN和 DagNN
参考:http://www.vlfeat.org/matconvnet/mfiles/+dagnn/@DagNN/DagNN/
接触过SimpleNN的童鞋应该记得,SimpleNN是通过struct结构体进行构建的。所以在发布模型或者共享模型的时候可以直接将结构体进行发布,再利用vl_simpnn进行评估就好了。
后来由于Simplenn定义太随性,使得代码非常容易出错。我讲的随性不是灵活,而是结构极其松散。牛津团队为了应付这个事,开始采用DagNN,也就是有向无环图进行网络的定义、训练,但是没有封装一个更好的用于DagNN评估函数。因此,我们只能通过vl_simplenn进行模型评估。也就是说,我们需要将DagNN转成SimpleNN,并去除掉损失函数层。下面开始详细说明我探索出来的一种方法:
首先将网络确定成DagNN类型:
net = dagnn.DagNN.loadobj(net) ; % 'struct' To 'dagnn'
采用遍历的方式进行信息提取:
function simple_net = deployNet(net)
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.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
很多同学问我,为什么要将训练好的模型转成DagNN之后,在进行网络层和网络参数提取。这是因为我需要用DagNN封转好的一些函数,如getParamIndex()简化流程。
一旦训练好的网络得到了如上处理就可以直接用于测试。测试函数为:
res = vl_simplenn(net, instance)
这里需要注意两点: instance要求为single类型;我们需要用gpuArray(instance)将待测试数据放入到GPU中。
3. vl_simplenn解析
在使用vl_simplenn进行模型性能评估之前,我们都会进行如下操作:
net = vl_simplenn_tidy(net) % matconvnet的版本适应性
res = vl_simplenn(net, inputdata)
http://www.vlfeat.org/matconvnet/mfiles/simplenn/vl_simplenn/