深度學習的多個loss如何平衡 & 有哪些「魔改」損失函數,曾經拯救了你的深度學習模型?

2021-02-13 機器學習算法那些事

這篇文章整理自我的知乎回答(id: Hanson),分別對深度學習中的多個loss如何平衡 以及 有哪些「魔改」損失函數,曾經拯救了你的深度學習模型 這兩個問題進行了解答。

1. 深度學習的多個loss如何平衡?1.1 mtcnn

對於多任務學習而言,它每一組loss之間的數量級和學習難度並不一樣,尋找平衡點是個很難的事情。我舉兩個我在實際應用中碰到的問題。第一個是多任務學習算法MTCNN,這算是人臉檢測領域最經典的算法之一,被各家廠商魔改,其性能也是很不錯的,也有很多版本的開源實現(如果不了解的話,請看:https://blog.csdn.net/qq_36782182/article/details/83624357)。但是我在測試各種實現的過程中,發現竟然沒有一套實現是超越了原版的(https://github.com/kpzhang93/MTCNN_face_detection_alignment)。下圖中是不同版本的實現,打了碼的是我復現的結果。

不同版本mtcnn在FDDB上roc曲線

這是一件很困擾的事情,參數、網絡結構大家設置都大差不差。但效果確實是迥異。

clsloss表示置信度score的loss,boxloss表示預測框位置box的loss,landmarksloss表示關鍵點位置landmarks的loss。

那麼,,這幾個權值,究竟應該設置為什麼樣的才能得到一個不錯的結果呢?

其實有個比較不錯的主意,就是只保留必要的那兩組權值,把另外一組設置為0,比如 。為什麼這麼做?第一是因為關鍵點的回歸在人臉檢測過程中不是必要的,去了這部分依舊沒什麼大問題,也只有在這個假設的前提下才能進行接下來的實驗。

就比如這個MTCNN中的ONet,它回歸了包括score、bbox、landmarks,我在用pytorch復現的時候,出現一些有意思的情況,就是將landmarks這條任務凍結後(即 ),發現ONet的性能得到了巨大的提升。能超越原始版本的性能。

但是加上landmarks任務後( )就會對cls_loss造成影響,這就是一個矛盾的現象。而且和a、b、c對應的大小有很大關係。當設置成( 係數全1 )的時候關鍵點的精度真的是慘不忍睹,幾乎沒法用。當設置成(  a/b/c=1/10/100)的時候,loss到了同樣一個數量級,landmarks的精度確實是上去了,但是score卻不怎麼讓人滿意。如果產生了這種現象,就證明了這個網絡結構在設計的時候出現了一些缺陷,需要去修改backbone之後的multi-task分支,讓兩者的相關性儘量減小。或者是ONet就不去做關鍵點,而是選擇單獨的一個網絡去做關鍵點的預測(比如追加一個LNet)。box的回歸併不是特別受關鍵點影響,大部分情況box和landmarks是正向促進的,影響程度可以看做和score是一致的,box的精度即便下降了5%,它還是能框得住目標,因此不用太在意。

上面這個實驗意在說明,要存在就好的loss權重組合,那麼你的網絡結構就必須設計的足夠好。不然你可能還需要通過上述的實驗就驗證你的網絡結構。從多種策略的設計上去解決這種loss不均衡造成的困擾。

和@葉不知(知乎用戶)討論後,有一篇論文也可以提供參考:

https://arxiv.org/abs/1810.04002

1.2 ocr-table-ssd

第二個是我之前做過一點OCR方面的工作,這個是我對於表格框格式化方面做的工作,基本算原創工作。

https://github.com/hanson-young/ocr-table-ssd

改進版本的SSD表格檢測

算法是基於SSD改的,與原有SSD相比增加了一個預測heatmap的分支,算是一種attention機制的表現吧。改進後訓練達到相同的精度和loss,SSD用時10小時,改進後的方法耗時僅需10-20min。在訓練過程中如果兩個分支一起訓練,很難發揮網絡的真正意義,並且收斂到不是很理想的地方,所以訓練過程也挺重要的,在實驗中,將原來的optimizer從SGD(不易收斂,可能和學習率有關)換到RMSProp:

先凍結SSD網絡,然後訓練segmentation分支,到收斂再凍結segmentation分支進行SSD部分的訓練,到收斂原圖預測結果heatmap

因為表格尺度的影響,不加入heatmap分支會導致圖像被過分拉升,導致無法檢測到表格框。

加入heatmap後還有個好處就是為表格的對齊提供了可能。

原圖

如果直接檢測,對於一個矩形框來說,恐怕是會非常吃力的。如果

heatmap -> 閾值分割 -> Sobel -> HoughLineP -> angle

求出表格的傾斜角angle後,可以將原圖和heatmap旋轉統一的angle後concatenation,這樣再接著跑SSD,對齊後的效果比較明顯,解決了傾斜角度過大,帶來bbox框過大的影響,詳細見下圖。

可以求出角度

然後進行對齊工作

對齊後的結果

是不是能好很多。

2. 有哪些「魔改」損失函數,曾經拯救了你的深度學習模型?

我在做缺陷檢測時候對比了一些loss的性能,其實確實是那句話,適合自己的才是最好的。以下我用實際例子來說明這個問題。

2.1 實驗條件

為了實驗方便,我們使用了CrackForest數據集(https://github.com/cuilimeng/CrackForest-dataset)做訓練測試,目的是去將裂紋缺陷分割出來,總共118張圖片,其中訓練樣本94張,測試樣本24張,採用旋轉、隨機縮放、裁剪、圖像亮度增強、隨機翻轉增強操作,保證實驗參數一直,模型均是類Unet網絡,僅僅使用了depthwise卷積結構,進行了如下幾組實驗,並在tensorboard中進行圖像預測狀態的觀測。

CrackForest數據集samples2.2 weighted CrossEntropy

在loss函數的選取時,類似focal loss,常規可以嘗試使用cross_entropy_loss_RCF(https://github.com/meteorshowers/RCF-pytorch/blob/master/functions.py),或者是weighted MSE,因為圖像大部分像素為非缺陷區域,只有少部分像素為缺陷裂痕,這樣可以方便解決樣本分布不均勻的問題

validation
epoch[625] | val_loss: 2708.3965 | precisions: 0.2113 | recalls: 0.9663 | f1_scores: 0.3467
training
2018-11-27 11:53:56 [625-0] | train_loss: 2128.9360 | precisions: 0.2554 | recalls: 0.9223 | f1_scores: 0.4000
2018-11-27 11:54:13 [631-2] | train_loss: 1416.9917 | precisions: 0.2359 | recalls: 0.9541 | f1_scores: 0.3782
2018-11-27 11:54:31 [637-4] | train_loss: 1379.9745 | precisions: 0.1916 | recalls: 0.9591 | f1_scores: 0.3194
2018-11-27 11:54:50 [643-6] | train_loss: 1634.6824 | precisions: 0.3067 | recalls: 0.9636 | f1_scores: 0.4654
2018-11-27 11:55:10 [650-0] | train_loss: 2291.4810 | precisions: 0.2498 | recalls: 0.9317 | f1_scores: 0.3940

weighted CrossEntropy loss的最佳預測結果

weighted CrossEntropy 在實驗過程中因為圖片中的缺陷部分太過稀疏,導致了weights的選取有很大的問題存在,訓練後會發現其recall極高,但是precision卻也是很低,loss曲線也極其不規律,基本是沒法參考的,能把很多疑似缺陷的地方給弄進來.因此只能將weights改為固定常量,這樣可以在一定程度上控制均衡recall和precision,但調參也會相應變得麻煩

2.3 MSE(不帶權重)

我們先來試試MSE,在分割上最常規的loss

validation
epoch[687] | val_loss: 0.0063 | precisions: 0.6902 | recalls: 0.6552 | f1_scores: 0.6723 | time: 0
epoch[875] | val_loss: 0.0067 | precisions: 0.6324 | recalls: 0.7152 | f1_scores: 0.6713 | time: 0
epoch[1250] | val_loss: 0.0066 | precisions: 0.6435 | recalls: 0.7230 | f1_scores: 0.6809 | time: 0
epoch[1062] | val_loss: 0.0062 | precisions: 0.6749 | recalls: 0.6835 | f1_scores: 0.6792 | time: 0
training
2018-11-27 15:01:34 [1375-0] | train_loss: 0.0055 | precisions: 0.6867 | recalls: 0.6404 | f1_scores: 0.6627
2018-11-27 15:01:46 [1381-2] | train_loss: 0.0045 | precisions: 0.7223 | recalls: 0.6747 | f1_scores: 0.6977
2018-11-27 15:01:58 [1387-4] | train_loss: 0.0050 | precisions: 0.7336 | recalls: 0.7185 | f1_scores: 0.7259
2018-11-27 15:02:09 [1393-6] | train_loss: 0.0058 | precisions: 0.6719 | recalls: 0.6196 | f1_scores: 0.6447
2018-11-27 15:02:21 [1400-0] | train_loss: 0.0049 | precisions: 0.7546 | recalls: 0.7191 | f1_scores: 0.7364
2018-11-27 15:02:32 [1406-2] | train_loss: 0.0057 | precisions: 0.7286 | recalls: 0.6919 | f1_scores: 0.7098
2018-11-27 15:02:42 [1412-4] | train_loss: 0.0054 | precisions: 0.7850 | recalls: 0.6932 | f1_scores: 0.7363
2018-11-27 15:02:53 [1418-6] | train_loss: 0.0050 | precisions: 0.7401 | recalls: 0.7223 | f1_scores: 0.7311

MSE loss的最佳預測結果

MSE在訓練上較cross entropy就比較穩定,在heatmap預測上優勢挺明顯

2.4 weighted MSE(8:1)

既然MSE的效果還不錯,那麼是否加權後就更好了呢,其實從我做的實驗效果來看,並不準確,沒想像的那麼好,甚至導致性能下降了

validation
epoch[2000] | val_loss: 11002.3584 | precisions: 0.5730 | recalls: 0.7602 | f1_scores: 0.6535 | time: 1
training
2018-11-27 13:12:44 [2000-0] | train_loss: 7328.5186 | precisions: 0.6203 | recalls: 0.6857 | f1_scores: 0.6514
2018-11-27 13:13:01 [2006-2] | train_loss: 6290.4971 | precisions: 0.5446 | recalls: 0.5346 | f1_scores: 0.5396
2018-11-27 13:13:18 [2012-4] | train_loss: 5887.3525 | precisions: 0.6795 | recalls: 0.6064 | f1_scores: 0.6409
2018-11-27 13:13:36 [2018-6] | train_loss: 6102.1934 | precisions: 0.6613 | recalls: 0.6107 | f1_scores: 0.6350
2018-11-27 13:13:53 [2025-0] | train_loss: 7460.8853 | precisions: 0.6225 | recalls: 0.7137 | f1_scores: 0.6650

weighted MSE loss的最佳預測結果

以上loss在性能表現上,MSE > weighted MSE > weighted CrossEntropy,最簡單的卻在該任務上取得了最好的效果,所以我們接下來該做的,就是去懷疑人生了!

歡迎掃碼關注:

相關焦點

  • 【loss平衡】深度學習的多個loss如何平衡?
    在stage 1以後都用的是focal loss。首先對於每個 Task,你有個 Loss Function,以及一個映射到 [0, 1] 的 KPI (key performance indicator) 。比如對於分類任務, Loss function 可以是 cross entropy loss,KPI 可以是 Accuracy 或者 Average Precision。
  • 深度學習的多個 loss 是如何平衡的?
    Gal是Zoubin Ghahramani的高徒,近幾年結合Bayesian思想和深度學習做了很多solid的工作。一般都是多個loss之間平衡,即使是單任務,也會有weight decay項。比較簡單的組合一般通過調超參就可以。2. 對於比較複雜的多任務loss之間平衡,這裡推薦一篇通過網絡直接預測loss權重的方法[1]。以兩個loss為例,
  • 如何利用深度學習模型實現多任務學習?這裡有三點經驗
    我們運用多任務學習(Multi-Task Learning,MTL),在相同的輸入特徵集上預測多個關鍵性能指標(Key Performance Indicator,KPI),然後使用 TensorFlow 實現深度學習模型。回想最初的時候,我們感覺(上手)MTL 比現在要困難很多,所以我希望在這裡分享一些經驗總結。現在已經有很多關於利用深度學習模型實現 MTL 的文章。
  • 深度學習中的損失函數總結以及Center Loss函數筆記
    北京 上海巡迴站 | NVIDIA DLI深度學習培訓NVIDIA 深度學習學院 帶你快速進入火熱的DL領域正文共5481個字,19張圖,預計閱讀時間14分鐘。損失函數度量的是預測值與真實值之間的差異.損失函數通常寫做L(y_,y).y_代表了預測值,y代表了真實值.
  • 教程 | 如何估算深度神經網絡的最優學習率
    GitHub 連結:https://gist.github.com/surmenok我正在舊金山大學的 fast.ai 深度學習課程中學習相關知識。目前這門課程還沒有對公眾開放,但是現在網絡上有去年的版本,且年末會在 course.fast.ai (http://course.fast.ai/) 上更新。學習率如何影響訓練?
  • 要做好深度學習任務,不妨先在損失函數上「做好文章」
    雷鋒網 AI 科技評論按:損失函數對於機器學習而言,是最基礎也最重要的環節之一,因此在損失函數上「做好文章」,是一個機器學習項目順利進行的前提之一。Deep Learning Demystified 編輯、數據科學家 Harsha Bommana 以淺顯易懂的文字介紹了在不同的深度學習任務中如何設置損失函數,以期大家能夠對損失函數有一個更加清晰的認識。
  • 深度時序模型如何自定義MSE損失函數
    今天是「好技巧」專題的更新日,非常一個實用的模型改進小trick獻給大家,靈感也是來源於自己的項目實踐。以自己為例,我在處理時間序列數據,需要提前48小時輸出預測數據,現在採用的策略是均方誤差(Mean Square Error, MSE)作為預測模型的損失函數,但是結果不太好。通過思考業務邏輯之後,我恍然大悟,想明白了不同時刻的輸出預測值對損失函數的貢獻度是不同的。
  • 神經網絡中,設計loss function有哪些技巧?
    (如目標檢測任務中的框回歸loss+分類loss)2、multitask時,起始訓練各loss的數量級不同對收斂存在著哪些影響?3、根據任務修改loss時,如改進tripet loss,時常出現神經網絡作弊的情況,該如何設計loss?看看各位小夥伴的回答吧!
  • 直播 | Circle Loss:從對相似性優化的統一視角進行深度特徵學習
    「PW Live」是 PaperWeekly 的學術直播間,旨在幫助更多的青年學者宣傳其最新科研成果。我們一直認為,單向地輸出知識並不是一個最好的方式,而有效地反饋和交流可能會讓知識的傳播更加有意義,從而產生更大的價值。
  • GitHub | 機器學習&深度學習&nlp&cv從入門到深入全套資源分享
    深度學習之目標檢測的前世今生(Mask R-CNN)深度學習目標檢測模型全面綜述:Faster R-CNN、R-FCN和SSD從RCNN到SSD,這應該是最全的一份目標檢測算法盤點目標檢測算法綜述三部曲基於深度學習的目標檢測算法綜述(一)基於深度學習的目標檢測算法綜述(二)基於深度學習的目標檢測算法綜述
  • 深度學習中常見的損失函數
    在深度學習分類任務中,我們經常會使用到損失函數,今天我們就來總結一下深度學習中常見的損失函數。而邏輯回歸的推導中,它假設樣本服從於伯努利分布(0-1分布),然後求得滿足該分布的似然函數,接著求取對數等(Log損失函數中採用log就是因為求解過中使用了似然函數,為了求解方便而添加log,因為添加log並不改變其單調性)。但邏輯回歸併沒有極大化似然函數,而是轉變為最小化負的似然函數,因此有了上式。已知邏輯函數(sigmoid函數)為:
  • 乾貨分享 | 機器學習、深度學習、nlp、cv從入門到深入全套資源分享
    深度學習之目標檢測的前世今生(Mask R-CNN)深度學習目標檢測模型全面綜述:Faster R-CNN、R-FCN和SSD從RCNN到SSD,這應該是最全的一份目標檢測算法盤點目標檢測算法綜述三部曲基於深度學習的目標檢測算法綜述(一)基於深度學習的目標檢測算法綜述(二)基於深度學習的目標檢測算法綜述
  • 深度 提升深度學習模型的表現,你需要這20個技巧(附論文)
    ,也為機器學習社區貢獻了很多實用的建議和指南,本文所講解的是「能幫助你對抗過擬合以及實現更好的泛化」的 20 個技巧和技術。你可以怎樣讓你的深度學習模型實現更好的表現?這是一個我常被問到的問題:「我該怎麼提升準確度?」或者「如果我的神經網絡表現很糟糕我該怎麼辦?」……我常常給出的回答是:「我也不完全知道,但我有很多想法。」然後我開始列出所有我可以想到的可能能夠帶來效果改進的想法。
  • 深度學習的學習率調節實踐
    當一個ANN包含一個很深的隱藏層時,它被稱為深度神經網絡(DNN)。在本文中,我們將在MNIST數據集上訓練一個深度MLP,並通過指數增長來尋找最佳學習率,繪製損失圖,並找到損失增長的點,以達到85%以上的準確率。對於最佳的實踐過程,我們將實現早期停止,保存檢查點,並使用TensorBoard繪製學習曲線。
  • 深度學習模型訓練的一般方法(以DSSM為例)
    訓練深度學習模型,主要需要考慮四個方面(受限於當前認知水平,僅總結了四個方面),分別是:數據處理,包含數據清洗和分布;模型結構,包括網絡層結構設計和一些細節處理,前者主要有輸入層設計和隱層設計(輸出層設計劃分至目標函數),後者主要有初始化、正則化和激活函數;目標函數設計,包含目標的意義和難度,前者決定了模型的學習方向,後者影響對模型能否收斂影響很大
  • Hinton 新作「在線蒸餾」,提升深度學習分布式訓練表現的利器
    為此,「深度學習泰鬥」Geoffrey E.Hinton 近年來在知識蒸餾(或者「暗知識提取」)方面做了一系列工作,試圖通過這種從高計算能力要求、同時也具有高表現的模型中提取出一些隱含的知識,並且將其作為先驗,通過設計新的網絡結構和目標函數將這種知識「傳授」給規模較小的深度學習網絡,實現對網絡模型的壓縮,以顯著縮小的網絡規模和計算需求展現出儘量高的模型表現。
  • Head Pose Estimation第三季:深度學習版!一起來學習!
    本次CV_life君推出深度學習版Head Pose Estimation,給大家介紹兩個比較有代表性的深度網絡:Hopenet和HyperFace。CV_life君在文中提供了論文下載連結以及部分數據集(部分數據集太大,CV_life君提供了數據集的連結)。重磅!頭部姿態估計「原理詳解 + 實戰代碼」來啦!
  • 【深度學習】一文讀懂機器學習常用損失函數(Loss Function)
    >>文章轉載博客園郭耀華's Blog>>http://www.guoyaohua.com並做少量的補充損失函數(loss function)是用來估量模型的預測值f(x)與真實值Y的不一致程度,它是一個非負實值函數,通常使用L(Y, f(x))來表示,損失函數越小,模型的魯棒性就越好。
  • 多任務學習與深度學習
    多任務學習是機器學習的一個子領域,學習的目標是同事執行多個相關任務。因為多任務學習是一個非常有泛化性質的工作,比如我們想同時來預測股市的波動和輿情政策的關係,那麼多任務學習就會更有幫助,因為它有助於跨任務的資源和參數共享,並且還可以減少單獨訓練兩個模型的訓練時間。在這篇文章中,我們將分享如何執行 「深度學習中任務學習的步驟」。我們在這裡將使用 TensorFlow 的 Slim API 執行這個任務。
  • 教你如何從零開始構建深度學習項目?
    本文由六大部分組成,涵蓋深度學習 ( DL ) 項目的整個過程。我們將使用一個自動漫畫著色項目來說明深度學習的設計、程序調試和參數調整過程。本文主題為「如何啟動一個深度學習項目?」做深度學習的正確策略是快速的執行學到的東西。在跳到使用無暗示(no hints)模型之前,我們先使用帶有空間顏色暗示的模型。不要一步跳到「無暗示」模型設計,例如我們首先去掉暗示中的空間信息,顏色質量會急劇下降,所以我們轉變優先性,在做下一步前先精煉我們的模型。在設計模型的過程中,我們會遇到許多驚喜。相比於做個要不斷改變的長期計劃,還不如以優先性驅動的計劃。