深度网络模型裁剪和发布正规化
1.導讀
關于Matconvnet中模型發布與共享的思考:https://blog.csdn.net/shenziheng1/article/details/81316760
前面討論了,如何利用vl_simplenn應用訓練好的模型。有一些朋友問我,明明可以直接通過net.val評估函數進行處理,為什么還要單獨發布模型,是不是多此一舉?
其實,采用模型直接進行評估,或者采用網絡裁剪后應用,完全看個人所需。就我自己而言,訓練多分支結構用于跟蹤領域,如果采用網絡直接進行評估是非常消耗時間的。但是,在跟蹤領域,跟蹤的速度是一個非常重要的的指標!但是,既然有朋友指出來了,我直接對兩種測試網絡方式都放在這里,需要那種可以直接用。
- 利用DagNN的評估函數,評估原始網絡,用于測試模式;
- 利用我共享的代碼進行網絡裁剪,提取網絡核心成分用于測試;
- 此外,這篇博文也增加了對BatchNorm的討論
2. DagNN的評估函數 eval
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);3. 采用我編寫的裁剪網絡提取主干
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) ;elseerror('No such layer!');endcontinue;endend end這段代碼可以直接調用。之前發布的那個版本由于沒有添加BatchNorm層,這個版本涵蓋了所有成分。
我親自用孿生網絡測試過,利用裁剪后的網絡要比利用完整網絡跟蹤速度提升477%。
3. 關于BatchNorm的補充
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的數,防止分母出現0momentum : 動量參數,一般為0.9, 0.99, 0.999running_mean :滑動平均的方式計算新的均值,訓練時計算,為測試數據做準備running_var : 滑動平均的方式計算新的方差,訓練時計算,為測試數據做準備 """這里需要額外說明的是bn的學習參數,使用MatConvNet的都知道,我們學習好BatchNorm層之后會返回三個參數值,bn_f / bn_b / bn_c。 如果前面兩個用來表征Batch的均值和標準差,那第三個參數是什么?
其實,BatchNorm的原理就是用一系列Batch去評估整個數據集整體的均值和方差。這其實是有有偏估計,最簡單的方法就是引入時間平滑。
2. BatchNorm到底有對多大用?是不是有了BatchNorm就一定能夠避免過擬合?
不是這樣的,小心做好自己的訓練集。爭取使得訓練集可以做到獨立同分布。否則極其容易過擬合(現象:訓練集的誤差非常小,然而驗證集的誤差很大)。
總結
以上是生活随笔為你收集整理的深度网络模型裁剪和发布正规化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一种被忽视的构造和整数溢出重现
- 下一篇: C++ Templates 中的一个例