<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于一階泰勒展開式的結(jié)構(gòu)化剪枝

          共 3512字,需瀏覽 8分鐘

           ·

          2021-01-21 00:13

          【GiantPandaCV導(dǎo)語】文章是Nvidia在2017年ICLR發(fā)表的,核心思路是將結(jié)構(gòu)化通道剪枝判別依據(jù)視為一個優(yōu)化問題,即最小化剪枝后前后的代價函數(shù)之間的差。把優(yōu)化問題基于一階泰勒展開式近似,得到通道重要性的判據(jù)只需要考慮激活函數(shù)與對應(yīng)的梯度的乘積,再求其均值。為了跨層的公平性加上重要性歸一化,以及加入Flops正則化。

          0.引言

          文章是NVIDIA在2017 ICLR上面發(fā)表的,《Pruning convolution Neural Network for resource efficient inference》。其核心也是將結(jié)構(gòu)化通道剪枝判別依據(jù)視為一個優(yōu)化問題,最小化剪枝后前后的代價函數(shù)之間的差。

          四個要點:

          1、優(yōu)化方程是最小化已減去權(quán)重的代價函數(shù)與未剪枝之前權(quán)重的代價函數(shù)之差,用一階泰勒展開式去近似優(yōu)化方程,計算通道重要性只需要激活函數(shù)與對應(yīng)的梯度的乘積,再求其均值;

          2、對計算出來的重要性進行歸一化;

          3、加入FLOPs等正則化,使其硬件更友好;

          4、可以聯(lián)合其他通道重要性判據(jù)

          圖片描述:三步剪枝流程圖

          三步剪枝流程圖

          一.剪枝的優(yōu)化方程

          這一部分是為了推導(dǎo)出公式(6)、公式(7)公式(8)。

          訓(xùn)練樣本集合

          表示輸入, 表示輸出

          網(wǎng)絡(luò)模型的參數(shù)

          模型參數(shù)的代價函數(shù)為 ,其中 是負對數(shù)似然函數(shù)(negative log-likelihood function)

          剪枝的目標是最小化已減去的權(quán)重的代價函數(shù)與未剪枝之前的代價函數(shù)的差,記為公式(1)

          其中 ,范數(shù),也即非0值的個數(shù), 是被剪掉的權(quán)重參數(shù)。

          按照最樸素遍歷的方法,剪去一組參數(shù)需要次計算,顯然不科學(xué)的。比如VGG-16有4224個卷積特征圖(可以對照VGG模型數(shù)出來)。

          利用泰勒展開式的方法來近似優(yōu)化方程:

          一組卷積核:

          ,是一組特征圖, 表示layer

          單張?zhí)卣鲌D

          ,表示剪枝與否。

          所以

          特征圖集合記為:

          是由一組參數(shù)得到的

          公式(2)

          表示被剪去參數(shù)的代價函數(shù)是原來參數(shù)的代價函數(shù)

          公式(3) 為泰勒公式:

          用一階泰勒展開式來逼近,即

          公式(4)

          余項采用拉格朗日(Lagrange)余項:

          所以 :

          忽略余項,將公式(4)代入公式(2),

          公式(5)

          公式(6)

          其中 ?是特征圖向量的長度。公式5和公式6本質(zhì)上沒有什么區(qū)別,只是等價變換。

          到這里,優(yōu)化方程已經(jīng)得到了,就是公式6,得出的就是通道重要性的評分,這里計算通道重要性只需要計算激活函數(shù)與對應(yīng)的梯度的乘積,再求其均值。

          另外,為了保證跨層的通道之間的公平性,對特征圖作了歸一化,

          公式(7)

          其中是第層中第個通道(參數(shù)組)的重要性。

          最后一點,做了FLOPs正則化,這個是為了減少FLOPs,這里也可以對其他參數(shù)做正則化,比如存儲大小,內(nèi)存,卷積核。

          公式(8)

          二、核心代碼實現(xiàn)

          整個代碼不算大,但是全部貼上來也占據(jù)不少位置,于是我就貼上文章核心觀點的重要代碼,全部代碼在參考鏈接。

          圖片描述:整體代碼流程圖

          代碼流程圖

          1、通道重要性計算

          def?compute_rank(self,?grad,?lamda=1):
          ????activation_index?=?len(self.activations)?-?self.grad_index?-?1
          ????activation?=?self.activations[activation_index]
          ????
          ????taylor?=?activation?*?grad????????????##計算基于一階泰勒展開的值???
          ????taylor?=?taylor.mean(dim=(0,?2,?3)).data????##?以通道維度計算得分

          ????flops?=?self.flops_dict[activation_index]?*?torch.ones_like(taylor)?###FLOPs?正則化,見下面get_flops()
          ????taylor?=?taylor?-?lamda?*?flops?#?公式(8)

          ????if?activation_index?not?in?self.filter_ranks:
          ????????self.filter_ranks[activation_index]?=?torch.FloatTensor(activation.size(1)).zero_().cuda()

          ????????self.filter_ranks[activation_index]?+=?taylor
          ????????self.grad_index?+=?1

          2、計算FLOPs

          def?get_flops(self):
          ????self.flops_dict?=?{}
          ????def?hook(module,?inputs,?outputs):??#hook函數(shù),用來計算每層的flops
          ????????params?=?module.weight.size().numel()??#torch.numel()?返回一個tensor變量內(nèi)所有元素個數(shù),可以理解為矩陣內(nèi)元素的個數(shù)
          ????????W?=?outputs.size(2)
          ????????H?=?outputs.size(3)
          ????????module.flops?=?params?*?W?*?H??#計算flops
          ????????
          ????for?m?in?model.modules():
          ????????if?isinstance(m,?nn.Conv2d):
          ????????????m.register_forward_hook(hook)?#為每一層注冊hook
          ????????x?=?torch.randn(1,?3,?224,?224)?#隨便定義一個數(shù)據(jù),跑一次forward來獲取flops
          ????????_?=?self.model(x)
          ????????activation_index?=?0
          ????????for?m?in?self.model.modules():
          ????????????if?isinstance(m,?nn.Conv2d):
          ????????????????self.flops_dict[activation_index]?=?m.flops??#獲取每層的flops,記錄到字典
          ????????????????activation_index?+=?1

          3、對基于一階泰勒展開式計算得到重要性,進行通道歸一化

          def?normalize_ranks_per_layer(self):
          ????for?i?in?self.filter_ranks:
          ????????v?=?torch.abs(self.filter_ranks[i])
          ????????v?=?v?/?torch.sqrt(torch.sum(v?*?v))
          ????????self.filter_ranks[i]?=?v

          三、文章的一些討論

          1、泰勒展開的討論

          1990年 LeCun提出Optimal Brain Damage (OBD) 也是采用泰勒展開式的方法來近似。因為經(jīng)過多次訓(xùn)練迭代后,梯度會趨向于0,那么,則,所以LeCun認為提供的信息很有限, ,所以采用泰勒二階展開式。

          雖然的期望為0,但是他的方差不為0,其,所以,所以,可以用一階泰勒展開式來近似。

          2、通道重要性

          雖然文章提出了一種基于一階泰勒展開的方法計算通道重要性,從flops正則化中我們可以,將其他通道重要性判別也加入最后的重要性排序,也就是在公式8中加入其他項,這樣可以更加全面的考慮通道重要性;當然,隨之增加的就是整個剪枝算法的計算量和耗時也增加。

          四、參考鏈接

          • 論文:https://arxiv.org/abs/1611.06440

          • 代碼:https://github.com/azhe198827/channel_prune


          歡迎關(guān)注GiantPandaCV, 在這里你將看到獨家的深度學(xué)習(xí)分享,堅持原創(chuàng),每天分享我們學(xué)習(xí)到的新鮮知識。( ? ?ω?? )?

          有對文章相關(guān)的問題,或者想要加入交流群,歡迎添加BBuf微信:

          二維碼

          為了方便讀者獲取資料以及我們公眾號的作者發(fā)布一些Github工程的更新,我們成立了一個QQ群,二維碼如下,感興趣可以加入。

          公眾號QQ交流群


          瀏覽 186
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人偷拍小视频 | 久久久三级电影 | 激情综合网五月丁香 | 国产精品爽爽久久久 | 久久视频午夜视频久久 |