深度网络模型裁剪和发布正规化
1.導(dǎo)讀
關(guān)于Matconvnet中模型發(fā)布與共享的思考:https://blog.csdn.net/shenziheng1/article/details/81316760
前面討論了,如何利用vl_simplenn應(yīng)用訓(xùn)練好的模型。有一些朋友問我,明明可以直接通過net.val評(píng)估函數(shù)進(jìn)行處理,為什么還要單獨(dú)發(fā)布模型,是不是多此一舉?
其實(shí),采用模型直接進(jìn)行評(píng)估,或者采用網(wǎng)絡(luò)裁剪后應(yīng)用,完全看個(gè)人所需。就我自己而言,訓(xùn)練多分支結(jié)構(gòu)用于跟蹤領(lǐng)域,如果采用網(wǎng)絡(luò)直接進(jìn)行評(píng)估是非常消耗時(shí)間的。但是,在跟蹤領(lǐng)域,跟蹤的速度是一個(gè)非常重要的的指標(biāo)!但是,既然有朋友指出來了,我直接對(duì)兩種測試網(wǎng)絡(luò)方式都放在這里,需要那種可以直接用。
- 利用DagNN的評(píng)估函數(shù),評(píng)估原始網(wǎng)絡(luò),用于測試模式;
- 利用我共享的代碼進(jìn)行網(wǎng)絡(luò)裁剪,提取網(wǎng)絡(luò)核心成分用于測試;
- 此外,這篇博文也增加了對(duì)BatchNorm的討論
2. DagNN的評(píng)估函數(shù) 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'); % 測試數(shù)據(jù) net.eval({'data_rand',gpuArray(im)}); % 測試數(shù)據(jù)索引 result = gather(net.vars(net.getVarIndex(('G3x'))).value);3. 采用我編寫的裁剪網(wǎng)絡(luò)提取主干
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這段代碼可以直接調(diào)用。之前發(fā)布的那個(gè)版本由于沒有添加BatchNorm層,這個(gè)版本涵蓋了所有成分。
我親自用孿生網(wǎng)絡(luò)測試過,利用裁剪后的網(wǎng)絡(luò)要比利用完整網(wǎng)絡(luò)跟蹤速度提升477%。
3. 關(guān)于BatchNorm的補(bǔ)充
Double_V_博主維護(hù)的https://blog.csdn.net/qq_25737169/article/details/79048516?(基礎(chǔ) | batchnorm原理及代碼詳解)質(zhì)量非常高。這里,引用一下他的工作作為參考。
1. BatchNorm到底涉及到哪些參數(shù)?
Batchnorm(x, gamma, beta, bn_param): """ param:x : 輸入數(shù)據(jù),設(shè)shape(B,L) param:gama : 縮放因子 γ param:beta : 平移因子 β param:bn_param : batchnorm所需要的一些參數(shù)eps : 接近0的數(shù),防止分母出現(xiàn)0momentum : 動(dòng)量參數(shù),一般為0.9, 0.99, 0.999running_mean :滑動(dòng)平均的方式計(jì)算新的均值,訓(xùn)練時(shí)計(jì)算,為測試數(shù)據(jù)做準(zhǔn)備running_var : 滑動(dòng)平均的方式計(jì)算新的方差,訓(xùn)練時(shí)計(jì)算,為測試數(shù)據(jù)做準(zhǔn)備 """這里需要額外說明的是bn的學(xué)習(xí)參數(shù),使用MatConvNet的都知道,我們學(xué)習(xí)好BatchNorm層之后會(huì)返回三個(gè)參數(shù)值,bn_f / bn_b / bn_c。 如果前面兩個(gè)用來表征Batch的均值和標(biāo)準(zhǔn)差,那第三個(gè)參數(shù)是什么?
其實(shí),BatchNorm的原理就是用一系列Batch去評(píng)估整個(gè)數(shù)據(jù)集整體的均值和方差。這其實(shí)是有有偏估計(jì),最簡單的方法就是引入時(shí)間平滑。
2. BatchNorm到底有對(duì)多大用?是不是有了BatchNorm就一定能夠避免過擬合?
不是這樣的,小心做好自己的訓(xùn)練集。爭取使得訓(xùn)練集可以做到獨(dú)立同分布。否則極其容易過擬合(現(xiàn)象:訓(xùn)練集的誤差非常小,然而驗(yàn)證集的誤差很大)。
總結(jié)
以上是生活随笔為你收集整理的深度网络模型裁剪和发布正规化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一种被忽视的构造和整数溢出重现
- 下一篇: 10条途径迅速提高你的生活