Octave Convolution
這是一篇論文的閱讀筆記,並且嘗試以公開資料集作實驗心得。內文源引自 Yunpeng Chen, Haoqi Fan, Bing Xu, Zhicheng Yan, Yannis Kalantidis, Marcus Rohrbach, Shuicheng Yan, Jiashi Feng. “Drop an Octave: Reducing Spatial Redundancy in Convolutional Neural Networks with Octave Convolution”. In ICCV, 2019.
論文連結:https://arxiv.org/abs/1904.05049
Github (Facebook Research):https://github.com/facebookresearch/OctConv
1. 簡介
此篇論文提出一種名為 Octave Convolution (OctConv) 的卷積運算,針對 feature maps 進行高低頻率的分離,並以更小的空間解析度 (lower spatial resolution) 處理低頻率部分,達到更少的運算成本。
另一方面,此種新形態卷積運算可直接融入既有的模型架構,將原本Convolution 的部分全部取代為 Octave Convolution,並藉由可調整的參數α,完成對於 FLOPs 和 Accuracy 之間的取捨。
基於論文中的理念與實驗數據,本文最後將以 “AF Classification from a Short Single Lead ECG Recording — The PhysioNet Computing in Cardiology Challenge 2017” 的資料集,以同樣的模型架構和訓練方式,進行 Vanilla Convolution 與 Octave Convolution 的對照實驗與檢視。
2. 概念與動機
一張照片若從頻率的觀點,『高頻率部分描述著畫面中變化比較劇烈的部分,意味著可呈現出較具體的細節』;反之,『低頻率部分則描述著畫面中變化比較平緩的部分,呈現出較模糊但具備全域輪廓的特徵』。論文中針對此特性給出了示意圖 ,如下:
依據這個特性,論文中進一步把卷積層的特徵輸出圖 (The output maps of a convolution layer) 視為可分解的圖層,將其分成高頻率與低頻率的空間解析度。
另一方面,雖然卷積神經網路 (Convolutional Neural Networks, CNNs) 相較於 Dense model 使用更少的模型參數,以及使用更少的特徵輸出圖之通道維度 (channel dimension of feature maps)。但是,在空間維度 (spatial dimension) 上其實也有可精簡的部分。
因此,論文中結合空間解析度分群的特性和精簡空間維度的想法,提出將輸入影像分解成高頻率與低頻率兩群後,接著可經由與臨近區域共享資訊來縮減低頻率部分的空間維度。論文中的示意圖如下:
之所以可以針對低頻率部分進行縮減,原因在於前面提過『低頻率部分則描述著畫面中變化比較平緩的部分,呈現出較模糊但具備全域輪廓的特徵』,因此,並不需要以同樣的空間維度來儲存低頻率資訊,進一步提升運算效率。
3. 定義與方法
3-1. Octave
“Octave” 一詞原本跟音樂中的八度有關,代表著頻率加倍。而在這篇論文中,『定義 “Octave” 為空間維度除以 2 的冪次方』。以下的內容皆只以 2¹ 進行處理的情況下,意即低頻率部分的空間維度只有高頻率部分的一半。
3–2. Octave Convolution
為了進一步理解 Octave Convolution,本文先對一些符號作說明。
- 可調控參數 α ∈ [0, 1] ,代表著分配給低頻率部分的通道比例 (the ratio of channels allocated to the low-frequency part)。
- X 為每一次卷積層的輸入特徵張量 (input feature tensor of a convolutional layer),而 Y 則為每一次卷積層的輸出張量 (output tensor of a convolutional layer)。
根據上面兩個列點+兩張圖片的說明後,論文中提供了 Octave Convolution 公式的示意圖,如下所示:
從 Octave Convolution 公式與流程圖中,我們可以看到一些細節:
- 若 α_in = 0,意味著輸入特徵張量 X 不會分解成高低頻率兩群;反之,若 α_out = 0,意味著輸出特徵張量 Y 也不會分解成高低頻率兩群。因此,若 α_in = α_out = 0,Octave Convolution 等同於 Vanilla Convolution。
- 若 α_in 和 α_out 都不等於 0,對於每一個 Octave Convolution,輸入分別為 XH 與 XL,而輸出則是 YH 和 YL。
- 不論輸入或輸出張量,對於每一個 Octave Convolution,低頻率部分空間維度 (h/2, w/2) 是高頻率部分空間維度的兩倍 (h, w)。因為論文中設定除以 2 來當作一次 Octave operation。
- Octave Convolution 保有高低頻率資訊互相交流的特性,也就是流程圖中 YH 與 YL 分別由高低頻率組合而成 (綠箭頭路徑+紅箭頭路徑)。 其中,低頻率部分要轉換至高頻率時,需要經過 Up-sampling;而高頻率部分要轉換至低頻率時,則需要經過 Average-Pooling。
實際上,對於整個流程來說,最原始只有輸入資料 X,最終只有輸出張量 Y。意味著實踐在整個模型架構中,若想要完美替代原本模型架構中的 Convolutional Layers,第一個 Octave Convolutional Layer 必須能處理 1 個輸入張量 X,並輸出 2 個張量 YH 和 YL;中間過程的 Octave Convolutional Layers 則與流程圖中相同,處理 2 個輸入張量 XH 和 XL,並輸出 2 個張量 YH 和 YL;最後一個 Octave Convolutional Layer 必須處理2 個輸入張量 XH 和 XL,並輸出 1個張量 Y。
為了達成上述過程,因此,論文中直接設定『第一個 Octave Convolutional Layer 的 α_in = 0,α_out = α』、『中間過程的 Octave Convolutional Layers 的 α_in = α_out = α』、『最後一個 Octave Convolutional Layer 的 α_in = α,α_out = 0』。
3–3. Implementation Details
這一部分將延續 3–2. Octave Convolution 的內容,本文以 tf.keras 為基礎,進一步描述本次實作 Octave Convolution 的方法。若想看官方的內容,也可以參考本文最上面的 Facebook Research Github。
- 對於第一個 Octave Convolutional Layer,選定一個 α ∈ [0, 1],則
α_in = 0 且 α_out = α
# of H_L filter = α * Total filter
# of H_H filter = (1 — α) * Total filter
- 對於中間過程的 Octave Convolutional Layers,選定一個 α ∈ [0, 1],則α_in = α_out = α
# of L_L filter = # of H_L filter =α * Total filter
# of H_H filter = # of L_H filter =(1 — α) * Total filter
- 對於最後一個 Octave Convolutional Layer,選定一個 α ∈ [0, 1],則
α_in = α 且 α_out = 0
如果讀者嘗試以 tf.keras 來實作的話,可以 functional API 進行,而會運用到的 layer 也都已呈現在圖中,不妨可以試試看。另一方面,實際要運用在既有的 CNN-based model 時,就請根據相對應的 Convolutional Layer 直接進行替換即可。
不過,有一點需要注意的是 UpSampling2D() 這個 layer:
由於有時候會遇到某些維度長度為『奇數』的目標張量 (tensor),這時候使用若 tf.keras.layers.UpSampling2D(),可能會在下一步驟 tf.keras.layers.Add() 遇到長度不匹配的錯誤,因此建議改以 tf.image 裏面 resize 相關的 function 來實做,直接指定目標維度。
4. 實驗與評估
4–1. Relative Theoretical Gains of OctConv
論文中以 Octave feature representation 和 regular feature representation 做比較,並提出理論上,Octave Convolution 在 memory cost 上的效益為『1–(3/4) * α』,同時在 computation cost 上的效益為『 1- (3/4) * α * (2- α)』
。
4–2. Ablation Study on ImageNet
論文為了驗證 Octave Convolution 的實用性,並實際釐清運用 OctConv 的模型在 FLOPs 與 Accuracy 的權衡取捨,實際上針對許多模型做過評估,本文只截取 ImageNet 上面的實驗結果,其他實驗與細節可閱讀論文中的第四章節。
根據論文中給出來的實驗結果,可以看出隨著 α 上升,FLOPs 逐漸下降。『考量到 FLOPs 與 Accuracy 的權衡取捨下,多數模型在 α = 0.125 或 α = 0.25 時有最佳權衡表現』。
另一方面,由於論文中宣稱 Octave Convolution 可以增加接受域 (receptive field),有利於偵測畫面中的大型物件。因此,也有對 ImageNet 測試集影像的大小變化做實驗,如下圖所示:
4–3. 本文自行實做與評估
經過論文的重點介紹與 Octave Convolution 實做的說明,本文嘗試以 “AF Classification from a Short Single Lead ECG Recording — The PhysioNet Computing in Cardiology Challenge 2017” 的資料集,以同樣的模型架構和訓練方式,進行 Vanilla Convolution 與 Octave Convolution 的對照實驗與檢視。
關於此次實驗的公開資料集,總共有 8528 筆 single lead ECG recordings,取樣率為 300 Hz,每一筆對應一種心律分類,分別是 Normal rhythm (N), AF rhythm (A), Other rhythm (O) and Noisy (~) recordings。因此,可把這次的任務視為一維時序的分類問題。公開資料集的詳情如下圖所示:
其中每一筆心電圖記錄在時域 (Time domain) 與頻域 (Frequency domain) 的範例,以及轉換成頻譜圖 (spectrogram) 後的情形,將呈現如下圖:
這次實驗將公開資料集事先切分出測試資料集後,對剩下的部分進行 5-folds cross validation。所有 Evaluation 和 Efficiency 的評估皆以測試資料集為主:
本文實做的 Octave Convolution 確實可以直接套用在既有的 CNN-based model。經過一番實驗後,有一些發現:
- 以本文的實做方法而言,『α 太小時會報錯,因此無法進一步驗證 α = 0 時是否與 Vanilla model 的模型結構是否相同』。因此,以下幾點在討論模型訓練成果、模型參數量、模型訓練所需時間時,會分開說明。
- 以本文的實做方法與測試資料集來說, 『Octave model 的訓練成果並沒有超過 Vanilla model』。
- 若只比較 Octave model 在不同 α 的情況下,得到和論文一樣的權衡情況,也就是當『α = 0.125 或 α = 0.25 時會有最好的訓練成果』。
- 以本文的實做方法與測試資料集而言,『除了 Vanilla model 外,確實如同論文中的描述,不論 α 如何變化,並不會影響 Octave model 的模型總參數量與可訓練參數量』。
- 以本文的實做方法與測試資料集而言,『除了 Vanilla model 外,確實會隨著 α 上升,Octave model 的訓練所需時間逐漸減少』。當 α = 1 時,所需時間比 Vanilla model 減少 42% ~ 50%,或比 α = 0.125 時減少 52% ~ 60%,與理論上的 75% 有一些差距。
5. 結論
本文最後以兩個面向來闡述關於 Octave Convolution 的結論,分別是論文所述與個人實驗。
以論文所述,主要提到的結論如下:
- Octave Convolution Operation 可分別儲存與處理高低頻率的資訊,進而改善模型效率。
- Octave Convolution Operation 可讓高低頻率的資訊交互作用,加上更大的接受域,進而提升畫面中的物件辨識能力。此項特性對於淺層神經網路 (shallow networks, e.g. ResNet-26) 有限的接受域特別有幫助。
- Octave Convolution Operation 可直接融入既有的 CNNs 中使用,並不影響模型架構。
- 考量到模型表現與模型效率的權衡取捨下,文中的實驗結果顯示,
當 α = 0.125 或 α = 0.25 時會有最好的訓練成果。 - Octave Convolution Operation 的 α ∈ [0, 1],可自由選擇。當 α = 0 時等同於 Vanilla Octave Convolution。
另一方面,以本文的個人實驗來說,主要的發現與結論如下:
- 參考論文所述的流程和 Facebook Research Github 內容後,嘗試實做的 Octave Convolution 確實可以分別儲存與處理高低頻率的資訊,以及讓讓高低頻率的資訊交互作用。
- 實做的程式是奠基於 Tensorflow 2.0 下的 tf.keras。但是目前並未如同文中宣稱,可自由讓 α ∈ [0, 1]。實際上,α = 0 時會報錯,導致無法完整驗證是否等同於 Vanilla Convolution。
- 除了 α = 0 以外,其他 α 下的模型總參數量與可訓練參數量確實皆相同。但是,跟一般的 Conv2D() 實做的模型相比,其實模型總參數量與可訓練參數量皆變少一些。
- 除了 α = 0 以外,其他 α 下的訓練所需時間,確實隨著 α 提升而縮減。但是,跟一般的 Conv2D() 實做的模型相比,當 α ≤ 0.5 時,Octave Convolution 訓練所需時間比一般的模型多,直到 α > 0.5 後才有更佳的效率。
- 除了 α = 0 以外,其他 α 下的模型分類表現確實是在 α = 0.125 或 α = 0.25 時會有最好。但是但是,跟一般的 Conv2D() 實做的模型相比,其實模型分類表現仍未超越。
除了上述兩個方面的結論與發現外,事實上,本文這次的實驗過程是將一維時序透過短時距傅立葉變換 (Short-time Fourier Transform) 轉成頻譜圖,每一筆資料的維度皆從 (9000, ) 轉成 (280, 33, 1),然後再以 Conv2D 的基調處理。
理想上,其實應該將同樣的概念套用至 Conv1D,直接嘗試以原始一維時序進行 CNNs 建模處理與實驗比較,可以避免事先人工資料轉換的選取問題。
終於寫完這篇實做心得,以上解說到此,希望有幫助到想了解 Octave Convolution 的朋友們。若有其他的想法或問題,歡迎指教與討論,也可透過 Email 洽詢,謝謝。