深度學習-物件偵測YOLO cfg檔解讀 (三) - 2021年
因為Darknet也出很多年了,時隔兩年了,很多新的參數和cfg設定推陳出新,所以update一下,本篇文章依據Darknet的wiki「CFG Parameters in the [net] section」翻譯說明。
舊版的Darknet參數設定說明,可以參考之前寫的文章:
深度學習-物件偵測YOLOv1、YOLOv2和YOLOv3 cfg 檔解讀(一)
深度學習-物件偵測YOLOv1、YOLOv2和YOLOv3 cfg 檔解讀(二)
[net]層
batch=64: 每個batch學習採用多少的樣本資料。subdivisions=4: 在一個batch學習中,要拆成幾個個mini-batch。
這個的意思是說假設batch=64,但可能你的GPU記憶體無法的時候一次訓練64筆資料,你又想要一次處理64筆資料,假設你的GPU撐得住16筆資料的記憶體,這時候用subdivisions的設定(設定為4),每個mini-batch有64/4=16筆資料,這樣記憶體撐得住16筆資料,所以GPU每次處理就是一個mini-batch=16筆資料,當四個mini-batch都處理過,將四個mini-batch平均起來得到這個batch的平均梯度後,再利用梯度下降法進行更新。
梯度下降法: 權重 = 權重 — 學習率*梯度(batch)
Batch = 64 = Mini-batch(1) + Mini-batch(2) + Mini-batch(3) + Mini-batch(4)
梯度(batch) = [梯度(Mini-batch(1))+ 梯度(Mini-batch(2))+ 梯度(Mini-batch(3))+ 梯度(Mini-batch(4))]/4 → 實際運作方式不完全是這樣,但概念是一樣的。
width=416 : 在神經網路訓練(training)和偵測(inference)階段,每張圖會被resize到寬為416的圖。height=416 : 在神經網路訓練(training)和偵測(inference)階段,每張圖會被resize到高為416的圖。channels=3 : 神經網路輸入的通道數(channel),一般彩色圖為RGB三個顏色,所以通道數為3,如果是灰階圖則通道數為1。inputs=256 : 當神經網路輸入不是圖像的時候,輸入的結構化資料大小,例如輸入資料是身高和體重兩個,則inputs=2。max_chart_loss=20 : 在chart.png內最大的loss值。
以下只有訓練會用到的部分
Contrastive loss
contrastive=1 : 訓練分類器時候採用Supervised contrastive loss,但只用在[contrastive]層。Unsupervised=1 : 訓練分類器時候採用Unsupervised contrastive loss,但contrastive參數需設定為1,且要搭配[contrastive]層。
Data augmentation in [net]層
angle=0 : 在訓練過程中會隨機旋轉圖片角度,單位是度,angle=10,就是隨機生成-10~10度旋轉的圖片(classification only)。saturation = 1.5 : 在訓練過程中會隨機改變圖像飽和度,在1–1.5之間隨機取飽和度參數設定。exposure = 1.5 : 在訓練過程中會隨機改變圖像曝光度(亮度),在1~1.5倍隨機取曝光度參數設定。hue =.1 : 在訓練過程中會隨機改變圖像色調),在-0.1~0.1倍隨機取參數設定。參考:https://en.wikipedia.org/wiki/HSL_and_HSVblur=1 : 百分之50的機率會採用模糊化處理。(only for detection and if OpenCV is used)
當參數設定為1,除了物件之外背景將被 blur_kernel為31大小的方式進行模糊化。
當參數>1,整張圖會被blur_kernel為blur參數的大小方式進行圖片模糊化。min_crop=224 :隨機截圖來進行模型訓練,截圖的最小大小。(classification only)。max_crop=448 :隨機截圖來進行模型訓練,截圖的最大大小。(classification only)。aspect=.75 : 長寬比在crop從0.75到1/0.75之間變化。letter_box=1 : 在訓練過程中保持輸入圖的長寬比(detection training only)
如果採用letter_box進行訓練,在inference階段,需額外下指令(-letter_box)在detection命令的最後面。cutmix=1 : 使用CutMix資料擴增法 (for Classifier only, not for Detector)mosaic=1 : 使用Mosaic資料擴增法(將四張圖合成一張)。mosaic_bound=1 : 當設定為1的時候,會限制物件的大小,也就是利用Mosaic合併後的圖,物件框的位置不會離開它對應的圖。
可以參考: https://blog.csdn.net/weixin_44791964/article/details/105996954gaussian_noise=1 :將圖片加入高斯雜訊。
Self-adversarial training(SAT)
以下這兩個資料增強方法是用來進行Self-adversarial training(SAT),參考: https://github.com/AlexeyAB/darknet/issues/5117
https://github.com/AlexeyAB/darknet/issues/5105(看這段解釋可能會更清楚Alexey這段adversarial attack在幹嘛)
部分內容是英文看完翻譯的,所以看起來很怪。
adversarial_lr=1.0attention=1 (打開會呈現attention結果,個人解讀應該是CAM顯示。)
adversarial_lr的設定是針對物件最後分類判斷的部分,因為在高的學習率的訓練過程中看起來比較不穩定,所以在前50次模型訓練(迭代更新)中先不採用這個程序,後面的更新就會增加adversarial_lr=0.05這樣的設定然後繼續訓練模型。
Alexey解釋說當它運行attention-algorithm或是adversarial-attack-algorithm時候,他發現神經網路只專注它認為於物件最重要稀有物件的位置,但是神經網路經常犯一個錯誤就是「神經網路只專注在物件的某些位置,並非這個物件最重要的地方,或是它專注的地方其實更本就不屬於該物件,神經網路在學習的過程中忽略掉了這個物件的其他細節」。
解決這個問題的方式就是在讓神經網路可以考慮到物件更全面的區域。
SAT就是一種解決上述問題的一種技術:在訓練過程中,每兩個iteration神經網路會產生一次Adversarial attack。
在第一次forward-backward pass,神經網路在學習過程中會試著將圖片中所有物件的細節都忽略掉,並且讓神經網路相信圖中不是只有一個物件。
在第二次forward-backward,神經網路會教它的權重說所有的物件還在圖片內,儘管神經網路覺得這個物件看起來不在那邊。
PS: Alexey解釋這個程序是要呼嚨偵測器,它不是訓練模型,而是在訓練影像。
NOTE: Adversarial attack圖片,類似下圖,在圖像中加入一些noise,神經網路就會誤判圖像的結果,熊貓的圖片加了一些雜訊後模型會判斷成長臂猿。
Alexey在github舉的範例,拿預設已經訓練好的yolov3.cfg/weights進行
記得這句話很重要「這個程序是要呼嚨偵測器,它不是訓練模型,而是在訓練影像,讓模型更難辨識圖片」。
第一和三欄圖片被SAT改變了Data augmentation得到的圖像。
第二欄是模型訓練是用原始圖的方式進行,如果拿這張圖(沒有經由adversarial attack)去跑模型,從attention圖來視覺化看,可以發現圖片有看到狗/腳踏車/汽車。
第一欄是拿SAT程序再進行模型訓練500次更新後得到的圖片,這邊要特別注意是在500次更新是更新圖片不是更新模型權重,所以圖片被改變後,所以模型看到的是模型只會看到一隻貓在那邊。第三欄的圖片和第一欄是一樣的,第三欄只是做Attention視覺化呈現,圖中對於狗/腳踏車/汽車的attention圖會被壓抑下來。
所以可以發現經由adversarial attack後的圖,模型根本很難正確偵測到物件的位置和類別,所以後續採用這些圖片進行模型更新(模型學習),則模型能有更強的能力再於對抗這類型(攻擊生成的假資料),也就是眼睛清楚看到狗/腳踏車/汽車的圖片,模型繼續訓練會更要求去專注再這些顯而易見的物件上。
白話說法「利用攻擊模型的資料來訓練資模型,讓模型可以學更多很難辨識的資料,這樣訓練出來模型一般性會更好」。
Alexey建議adversarial_lr在小的資料集和大的模型配置下設訂高一點,但在tiny model上不要用這個參數設定。
Data augmentation in [yolo]層
Jitter=0.3 : 隨機改變圖像的大小及其寬高比從 (1–2*jitter) 倍到 (1 + 2*jitter)倍Random=1 : 在十個batches(也就是十次模型更新之後)後,會隨機改變神經網路輸入的大小(1/1.4倍到1.4倍)但保持網絡大小的初始長寬比。
Optimizer配置
momentum=0.9: 利用momentum這個optimizer來訓練 (細節看: 機器/深度學習-基礎數學(三):梯度最佳解相關算法(gradient descent optimization algorithms))。decay=0.0005: decay是weight decay的正規化參數,主要是用在參數正規化權重避免overfitting。learning_rate=0.001: optimizer學習參數初始值 (細節看: 機器/深度學習-基礎數學(二):梯度下降法(gradient descent))
上述三個參數對應關係如下:
max_batches = 500200: 模型最大iteration次數(batch)。burn_in=1000: 如果此項有打開設定,則在初始的1000個iteration,採用的學習率會從小到大改變,類似warm-up策略,學習率變化公式:
current_learning rate = learning_rate * pow(iterations / burn_in, power) = 0.001 * pow(iterations/1000, 4)
policy=steps: 這個參數是用來調整學習率的策略(在機器/深度學習-基礎數學(二):梯度下降法(gradient descent)內有說明學習率的大小會影響找解的問題,所以用不同策略解決學習率在不同時間上大小要不同),包含constant, sgdr, steps, step,sig, exp, poly, random。
如果policy=random,則學習率會被以下列公式的方式更新
current_learning rate = learning_rate * pow(rand_uniform(0,1), power)
power=4: 當policy=poly,學習率會依據公式變化
current_learning rate = learning_rate * pow(1 — current_iteration / max_batches, power)
sgdr_cycle=1000: 當policy=sgdr,利用cosine-cycle進行的初始iteration次數。sgdr_mult=2: 當policy=sgdr,利用cosine-cycle的倍率。
steps=8000,9000,12000: 當policy=steps,利用學習率在第steps次下會進行乘法修改,乘上參數scales的設定。scales=.1,.2,.3: 同上參數使用。
假設在學習率初始為0.01,在第8000次模型更新的時候,
current_learning_rate = learning_rate * scales[0] =0.01*0.1=0.001
在第9000次模型更新的時候,
current_learning_rate = learning_rate * scales[0] * scales[1] =0.01*0.1*0.2=0.0002
在第12000次模型更新的時候,
current_learning_rate = learning_rate * scales[0] * scales[1] * scales[2] =0.01*0.1*0.2*0.3=0.00006
label_smooth_eps=0.1: 如果設置,則會採用label smoothing技術訓練分類器。