本篇是 Regularization的第二篇,講得是DATA Augmentation。是一個非常常見的技巧!
Data Augmentation是一個非常常用的技巧,大致上就是利用一些Computer Vision的技巧,對影像進行小幅度的修改,確保修改後的影像仍能具有原先希望辨別的特徵,以期望模型即使在圖片加入這些變化間,仍能具有判別影像特徵的能力。
具體實例可以參考albumentation函式庫中的展示圖:
大致上的重點便是同一張圖經過變化以後,還是要能看得出他是一隻鸚鵡(試想,如果連你都看不太懂了,要什麼都不會的模型學習是不是太強"模"所難了呢?),而我們同時也可使用不同的處理方法來疊合,創造出千變萬化的圖片出來讓模型學習!
這個方法同時也非常常見於資料量不大的專案中。但別忘了他的本質仍是一種Regularization,實際上資料量不大的模型訓練中,效果不好的結果,主要的問題是來自於小型的訓練集無法代表整體樣本,因此收斂於小樣本的模型,自然無法適應到整個宏觀世界。此時Data Augmentation的介入,便是盡可能的透過讓資料更接近整個宏觀世界的方式,來去增加模型訓練時收斂的難度,進而去讓模型能有更好的generalization error。
但這東西卻也不是加越多越好,它一樣是個需要tune的超參數組。常見的謬誤有做了過多不合理的變化,使得訓練資料變得已經有點過度扭曲,已經脫離宏觀世界的長相時(宏觀世界的借鑒則是驗證集及測試集),類似像下面這張圖(來源),有一張貓貓的頭已經完全被切掉了,這種難以辨識的東西如果一兩百張有1-2張還沒什麼關係,但太多可就不好了,所以實際也要注意一下。
另外補充一下,還有一個借鑒則是Data Augmentation也要符合資料與domain的知識。例如醫療影像中,即使是不同的人,人體骨頭的生理結構不會差異太大,不宜做過度的扭曲,如果跑出個斜的頭骨那還真不知道該如何是好?
這邊推薦幾個我個人比較常用的函式庫:
另外如果要把非monai的Augmentation整合起來一起使用的話,可以善用monai.transforms.Lambdad。
實作基本上不難,基本上一樣是準備一組monai.transforms
def prepare_data_aug(CONFIG: Dict) -> monai.transforms.transform:
prob = CONFIG['train']['data_aug']['prob']
transforms_data_aug = [
monai.transforms.RandAffined(keys = ['img'],
prob=prob,
rotate_range = [-0.1, 0.1],
translate_range = [-3, 3],
scale_range = 0.1),
monai.transforms.RandGaussianNoised(keys = ['img'],
prob=prob,
mean=0.0, std=0.1),
monai.transforms.RandFlipd(keys = ['img'],
prob=prob,
spatial_axis = [0])]
transforms_data_aug = monai.transforms.Compose(transforms_data_aug)
return transforms_data_aug
然後在做成dataloader前,套上dataset就可以了!
transforms_data_aug = prepare_data_aug(CONFIG)
processed_datasets['TRAIN'] = monai.data.Dataset(data = processed_datasets['TRAIN'],
transform = transforms_data_aug)
然後我們可以試跑看看,一張圖片可能有的變化性:
一樣參考這個commit訓練,讓我們直接看結果:
增加了一點幅度的訓練難度,一開始上升的比較少一些。但並沒有脫離宏觀世界太多,一樣是獲得了差不多0.76左右的auroc結果!