ML_LEE_2022_hw4
可進行的目標
- Medium : 0.70375 (train 1~1.5 hr)
- Strong : 0.77750 (train 3~4 hr)
- Boss : 0.86500 (train 2~2.5 hr )
調整transformer參數與pred_layer模型
- 包括降低multi-head數量、feedforward dropout rate等等
- 降低pred-layer的linear connect layer層數 (這個問題複雜度不高,線性聯階層不用到兩層)
實作conformer
- 把原本的
self.encoder_layer
改掉,套用conformer模型 - conformer來源
- 記得修改Classifier的forward
更動transformer/comformer encode層數
- 原本只有一層(就是
self.encoder_layer
),可以改成呼叫self.encoder
並修改Classifier的forward
寫作業歷程
2022/7/22
這次作業transformer(self-attention)在NLP與語音辨識領域運用廣泛,是我想要好好學好的章節,不過這次作業給我挫敗感很大…
這份作業寫一整天,白天的時候在查comformer的paper,但是因為對於transformer的觀念也不甚熟悉,所以照著李宏毅老師給的reference查到了這篇paper(中文心得版),在大略的瞭解了transformer家族以後,最後回去看了一下別人看「Attention is all you need」的心得,對照上課的筆記這才更有了概念
到了晚上終於要開始著手改code,首先在torchaudio document查到了他支援的conformer model API,開始套用以後才開始發現他的問題:看似簡單的forward修改其實困難重重!
首先是最基礎的問題,因為是pytorch菜雞,我甚至連forward的意涵是什麼都不知道,後來查到原來他是__call__會呼叫的函數,通常進行一個step(單位為一batch)的計算,而這份code在訓練時會呼叫model_fn
model_fn用意在於
- 先做mels與labels的分類
- 把資料放到GPU上
- 呼叫model.forward()
以及計算loss
- 最後進行predict以後算出該step之acc
搞懂了forward以後,開始著手修改forward內部的code使他貼合conformer,但因為這樣所以我也必須去查torchaudio.models.Conformer這個class裡面的forward會怎麼運作(巢狀模型),查到的資料如下:
註解寫到lengths with shape(B,),因此我很直觀的直接打了
1 | # out: (batch size, length, d_model) |
這麼做跳了一個錯誤:他抓不到out[0]
的shape,我這才發現他要的是torch.Tensor type,於是我改成
1 | self.encoder(out, torch.tensor(out[0],) ) |
仔細研究torch.tensor用法以後終於可以正確地塞tensor進去,但是我卻鬼打牆的一直卡在lengths這個參數的shape不對,從錯誤碼發現跟ket_padding_mask有關,幾經波折以後看到這篇才發現他要吃的參數是(batch size,sequence length),最後修正成了這樣
1 | out = self.encoder(out,torch.tensor([out[0],out[1]])) |
卻碰到了新的錯誤碼:
留待明天處理…
2022/7/23
果然是昨天腦袋昏到不好思考,把out.size(0)跟out[0].size()搞混,雖說後來修正了,但還是套不進去。對於tensor dim的掌握力太差了…
後來改用這個conformer來實作,多了很多我不知道幹嘛用的參數,而且看似不能增加layer數orz…,先求能跑吧,感覺達不到strong base line了,參數如下
1 | self.encoder_layer = ConformerBlock( |
要注意的是他的forward吃的參數是(length, batch size, d_model)
,所以permute那行註解要拿掉,這方面沒有統一真的很煩人,最後Classifier forward code如下:
1 | def forward(self, mels): |
中間有個out = self.encoder_layer(out)
被註解了,我原本是想說既然參數不能設定layer數,那就讓他跑兩次也可以是兩輪,不過我想太美了,因為GPU多線程的關係,讓整個tqdm的log大暴走,正確性也打個問號,搞不好會碰到race condition…,因為這是這個模型設計者沒設計到的部分(或是我菜到沒發現QQ),所以最後決定讓他就單層去跑
作業結果
Train了70000 step (大約1 hr),跟strong差一點點,但acc還在上升,感覺是練不夠久
補了以下的code讓他繼續撿剛剛的模型train
1 | if exists("./model.ckpt"): |
得到命中率=79%
但提交的時候卻出了大問題,測試的結果非常差
有查到一篇心得(下圖)也是成績暴跌,推測測試集跟訓練集的分布差很多(不過那篇作者是碰到切割長度的問題,這我沒有改不該有影響才對),這份作業做到這吧,沒力氣修正了orz,再修也會淪為調參之流,感覺學不到甚麼。
結論姑且下在data mismatch,不過模型參數與notebook我會保留在github,將來靈光乍現的時候再來看看
Report
因為卡住所以我有多看幾個varient
- linformer : 藉由attention matrix在做sorftmax轉化以後非行滿秩的特性,降低attention matrix的維度,使得transformer的複雜度可以降到線姓
- Sparse Attention (FP/LP) : 因為傳統transformer的複雜度過高,所以藉由讓self-attention關注的範圍由全局變成局部性,降低計算時間。FP(fixed patterns)是固定self-attention窗口大小,LP則是把它的大小變成一個可學習的參數
- linformer : 藉由attention matrix在做sorftmax轉化以後非行滿秩的特性,降低attention matrix的維度,使得transformer的複雜度可以降到線姓
因為transformer雖然可以考慮sequence的全局性,但對於自己的重視程度較為有限,而CNN則可以對局部性的特徵著重關注,兩者混合起來可以達到互補提高準確性的效果。