2021 年 7 月,我參加了 Tomofun 狗音辨識 AI 百萬挑戰賽 ,主題是運用機器學習來辨識居家環境中的聲音,我最終取得了第 10 名的成績。這則筆記裡,我將為各位簡短說明如何用深度學習進行音訊辨識,並且介紹我所研讀的論文中,運用了哪些技巧幫助我提高音訊辨識準確度。老實說,這次競賽我用到的技巧,相當簡單、但是有效!
本次競賽的 PyTorch 以及 Flask 程式碼,我也全都分享在 我的 GitHub。
目錄
競賽介紹
Tomofun 狗音辨識 AI 百萬挑戰賽 的主題是音訊辨識,參賽者須開發機器學習演算法,辨識 5 秒長度的音訊 wav 檔案屬於 10 種類別的哪一種。競賽的音訊都是居家常見的環境聲音,包括狗叫聲、玻璃破碎的聲音、人的大叫聲等等。主辦單位 Tomofun 希望透過演算法自動辨識音訊,當家裡的裝置聽見意外狀況的時候,可以第一時間用 APP 通知出門在外的屋主。
本次競賽方式模擬機器學習模型實際上線使用的狀況,主辦單位會用 HTTP Request(POST)發送音訊 wav 檔案,模型要能夠接收資料並即時回傳預測結果。因此,至少需要在雲端伺服器部署模型、做到基本的 MLOps 才能進行比賽。
(以上簡介是決賽內容,關於初賽內容請見 官方說明)
隊伍成績
- 隊伍名稱:StarRingChild
- 隊員:只有我自己 😛
- 名次:第 10 名 / 共 301 組隊伍 (Top 3%)
- AUC:0.934
簡短複習:怎麼做音訊辨識
此競賽的核心當然就是音訊辨識的方法,說明競賽技巧之前,先在這小節幫不太熟悉音訊辨識的讀者簡短複習。
首先,要讓電腦「看」懂聲音,有許多種不同的音訊表示方式,包括 Waveform、Spectrogram、及 MFCC 等等。其中,Spectrogram 與機器學習結合,在研究與實務中通常都有最佳的成效。
Spectrogram 中文名稱是時頻譜,是呈現聲波的各頻率成分隨時間變化的熱圖(Heatmap),橫軸是時間長度、縱軸是頻率分佈,每個資料點(熱圖的顏色)是能量大小。
而 Spectrogram 的資料表示,是二維的陣列,如下方的 librosa 範例程式 所表示:
>>> y, sr = librosa.load(librosa.ex('trumpet'))
>>> librosa.feature.melspectrogram(y=y, sr=sr)
array([[3.837e-06, 1.451e-06, ..., 8.352e-14, 1.296e-11],
[2.213e-05, 7.866e-06, ..., 8.532e-14, 1.329e-11],
...,
[1.115e-05, 5.192e-06, ..., 3.675e-08, 2.470e-08],
[6.473e-07, 4.402e-07, ..., 1.794e-08, 2.908e-08]],
dtype=float32)
只要在音訊轉換成 Spectrogram 之前,將所有音訊裁切成相同時間長度,這些音訊檔案,資料表示會是多個長寬大小一致的二維陣列、就像是多個相同大小的圖片一樣。對於這類型的「圖片」資料,我們下一步可以用稍微摸過深度學習的人都熟悉的 CNN 模型(卷積神經網路)來分析。
關於音訊分析的更多知識,筆者好豪推薦閱讀台大張智星教授的 音訊處理課程教材;如果是對 CNN 模型還不熟的讀者,可以參考 Udacity 的免費深度學習課程。
競賽解題方法摘要
筆者本次參賽使用的方法,全都是參考這篇 2020 年的論文 Rethinking CNN Models for Audio Classification,因此,以下介紹的競賽方法,幾乎都是論文內容的摘要,也是筆者好豪在競賽過程實驗後、確實對預測準度有幫助的方法。
多通道的 Spectrogram 轉換
通常,Spectrogram 的取得方式是將聲音訊號依照時間切分成多個相同時間長度的小段落,並且對每個小段落(Window)進行 傅立葉轉換、算出不同頻率的能量分佈。這個過程稱為 短時距傅立葉變換(STFT)。
STFT 的其中一個缺點是 Time-Frequency Trade-off:
- 對於同一個小段落,傅立葉轉換後看不出頻率的能量實際上發生在哪個時點
- 如果切分的段落長度太長,時間解析度就較低
- 訊號波長如果超過小段落的時間長度,傅立葉轉換就完全無法捕捉到
- 如果切分的段落長度太短,頻率解析度就較低
取決於小段落時間長度(Window Size),傅立葉轉換後得到的時間與頻率解析度會互相權衡(一方高則另一方低)。所以問題來了:
計算 Spectrogram 時,究竟 Window Size 要設為多大才對深度學習模型最有幫助呢?
論文中採用的方法是:「我全都要!」
論文作者選了三種 Window Size,對於同一個音訊檔案、分別產生三張 Spectrogram,這三張「疊」起來之後,就變成了有三個通道(Channel)的三維圖片。
我們也可以這樣想像:
- 原本只用單一種 Window Size、產生的 Spectrogram 圖片只有單一通道,陣列形狀等同於灰階圖片
- 使用三種 Window Size、產生的三個 Spectrogram 疊合圖片共有三個通道,陣列形狀等同於 RGB 圖片
同時納入不同的 Window Size,讓深度學習網路可以在每個通道都獲得不同解析度層級的時間以及頻率資訊,有更好的音訊辨識成效。
DenseNet 與 Feature Reuse
論文中的實驗包含了三個影像分析常用的模型 ResNet、Inception、以及 DenseNet,比較它們在音訊辨識任務的表現,實驗結果是 DenseNet 表現最好。而筆者好豪自己在競賽的實驗中,結果也同樣是 DenseNet 的 Cross-Validation 預測準確度最佳。
我認為 DenseNet 表現優於其他兩者的理由是此模型的 Feature Reuse 特色,在每一個多層卷積層組成的模型塊(Dense Block)中,任一層都會直接取得之前所有層產生的特徵(見下圖),換言之,深層網路也可以看到所有淺層網路所看到的內容、淺層網路的特徵被一再重複使用(Reuse)。
淺層卷積層學到的特徵,主要是影像的「幾何形狀」,像是邊緣、弧線、角落等等;而越深層的卷積層越才看得出圖形的「整體」,例如眼睛、臉型、山脈等等。
DenseNet 在音訊辨識任務表現特別好,或許是因為淺層卷積層所學的「原始」影像特徵,對於聲音訊號已經有夠好的表達能力,因此這些淺層特徵,已經足以增強預測、值得一再被深層的網路重複使用。當然,這只是筆者的假設,為何 DenseNet 的音訊辨識效果較好,有待進一步研究。
「看」過貓咪的模型,更能「聽」懂貓叫聲?
ImageNet 是電腦視覺領域相當火紅的影像資料集,擁有超過 1,400 萬張圖片,當中有超過 2 萬種類別。許多影像辨識 CNN 模型,在發表研究的同時,也會開源以 ImageNet 資料集預訓練過的模型,使用者不需要自己搜集圖片資料、也不用花時間訓練龐大的模型,直接用預訓練過的模型就能有很好的分類效果。
開源的 ImageNet 預訓練 CNN 模型,大多使用其中 1,000 種類別,包括桌子、貓、狗、香蕉等等,能辨識的類別相當多樣。然而,我們需要問的是,這些物件類別與我們現在要分析的聲音訊號 Spectrogram 顯然很不一樣,ImageNet 預訓練的 CNN 模型還能對音訊分析有幫助嗎?
這就是 這篇論文 實驗驗證過、並且筆者在競賽中運用的有趣之處:
ImageNet 預訓練的 CNN 模型能夠辨識貓咪的樣貌,經過 遷移學習 之後,還能更高準確度地辨識出貓叫聲
在論文的實驗中,ImageNet 預訓練的 CNN 模型,不論是 ResNet、Inception、或 DenseNet,在音訊辨識任務上,與隨機初始化的模型相比,準確度都更高,並且有不小的成效差異。
論文作者使用更多樣的遷移學習設計來驗證結果。一般的遷移學習,ImageNet 預訓練所得到的模型是用來初始化參數,模型得到新的 Spectrogram 資料後,所有參數都會繼續更新。論文中其中一項遷移學習的實驗,只讓部分的 CNN 模型使用 ImageNet 預訓練參數初始化、其餘模型隨機初始化,目的是要比較「只有淺層模型預訓練參數」以及「深層模型也預訓練參數」是否有成效差別。DenseNet 的實驗結果如下圖:
我們可以延續上個小節在 DenseNet 的討論來理解這項結果。DenseNet 用 ImageNet 圖片資料集訓練之後,擅長的任務是辨識肉眼可見的特徵,並且,深與淺層的卷積層學會的特徵類型不同、對音訊辨識遷移學習有幫助的程度也不同。我們可以直觀地想像:較深層的模型即使擅長辨識「貓咪的臉型」,這類特徵對於訊號分析顯然沒什麼意義吧!
而淺層模型的卷積層學會辨識的,大多是幾何「形狀」,這些「形狀」對於模型學習辨認音訊仍有幫助。例如,卷積層辨識出斜線,在 Spectrogram 上可能代表頻率隨著時間變高或變低。
實際上,筆者好豪在競賽中,並沒有像論文實驗這麼精細。我直接讓 DenseNet 模型的所有卷積層都用 ImageNet 預訓練參數初始化,只有最終的分類層(全連接層)是隨機初始化。方法十分簡單,也獲得了不錯的預測準確度。
我的賽後反省:MLOps
這次的競賽方式,是主辦單位用 HTTP Request 發出音訊檔案,參賽者接收檔案、用機器學習模型辨識結果後回傳,此決賽過程為 2 小時、共有 3,600 個音訊檔案。由於決賽期間傳來的音訊檔案不少,主辦單位建議大家在比賽期間手動標註資料、並且即時用新資料更新模型(Incremental Learning)。
由於對 MLOps 不夠熟悉,我個人並沒有即時更新模型,只用 Flask 架設基本的 API 就上場比賽。然而,比賽之後,評審之一的 李宏毅教授 對沒有做好 Incremental Learning 的參賽者,提出了警訊:
如果在某段時間內,模型接收到的都是非常不平衡的資料,那麼有無即時更新模型會是決定性的差異
在這次競賽中雖然沒有發生教授所說的非常不平衡資料狀況,我認為在推薦系統場景,這個問題格外重要。某篇文章或某部影片,要爆紅、病毒式傳播,很可能只發生在幾分鐘內,如果模型沒有做好 Incremental Learning,就沒有辦法即時推薦給用戶符合他興趣的最新潮玩意兒,沒有做到「捕捉流行趨勢」就不是夠好的推薦系統了。
結語
其實 Rethinking CNN Models for Audio Classification 論文的做法超簡單,只要理解 Spectrogram 的轉換,其餘的只是常見的 CNN 模型遷移學習。但是,我還是從這篇論文學到了很多實驗方法,包括了資料前處理的多通道設計、以及部分與完整模型預訓練成效差異比較等等。
這篇文章所提及的競賽 PyTorch 及 Flask 程式碼,我都分享在 好豪的 GitHub,歡迎大家一起玩玩看。(延伸閱讀:Python Flask 的 Udemy 線上課程心得)
主辦單位 Tomofun 也佛心地在 YouTube 分享競賽得獎者的作法分享以及賽後講評,有興趣的讀者快上去看看吧。
如果你對影像辨識相關的機器學習競賽有興趣,推薦你繼續閱讀以下幾篇文章:
- 2021 年玉山銀行中文手寫影像辨識競賽作法分享,以及手寫文字圖片合成基本教學
- 2021 年 AIdea 機器學習競賽,動態足壓影像辨識,Top 5% 作法分享
- Data Augmentation 教學:Image + Keypoints 同步資料增強
- 最讚的 PyTorch 免費初學課程,由臉書 AI 團隊教學! — Udacity 課程心得
喜歡這篇文章的話,歡迎點選下方按鈕分享或者收進書籤;也歡迎追蹤 好豪的 Facebook 粉絲專頁,我會持續和你分享資料科學相關的新知識。