說在最前面的,這些訓練數據可能會因為演算法、優化器、排程器或是各種相關套件更新而失準。本次的實驗主要是要測試 Noise 對於整體訓練的差異,與可能可以怎麼選擇或是設定的紀錄。
Kohya GUI
本次所使用的 Kohya GUI 版本是 24.1.4,如果你不是這個版本,或者是你是直接使用 kohya-ss/sd-script v0.8.7 也可以。
我們在 Kohya 的進階設定中可以找到本篇文章所提到的各種設定,你可以參考我之前的文章 [Lora] Kohya_ss GUI 介面筆記,我這邊就不贅述。
Noise 噪聲
在生成對抗網絡(Generative Adversarial Networks, GANs)中,噪聲(Noise)通常作為輸入注入到生成器網絡中,為生成的圖像引入隨機變化。在 Stable Diffusion 的做法是在最初的低分辨率層次由全噪聲(Pure Noise)然後根據生成的時間步數(timesteps
)逐漸的降噪(Denoising)進而生成目標圖片。
我把這件事情拿去問了 GPT-4o 他給了我上面這張奇怪的圖,覺得可愛所以我放上來,但應該不是很正確啦(笑)。
Noise Offset
關於 Noise Offset 我這邊就不多做解釋,有興趣理解原理的可以參考這個影片,他解釋的很清楚!
以下參考資料有興趣的人可以自行翻閱
Understanding “Common Diffusion Noise Schedules and Sample Steps are Flawed” and Offset Noise
在 Kohya 訓練當中,關於 Noise Offset 有兩種,
參數 | 說明 |
---|---|
Original | 原始噪聲 |
Multires | 多分辨率噪聲,又有人稱金字塔噪聲 |
而跟噪聲有關的設定,則有,
參數 | 說明 |
---|---|
Noise offset random strength | 在 0 ~ Noise Offset 之中取一個亂數來當作 Noise Offset |
Adaptive noise scale | 使用一個潛空間平均絕對值(latent mean absolute value),乘上這個數字來當作 Noise Offset |
Multires noise iterations | 多分辨率噪聲迭代的次數 |
Multires noise discount | 降低在不同層次尺度注入噪聲時的強度 |
IP noise gamma | 擾動噪聲 |
IP noise gamma random strength | 隨機由 0 ~ IP noise gamma 之間取擾動噪聲 |
關於 Loss
這裡 #PR294 的資訊量巨大,有興趣的人可以自己去爬文研究。
min SNR gamma
就是一個從論文來的方法,然後建議用 5%
,大家也就用了好像也沒什麼問題。
Debiased Estimation loss
跟 min SNR gamma 一樣,也是一篇論文的實作,但效果跟 min-SNR gamma 有點不太一樣。
Huber Loss
以下是我詢問 Claude 他給我的解釋,
Huber Loss 是一種常用的損失函數(Loss Function),通常應用於迴歸問題中。它的全名為Huber平滑絕對損失(Huber Smooth L1 Loss),是 L1 損失(絕對損失)和 L2 損失(平方損失)的一種混合形式,結合了兩者的優點。
Huber Loss 的數學定義如下:
L_δ(y, f(x)) = \begin{cases} \frac{1}{2}(y - f(x))^2 & \text{if } |y - f(x)| < \delta \ \delta|y - f(x)| - \frac{1}{2}\delta^2 & \text{otherwise} \end{cases}
其中δ稱為平滑參數(Smoothing Parameter),通常取一個較小的正值。
當|y - f(x)|較小時,Huber Loss 等同於 L2 損失,具有連續可微的優點,適合微小誤差情況。
當|y - f(x)|較大時,Huber Loss 等同於 L1 損失,對離群值(outlier)具有一定的鮮活性,不會過度放大其影響。因此,Huber Loss結合了 L1 和 L2 損失的優點,在小誤差情況下更平滑,在大誤差情況下更鮮活,往往比單一的 L1 或 L2 損失表現更好。它常被用於迴歸模型的訓練,特別是對離群值較為敏感的場景。
而我之前有提過,在 Kohya-ss 的 #PR1228 裡有提到他的作法與原本 Huber 的算法有點不太一樣。
比對與測試
首先,以下是我測試的差異參數,
參數/版本 | v53 | v54 | v55 | v56 | v57 | v58 | v59 | v60 | v61 | v62 | v63 | v64 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
精度 | fp8 | fp8 | fp8 | fp8 | fp8 | fp8 | fp8 | fp8 | fp8 | fp8 | fp8 | fp16 |
優化器 | DAP | L8 | DAP | DAP | DAP | DAP | DAP | DAP | Pg | Pg | DAP | DAP |
min-SNR gamma | 5 | x | x | x | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 |
Debiased | x | v | v | v | x | x | x | x | x | x | x | x |
Noise Offset | 0.0357 | x | x | x | 0.0357 | x | x | x | 0.0357 | 0.0357 | x | x |
Multires noise iterations | x | x | x | x | x | 10 | x | 6 | x | x | x | 6 |
IP noise gamma | x | x | x | x | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 |
huber_c | x | x | 0.01 | 0.05 | x | x | 0.08 | x | x | x | x | x |
BS | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 2 | 2 | 4 | 4 |
梯度累加 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 2 | 4 | 1 |
DAP = DAdaptAdamPreprint
L8 = Lion8bit
Pg = Prodigy
Debiased = Debiased Estimation loss
BS = Total batch Size
huber_c = use Scheduled Huber Loss, Loss type: huber, Huber schedule: snr
這些測試除了學習率,與特別寫出的 BS2
與 Gradient accumulate steps
以外,其他參數都全數固定,為了降低影響,在 v60
以前,提詞都是同一組,而 v61
以後則採用另一組提詞。而所有的訓練集都使用同一組,且解析度都以 2048x2048
為基準,並且使用 Don't upscale bucket resolution
與 ARB 分桶,分桶的尺寸是 32
。
影響層面
根據這些測試,我先整理一個影響層面給大家參考,
參數 | 影響 |
---|---|
Noise Offset 0.0357 |
這是 SDXL 預設的一組 Noise Offset 數值,對畫面的亮部或暗部的強化(或弱化)的效果會因為噪聲而有所變化 |
Multires noise iterations 6 |
金字塔噪聲在這個數字越大時,對於邊緣處理的強度會越強,維持 6 是明智的選擇 |
Multires noise discount 0.3 |
這個數字如果很大,那麼他對於邊緣處理的效果就越低,你用 0.8 有時候會有柔膚效果 |
min-SNR gamma 5 |
邊緣處理柔和,細節部分會產生失真,大面積特徵效果處理的比較平滑 |
Huber Loss, snr, huber_c: 0.01 |
擬合速度很快,如果你的訓練步數很多,你所拿到的擬合強度會非常高 |
Huber Loss, snr, huber_c: 0.05 |
因為增高了 huber_c ,所以擬合速度會放緩,強度也會稍微弱一點 |
Debiased Estimation loss | 這個啟用後,邊緣處理的強度會非常強,跟 min-SNR gamma 5 有極大的差異 |
IP noise gamma 0.1 |
增加擾動噪聲時,對於學習過程中可以補足部分細節,但強度過高會有奇怪的細節產生 |
fp8_base 與 fp16 |
相較之下 fp16 的表現內容比較多元(不一定是細節) |
測試結果
我們來看看這些產出的結果,
你會發現 v53
跟 v57
在頭髮的部分有一點差異,在 IP noise gamma
的作用下,細節會比沒有使用要來的多一些。臉部的肌理、服裝細節與陰影的部分也會比較豐富。
而 v57
與 v58
相比之下,使用了多分辨率噪聲的情況下,他的頭髮表現就更強,甚至有一點過度強化的感覺,這一點就看資料集是否需要,如果資料集的解析度偏低的情況下,多分辨率噪聲可能會比較好。
回頭看 v56
,完全不使用噪聲偏移,單純靠 Debiased Estimation loss
就把頭髮細節跟顏色做得很好。你會發現除了 v56
以外,所有的人物顏色都偏黃,我後來回頭檢查資料集,發現是有些照片並沒有做白平衡的調整,而是維持室內黃光。
我們再看另一組例子,
你會發現 v58
在多分辨率噪聲的加持下,臉部光影跟細節都表現的不錯,而 v57
也因為有 IP noise gamma
而在細節上有所提升。
接著我們看一下不同優化器所產生的結果,
在 v61
採用了 Prodigy 而 v60
則是 DAdaptAdamPreprint,你會說噪聲參數不同步公平,那麼你可以再往上一點跟 v57
比較。
整體上來說,在 Prodigy 的學習狀況來看,他的擬合速度比我想像中的還快,整體的表現其實已經是過擬合的狀況,之所以沒有爆炸應該是提詞的方式救了他。對於高品質的訓練集來說,使用 Prodigy 可能不是一個好的選項(對我而言來說,他表現反而不好)。
但是,雖然擬合程度高,不過沒有出現過度偏黃的問題。我們來看一組故意讓他模擬底片表現的效果,
這個時候你會發現 Prodigy 的顏色表現很穩定(起碼沒有偏黃)。
接著我們來背景表現的狀況,
你會發現三張的背景都不太合理,幾乎都是左右對切的不連貫狀況。由於提詞泛化程度很高,目前不確定是否是提詞影響。
但,由於我重點只跟他說 a girl standing in front of the coffeeshop bar
,其他都是描述服裝、光影、品質等等的提詞,所以那個 in front of
是對的,但是 coffeeshop bar
可能就很自由發揮了。
不過,你可以對比 v60
與 v64
兩者是 fp8
與 fp16
的訓練差異。實際上在 fp16
的結果上,他的話面豐富度會比較多一點。
高強度的結果
我上面有提到幾個東西會造成邊緣強度過高,例如 Debiased Estimation loss
這件事。
頭髮的強度你這樣看起來就會發現,他有點太超過了。
而,更超過的還有一個,就是使用 Huber Loss, snr, huber_c: 0.01
加上 Debiased Estimation loss
,由於 huber_c: 0.01
的關係,外加 Debiased Estimation loss
本身就會加速擬合,所以就會拿到這種結果(特徵不像是因為我沒下觸發詞的關係),
所以大抵上來說,如果你的訓練集狀況不是很好(當然也不能太爛),那麼用 Huber Loss 搭配 Debiased Estimation loss
或許是一個不錯的選擇。當然,你的 huber_c
可以的話先從 0.05
開始嘗試會比較好,最後再視狀況往上或是往下。
我這邊有一個 0.05
的例子(就是 v56
),
所以對於細節或是特徵比較要求的話,使用 Debiased Estimation loss
確實效果不錯,至於是不是要使用 Huber Loss 就端看你的資料集跑起來,哪個比較好來決定。
意外的發現
當我在測試 v62
與 v63
的時候,其實是沒有完整跑完的,但是卻發現了一件事,就是他們的擬合速度出乎我意料之外,
上面三張的總步數是這樣,
版本 | 總步數 |
---|---|
v61 | 6,000 |
v62-000005 | 1,180 |
v63-000006 | 1,428 |
令人驚訝的是絕大部分的特徵在 1,500
步內已經有了七八成的訓練結果!
這兩個版本剛好是因為 Prodigy 我無法跑到 Train batch size: 4
的設定,所以只好搭配 Train batch size: 4
加上 Gradient accumulate steps 2
來去執行。
中間為了修改設定而中斷了 v62
這一爐,而另開 v63
的時候,沒注意到 Gradient accumulate steps 2
的情況下,就用 DAdaptAdamPreprint
開跑了,所以就這樣突然發現他們擬合的速度好快!
但是!
這個狀況拿來測試是可以的,因為步數相當低,而 Epochs 數量也不高,所以對於背景或其他物件的表現就不會太好。
背景被切成三塊,衣服與人物連接觸的不自然陰影等。臉部的瑕疵大概還可以用 ADetailer 去修正,其他的部分就稍微麻煩一點,當然你用 segment-anything 切下來另外做也是可以。
加噪這件事
這邊要說一件事,使用 IP noise gamma
是他隨機加入一個固定權重的擾動噪聲,對訓練來說,這個動作確實會增加一點細節,但過多會產生不必要的東西。
使用這個參數對於你的 訓練集 內容是 使用 AI 產生的圖 來說,會有一定的幫助,這個擾動噪聲可以避免學習這些 AI 產生的圖的 副作用。
AI 產出的圖拿來訓練,大部分會有超快速擬合的副作用。
關於這一點,我所使用解決的方式有幾種,
- 圖片丟進 Photoshop 手工加入一點噪訊(只能一點點,太多會變成風格被學起來)
- 使用 Lightroom 統一把圖片套用某種風格(強度不能太高,太強也是會變成風格被學起來)
- JPEG 破壞壓縮縮小
0.9
再放大回原本尺寸(故意破壞畫面)
現在有 IP noise gamma
是可以比較省事一點,但就是強度自己斟酌,雖然會增加細節,但是也會有機會 長出不對的細節。
結語
要我推薦參數就 v53
, v57
, v60
, v64
這些吧。