# Pruning - Learning Efficient Convolutional Networks through Network Slimming
> [name=謝朋諺(Adam Hsieh)]
> [time=Thu, Nov 5, 2020 3:03 PM]
###### tags: `paper`
---
## Reference
> [Learning Efficient Convolutional Networks through Network Slimming](https://blog.csdn.net/h__ang/article/details/89376079)
> [模型压缩:Networks Slimming-Learning Efficient Convolutional Networks through Network Slimming](https://blog.csdn.net/u011995719/article/details/78788336)
> [【论文阅读笔记】Learning Efficient Convolutional Networks through Network Slimming](https://blog.csdn.net/qq_19784349/article/details/107214544)
> [模型压缩:利用BN放缩因子来修剪Channel](https://zhuanlan.zhihu.com/p/39761855)
> [次梯度(subgradient)方法](https://blog.csdn.net/quiet_girl/article/details/79648124)
> [【机器学习】次梯度(subgradient)方法](https://blog.csdn.net/qq_32742009/article/details/81704139)
---
# Learning Efficient Convolutional Networks through Network Slimming
[論文連結](https://openaccess.thecvf.com/content_ICCV_2017/papers/Liu_Learning_Efficient_Convolutional_ICCV_2017_paper.pdf)
{%pdf https://openaccess.thecvf.com/content_ICCV_2017/papers/Liu_Learning_Efficient_Convolutional_ICCV_2017_paper.pdf %}
## Outline
> [TOC]
## 摘要重點
- 本文提出一種新的 CNNs 學習策略,他同時滿足
1. 縮小模型大小
2. 減少執行時佔用的記憶體大小
3. 在不影響正確率的情況下降低計算的 operations
- 利用 Channel 稀疏化是一個簡單又有效的方法,我們稱之為 Network Slimming。
- 在訓練期間不重要的 Channel 可以被自動鑑別並刪除,進而產生無損正確率的緊湊網路。
- 在多個網路上做個實驗,對於 VGGNet 使用一個 Multi-pass 方案(也就是將網路瘦身這過程重複多次)使得模型大小上壓縮了 20 倍,計算量上少了 5 倍。
## CNN 網路現實中容易遇到的三大挑戰
1. **Model Size:** CNN 的強力表現是來源於上百萬可訓練的參數,這些參數在儲存的時候以一個訓練在 ImageNet 良好的模型來說大概需要 300MB 的硬碟空間,在 Inference 的時候又得載入到記憶體中,對於嵌入式系統是很大的負擔。
2. **Run-time memory:** 在 inference 的時候,CNN 的中間 Activation/Response 儲存空間甚至需要比儲存模型的參數還要大,就算 Batch Size 只有 1。這對好一點的 GPU 來說不是問題,但對於低計算能力的裝置是很大的負擔。
3. **Number of computing operations:** 再高解析度的圖片上執行卷積操作可能會計算過大,一個大的 CNN 在嵌入式裝備上可能要花費幾分鐘來處理一張影像,非常不實用。
## 壓縮大型 CNN 網路的方法
1. **Low-rank Decomposition:** 主要使用 **奇異值分解(SVD)** 對全連接層可以,但對卷積層不怎麼樣;模型可壓縮三倍,但運算速度無明顯提升。
2. **Weight Quantization:**
- HashNet 雖然可以採用分組、共享權重方法來壓縮所需保存的參數數量,且在深度壓縮中使用提高的量化技術再 AlexNet 和 VGGNet 上可以達到 35x~49x 的壓縮比,但是在 Run-time memory 上面沒有任何壓縮,也不能節省 inference 時間,因為必須將共享的權重恢復到原來的位置,甚至要多了解碼的時間。
- 也有人將真實的權重值量化為二元或三元化的權重 ($\{-1,1\}$ or $\{-1,0,1\}$),這種極大的壓縮了模型大小,同時由於是位元的操作,所以速度也很快,但這種激進的 low-bit 近似法通常也帶來顯著的準度下降。
3. **Binarization:** 損失 Precision。
4. **Weight pruning / Sparsifying:**
* 提出在訓練網路中剪枝掉不重要的連接關係,這樣的話網路中的權重大多數變成了 0,可以使用一種稀疏的模式儲存模型。
* 但這些方法必須用專門的稀疏矩陣函式庫或硬體來加速,運行時的記憶體佔用節省非常有限,因為產生的 Activation maps 仍然是密集的。
5. **Dynamic inference**
6. **Structured Pruning / Sparsifying:**
- 在訓練 CNNs 時剪枝通道,然後透過微調來恢復準度;也有些人透過隨機拋棄 channel-wise 的連接引入稀疏化,也會得到更小的網路。
- 我們在訓練過程中將 channel-wise 稀疏化加到目標函示,導致了一種更平滑的通道剪枝過程和較小的精度損失。
- 由於這些方法都是對網路結構的一部份做剪枝或稀疏化,而不是對個別權重,因此不太需要特別的函式庫,
- 本文的 Network slimming 就屬於這種方法。號稱沒有缺點?!且解決了前面所有的挑戰,方法是將 L1 Regularization 放在 Batch Normalization 的縮放因子上,這可以使得縮放因子趨向於 0,使得我們可以鑑別出不重要的 Channel 或神經元,這是因為==每一個縮放因子都跟和一個特定的 CNN channel 或全連接層的一個神經元相關聯==。剪掉不重要的 Channels 有時候可能會降低效能,但是通過對剪枝過後的網路微調可以對 Precision 作補償。
- 在幾個基準的資料集和不同的網路架構上的實驗表明可以==將 CNN 模型壓縮 20 倍、計算量壓縮 5 倍==,同時實現更高的準確率。
:::success
:bulb: Regularization 很少傷到效能,甚至有些時候能提高泛化的正確率。
:::
7. **Neural Architecture Learning:** 提出用強化式學習自動學習神經網路結構,這些方法的搜索空間非常大,因此常常需要從上百個模型中辨別好壞,Network slimming 可以說是一種結構式學習,只是對於每一層的選擇有限,但比起前面的方法 Network slimming 僅透過單個訓練過程就可以學習到網路結構,是很高效的做法。
## Network Slimming
### Advantages of Channel-level Sparsity.
稀疏化是可以在不同的 level 上來實現 (weight-level, kernal-level, channel-level, layer-level)
- Fine-grained level (weight-level): 有最高的靈活性與泛化能力因此可以獲得最高的壓縮比,但通常需要特殊的軟硬體加速器才能在稀疏模型上快速推理。
- Coarsest layer-level: 相反的這種粗粒度稀疏化不需要特殊的函式庫做 Inference 加速,但靈活度就沒有這麼高,而且也只有在深度夠深的時候才適用 (超過 50 層)。
- Channel-level: 相比之下 Channel-level 做出了平衡,可以被應用到任何典型的 CNN 或者全連接層 (講每個神經元看作一個通道),就可以將網路減肥。
### Chanllenges
- 要實作 Channel-level sparsity 需要和一個 Channel 相關聯的輸入和輸出都剪掉,但==對已經訓練好的模型來說並不適合==,比如對預訓練好的 ResNet 做 channel pruning 在不損失 precision 的情況下大概只能減少 ~10% 的參數量。
- 在其他篇論文中有提到通過強迫將==稀疏正歸化的放進目標函式==,也就是採用 **Group Lasso** 來==使得所有 filter 的同一個通道在訓練時同時趨向於 0==,不過這個方法需要額外計算新引入的和所有 filters 有關的梯度項。
### Scaling Factors and Sparsity-induced Penalty
1. 對每個 Channel 引入一個縮放因子 $\gamma$,並與 Channel 的輸出相乘。
2. 接著一起訓練模型權重和這些縮放因子。
3. 最後我們剪枝那些縮放因子 $\gamma$ 過小的 Channel。
4. 微調剪枝後的網路。
以上步驟最後可得這個公式:$$L=\sum_{(x,y)}l(f(x,W),y)+\lambda\sum_{\gamma\in\Gamma}g(\gamma)$$
- $(x,y)$ 是訓練的輸入和目標
- $W$ 是網路中可訓練的參數
- 第一項是 CNN 網路的 Loss Function
- $g(.)$ 是縮放因子的懲罰項
- $\lambda$ 是兩項的平衡因子
- 在本文我們是設 $g(s)=|s|$,也就是 L1-norm,這個方法被廣泛地用在稀疏化的步驟中。
- 次梯度化下降法 (Subgradient descent) 被採用在 L1 不平滑(不可微分)的 L1 懲罰項優化方法,另一個建議是使用平滑的 L1 正規化取代 L1 懲罰項,盡量避免在不平滑的點使用次梯度。
:::success
:bulb: 次梯度方法是傳統梯度下降算法的拓展,傳統梯度下降算法是為了解決可導凸函數的問題,而次梯度方法主要是為了解決不可導梯度的問題。但是其算法收斂速度會相對較慢。
- 想深入了解可直接參考:[次梯度(subgradient)方法](https://blog.csdn.net/quiet_girl/article/details/79648124) 或 [【机器学习】次梯度(subgradient)方法](https://blog.csdn.net/qq_32742009/article/details/81704139)

:::
剪掉一個 Channel 代表要剪掉他的輸入與輸出的連接關係,因此我們可以直接獲得一個較窄的網路且不需要藉由任何特殊的軟硬體加速,如下圖所示,因為我們透過縮放因子的正規項來自動辨別不重要的 Channel 並移除掉,幾乎不影響網路的泛化能力。

:::info
:bulb: 本文將每個縮放因子與 CNN 中的每個 Channel 相關聯。
- 上圖可看到在訓練過程中,縮放因子進行稀疏正規化後會自動識別不重要的 Channel。
- 左側模型縮放因子較小的(橘色)將會被修剪掉,變為較緊湊的右側模型,然後對其進行微調以達到正常訓練網路的準確率。
:::
### Leveraging the Scaling Factors in BN Layers
- BN 現已被大多數現代 CNN 網路採用,本文將他與 channel-wise 縮放因子做結合,尤其 BN 層使用 mini-batch 的統計特性對內部 Activation 做正規化。
- BN layer 的公式如下:$$\hat z=\dfrac{z_{in}-\mu{_B}}{\sqrt{(\sigma^2_B+\epsilon)}};z_{out}=\gamma\hat z+\beta$$
- $\mu_B$ 是 $B$ 上輸入 Activation 的平均值
- $\sigma_B$ 是 $B$ 上輸入 Activation 的標準差
- $\gamma$ 和 $\beta$ 是可訓練的 Affine 轉換參數 (Scale and Shift)
- 通常會==在卷積層之後插入一個 BN 層,引入 Channel-wise 的 Scaling/Shifting 的參數==,並將 BN 層的 $\gamma$ 參數作為本文網路瘦身的縮放因子,這個做法最大的優勢就是並不會給網路帶來額外的資源成本,又能有效的學習到作為 Channel 剪枝的縮放因子:
1. 如果本文未使用 BN 層而是在卷基層之後添加一個縮放層,這個縮放因子對於評估一個 Channel 重要性就變得沒有意義。
2. 如果我們在 BN 層之前插入一個縮放層,縮放層的影響將完全被 BN 層所掩蓋。
3. 如果我們在 BN 層之後插入一個縮放層,就等於每個 Channel 將會有兩個連續的縮放因子。
### Channel Pruning and Fine-tuning
- 引入縮放因子的正規項後,我們得到的許多縮放因子都會趨近於 0,並且剪掉趨近於 0 的 Channel 的輸入和輸出的連接,每一組都有各自的 $\gamma$ 和 $\lambda$。
- 要刪掉的 Channel 會透過一個全域閾值,比如我們要剪掉整個網路的 70% 的通道,那麼我們就會對縮放因子進行排序,然後取從小到大 70% 的縮放因子當作閾值,低於它的都會被砍掉。
- 雖然剛開始修剪 Precision 會下降,但當我們開始微調之後,在本文的實驗往往狹窄的網路反而能獲得比原始未修剪的網路更高的準確性。
### Multi-pass Scheme

:::info
:bulb: Network slimming 步驟的 Flow-chart。
- 虛線部分代表可以做 multi-pass/iterative 的部分。
:::
- 我們可以將單階段學習晉升為多階段學習方法,這樣可以得到更緊湊的網路。
### Handling Cross Layer Connections and Pre-activation Structure
- 上面介紹的做法可以直接用在叫簡單的 CNN 結構,如 AlexNet, VGGNet。
- 對於有跨層連接的網路如 ResNet, DenseNet,每一層的輸出會作為後續多個層的輸入,且其 BN 層是在卷基層之前,因此稀疏化是在層的輸入末端才能得到的,也就是說==每個 Layer 會對所有輸入到他那邊的 Channel 子集合做選擇性使用==。
- 為了在測試的時候可以節省參數和計算量,我們==需要放一個 Channel Selection Layer 來鑑別重要的 Channel==。
## Experiment
### Dataset
使用 CIFAR, SVHN, ImageNet, MNIST 資料集上做測試。
- CIFAR:
- 解析度:$32\times32$
- 類別:CIFAR-10 有 10 類,CIFAR-100 有 100 類
- 訓練張數:50,000
- 測試張數:10,000
- 在 CIFAR-10 會拿訓練集的 5,000 張當驗證集並且用它來搜出前面公式所提到的 $\lambda$ 值
- 資料增強:Shifting/Mirroring
- 資料預處理:對 Channel 做平均與標準差的標準化
- SVHN:
- 解析度:$32\times32$
- 訓練張數:604,388
- 測試張數:26,032
- 拿訓練集的 6,000 張當驗證集並且用它來搜出前面公式所提到的 $\lambda$ 值
- ImageNet:
- 類別:1,000 類
- 訓練張數:1,200,000
- 測試張數:50,000
- MNIST:
- 訓練張數:60,000
- 測試張數:10,000
### Network Models
- CIFAR and SVHN
- VGGNet:在 ImageNet 預訓練過後的模型再拿來訓練。
- ResNet:使用具有瓶頸結構的 164 層預激活 ResNet。
- DenseNet:使用 40 層 DenseNet,增長率為 12。
- ImageNet
- 採用 11 層 (8-Conv + 3FC) 的 "VGG-A" 模型,並且加上 Batch Normalization,並移除了 Dropout layer。
- 為了修剪全連接層的神經元,我們直接視他們為 $1\times1$ Channel 的 Convolution Layer。
- MNIST
- 在三層全連接層上評估本文的方法。
### Training, Pruning and Fine-tuning
#### Normal Training
- 從頭開始訓練所有網路,並全部皆使用 SGD 進行實驗。
- CIFAR, SVHN:
- mini-batch: 64
- epoches: CIFAR 設為 160,SVHN 設為 20
- initial learning rate: 0.1
- update learning rate: 訓練迭代到總數的 50% 跟 75% 時各除以 10
- ImageNet, MNIST:
- mini-batch: 256
- epoches: ImageNet 設為 60,MNIST 設為 30
- initial learning rate: 0.1
- update learning rate: 訓練迭代到總數的 1/3 跟 2/3 時各除以 10
- Weight decay: $10^{-4}$
- Nesterov momentum: 0.9 不進行
- 所有實驗都先將 Channel 的縮放因子預設為 0.5。
#### Training with Sparsity
- CIFAR, SVHN:
- 超參數 $\lambda$:本文在 CIFAR-10 的驗證集上靠 grid search 得到範圍大概在 $10^{-3}, 10^{-4}, 10^{-5}$。
- VGGNet:我們選擇 $\lambda=10^{-4}$
- ResNet, DenseNet:我們設為 $\lambda=10^{-5}$
- ImageNet:
- VGG-A:我們設為 $\lambda=10^{-5}$
#### Pruning
- 使用全域修剪而非常見的每層各自的閾值修剪。
- 修剪閾值由縮放因子的百分比決定,例如 40% 的 channel 要被修剪,就取由小排到大第 40% 的那個縮放因子的值設為閾值,比他小的皆排除。
- 修剪過程是透過建構一個新的較窄的模型,並從原本的稀疏模型複製相應權重來實現。
#### Fine-tuning
- CIFAR, SVHN, MNIST:
- 使用與訓練相同的優化設置。
- ImageNet:
- 由於時間限制,僅在 5 個 epochs 內以 Learning Rate $10^{-3}$ 對 VGG-A 做微調。
## Results
### Parameter and FLOP reductions

:::info
:bulb: 在 CIFAR-10 上的資源節省情況的比較
- 藍色和綠色條是修剪後的模型和原始模型之間的參數和 FLOP 比例
:::
- 由上圖可以看出 VGGNet 具有大量可以修剪的冗余參數。
- ResNet-164 上參數和 FLOP 相對無關緊要,我們推測是因為 "Bottleneck" 結構已經有選擇 channel 的能力了。
- 另外在 CIFAR-100 上還原率通常略低於 CIFAR-10 和 SVHN,這可能跟 CIFAR-100 有更多類別的有關。



:::info
:bulb: CIFAR 和 SVHN 資料集的結果。
- 粗體代表那一個 Model 中錯誤率最低的。
- "Baseline" 表示沒有做稀疏性正則化的正常訓練。
- "60% Pruned" 表示透過稀疏性訓練模型中修剪掉 60% 的 Channel 模型。
- 修剪適量 (40%) 的 Channel 通常可以降低測試時的錯誤。
- 通常可以透過修剪 $\geq 60\%$ 的 Channel 來保持準確性。
:::
### Regularization Effect
- 從上表我們可以看出 ResNet 和 DenseNet 在修剪 40% 的 Channel 時,經過微調的網路可以實現比原始模型更低的錯誤率。
- 我們假設這是因為 L1 稀疏性對 Channel 正規化作用所致,它會在網路的中間層提供特徵選擇。

:::info
:bulb: ImageNet 結果
- 修剪 50% 的 Channel 時,參數量節省了 5 倍以上,而 FLOP 節省僅 30.4%。
- 這是因為在 CNN 中共排除了 378 個 Channel (共 2752 個),在全連接層則修剪了 5,094 個神經元 (共 8,192 個)
:::

:::info
:bulb: MNIST 結果
- 儘管我們方法是針對 CNN 但其實對全連接層幫助也很顯著。
- 在這個實驗中當我們使用全局閾值的時候會不小心刪除掉整層,因此在這邊我們是修剪兩個中間層中的每層 80% 的神經元。
- 本文的方法也勝過另一篇論文的做法。
:::
### Results for Multi-pass Scheme
- 我們使用 VGGNet 在 CIFAR 上執行 multi-pass 的實驗,由於沒有 skip-connections,所以若刪掉整個 Layer 會導致 model 被破壞,因此我們將全域閾值設置 50% 之外,也提出另一個限制就是每層最多只能刪減 50% 的 Channel。

:::info
:bulb: 使用 CIFAR-10, CIFAR-100 當作資料集,模型為 VGGNet 做 multi-pass 的實驗
- Baseline 的 test error 為 6.34% 和 26.74%。
- "Trained" 那欄代表模型已經經過稀疏訓練。
- "Fine-tuned" 那欄代表已做 Channel 修剪並且微調過模型的錯誤率。
- "Params Pruned" 和 "FLOP Pruned" 代表該行 Fine-tuned 與下一行的 Traind 模型的修剪比率。
:::
- 上表顯示了每次迭代修剪的測試誤差,隨著修剪過程可以獲得越來越緊湊的模型。
- CIFAR-10 迭代 5 次可以獲得 20 倍的參數減少和五倍的 FLOP 減少,同時仍然可以實現較低的誤差。
- CIFAR-100 則大概在迭代三次後錯誤就開始提升,可能是由於他的類別較多,因此過於積極的刪除 Channel 可能會有不可避免的傷害,但仍然可以修剪接近 90% 的參數和 70% 的 FLOP。
## Analysis
這段主要分析兩個超參數,剪枝的比例 $t$ 與稀疏正規項 $\lambda$,看看他們整體在模型上的影響力。
### Effect of Pruned Percentage

:::info
:bulb: 對於 Channel 剪枝比例的影響。
- 實驗模型為 DenseNet-40
- 資料集為 CIFAR-10
- $\lambda=10^{-5}$
:::
- 從上圖可看出若修剪比例過高,錯誤率會突然提升,微調模型可以稍微補償修剪所造成的 Precision 損失。
- 僅當閾值超過 80% 的時候為微調模型的誤差才會跟 Baseline 模型差不多。
- 當經過稀疏訓練時,即使沒有進行微調,該模型也會比原始模型好,這可能是因為 L1 稀疏性對 Channel 縮放因子正規化的關係所致。
### Channel Sparsity Regularization

:::info
:bulb: 以不同數值的 $\lambda$ 在 VGGNet 上訓練的縮放因子分佈結果。
- 隨著增加 $\lambda$ 數值,縮放因子變得更稀疏。
:::
- 由上圖可看出隨著 $\lambda$ 增加,縮放因子越來越集中在 0 的附近。
- 當 $\lambda=0$ (即沒有稀疏正規化) 分佈相對平坦。
- 當 $\lambda=10^{-4}$ 幾乎所有縮放因子都集中在 0 附近。

:::info
:bulb: 縮放因子在訓練過程中變化的可視化熱力圖。
- 取自 CIFAR-10 上 VGGNet 的第 11 個 Conv-layer。
- 顏色越亮值越大,亮線表示 "selected" 的 Channel,暗線表示可以修剪的 Channel。
:::
- 上圖可看出儘管一開始每個 Channel 的以相等的權重開始,但隨著訓練進行,某些 Channel 的縮放比例會變大,而其他則會變小。