Stable Diffusion LoRA 訓(xùn)練不完全指北(2)

前言
繼上一篇專欄講了一些比較通用的技巧,這次繼續(xù)補充了一些不常用的參數(shù),同時簡單討論了一下Dreambooth和正則化。然后對現(xiàn)有的一些噪聲做了一些實驗分析,希望能夠幫助到大家。有問題或者指出錯誤歡迎評論區(qū)友善交流。
想要更好的格式可以看 https://zpfam.gitbook.io/lora-jiao-cheng-xi-lie/

一些新的或者較少用到參數(shù)的補充
數(shù)據(jù)增強相關(guān)
數(shù)據(jù)增強是在訓(xùn)練時對圖片做變換的方法,可用于防止過擬合,但是,能用的一共有四種: color_aug, flip_aug, face_crop_aug_range, random_crop。
其中只有翻轉(zhuǎn)(flip_aug)能和cache latent兼容,因為latent可以直接翻轉(zhuǎn)。
四種都不推薦使用,因為裁剪圖片的兩種cropping方法都會導(dǎo)致tag對應(yīng)不上。color_aug無法啟用cache latent導(dǎo)致訓(xùn)練慢,得不償失。翻轉(zhuǎn)的flip_aug在圖像不對稱的情況下表現(xiàn)差,會導(dǎo)致無法正確生成人物不對稱的特征(劉海、發(fā)飾等)。
caption dropout相關(guān)
網(wǎng)上關(guān)于這幾個caption dropout的說明少之又少,甚至作者在文檔里面也沒有包含這些參數(shù),只能在代碼注釋里面找到說明。但是caption dropout在某些情況下對模型性能有提升,所以拿出來講一下。
caption_dropout_rate
丟棄全部標(biāo)簽的概率,對一個圖片概率不使用caption或class token
caption_dropout_every_n_epochs
每N個epoch丟棄全部標(biāo)簽。
caption_tag_dropout_rate
按逗號分隔的標(biāo)簽來隨機丟棄tag的概率。如果使用DB+標(biāo)簽的訓(xùn)練方法訓(xùn)練畫風(fēng),推薦使用這個參數(shù),能夠有效防止tag過擬合,一般選擇0.2-0.5之間的值。訓(xùn)練人物則無需開啟。
token_warmup_min、token_warmup_step
兩個token熱身相關(guān)的參數(shù)。第一個是最小學(xué)習(xí)的token數(shù)量,第二個是在多少步后達(dá)到最大token數(shù)量。
token_warmup可以理解為另一種形式的caption dropout,但是如果不隨機打亂token,則只會學(xué)習(xí)前面N個token。本人并未實測過啟用這兩個參數(shù)的效果,有興趣可以自行實驗。
max_grad_norm
限制模型更新梯度的大小,改善數(shù)值穩(wěn)定性。梯度的范數(shù)超過這個值將會被縮放到這個大小,一般來說無需設(shè)置。
gradient_accumulation_steps
梯度累積步數(shù),用于在小顯存上模擬大batch size的效果。如果顯存足夠使用4以上的batch size就沒必要啟用。
log_with、wandb_api_key
選擇logger類型,可選tensorboard或者wandb。使用wandb需要指定api key。
multires_noise_iterations、multires_noise_discount
多分辨率/金字塔噪聲相關(guān)參數(shù)。詳情看下面噪聲實驗的部分。
prior_loss_weight
DB訓(xùn)練當(dāng)中先驗部分的權(quán)重,控制正則化圖像的強度,論文中使用的是1的值,如無特殊情況無需更改。
debug_dataset
不訓(xùn)練模型,僅輸出訓(xùn)練集元數(shù)據(jù)和訓(xùn)練信息,可以用來看設(shè)置是否正確。
vae_batch_size
cache lantent的時候VAE編碼器的batch size,和訓(xùn)練效果無關(guān)。一般來說使用2-4可以加速一點cache latent的過程。因為VAE編碼器本身參數(shù)量比較小,在Linux下8G的顯卡也能開啟4。Windows下顯存占用較多,建議不開啟或者使用2。

Dreambooth淺析
Dreambooth是什么,和Lora的區(qū)別?
此部分并非訓(xùn)練必要,理解有困難可以酌情跳過,或者參考秋葉aaaki這篇文章(通俗易懂):https://www.bilibili.com/read/cv22578510
Dreambooth是一種微調(diào)大模型加入正則化損失函數(shù)防止語言漂移的方法,而Lora是通過矩陣低秩分解的方法來降低微調(diào)模型所需的參數(shù)量。簡單來說DB修改的是訓(xùn)練過程/Loss函數(shù),Lora修改的是網(wǎng)絡(luò)架構(gòu),兩個修改的是完全不同的東西所以可以相互兼容。

此為Dreambooth所使用的Loss函數(shù),由兩部分構(gòu)成,實際并不復(fù)雜:第一部分為訓(xùn)練集圖片的重建損失,第二部分是正則化圖像(先驗)損失。
代碼里的實現(xiàn)表現(xiàn)為訓(xùn)練集和正則化圖片以相同的方式訓(xùn)練,但是正則化圖片的梯度更新會乘以先驗Loss權(quán)重,也就是公式中的λ,訓(xùn)練參數(shù)中的prior_loss_weight。
正則化是不是必要的?
不是。在使用標(biāo)簽文件訓(xùn)練的時候,可以不需要使用正則化。但是如果只是使用class token訓(xùn)練,建議使用。
原因在于使用標(biāo)簽文件的時候TE模型對單一token過擬合的概率較小,反而是UNet部分更加容易過擬合,加入正則化可以改善畫風(fēng)過擬合。
沒有使用標(biāo)簽文件的時候所有文件都以class token作為標(biāo)簽,語言漂移的問題可以通過正則化緩解。
需要什么樣的正則化圖片?需要提供標(biāo)簽嗎?
論文中使用的正則化圖像是在相同底模上用AI生成的相同類的圖片。如果使用class token訓(xùn)練,可以根據(jù)你需要訓(xùn)練的內(nèi)容使用如1girl等來生成。
如果在標(biāo)簽文件上訓(xùn)練,那么正則化文件是不需要標(biāo)簽的,只需要指定對應(yīng)的class token即可。
一個我認(rèn)為有用的小技巧:使用隨機tag生成不同背景、場景、姿勢、角度、光照的正則化圖片能夠有效提升效果。

不同噪聲的一些實驗以及隨想
不想看理論和實驗過程的可以直接跳轉(zhuǎn)結(jié)論。
為什么要使用不同的噪聲?不同噪聲之間有什么區(qū)別?
首先這兩篇博文的核心觀點都是現(xiàn)有的模型只能生成像素均值在0.5左右的圖片(關(guān)聯(lián):維數(shù)災(zāi)難),無法生成更亮或者更暗的圖片。因為獨立同分布的高斯噪聲是非常高頻的,模型需要非常長的時間才能學(xué)習(xí)到更加低頻率的信息,包括圖片的零頻率(像素均值)。
于是有了以下兩種解決方法:noise_offset(噪聲偏移)、multires_noise(多分辨率/金字塔噪聲)
噪聲偏移通過在圖片中隨機添加統(tǒng)一的值來快速改變圖片的均值(零頻率)從而使模型學(xué)習(xí)能夠更快學(xué)習(xí)到圖片的均值從而能夠生成更亮或者更暗的圖片。
而金字塔噪聲通過反復(fù)疊加不同分辨率的噪聲來增加低頻的部分從而達(dá)到同樣的效果。
由于multires文章的作者提出了其他噪聲如perlin noise和pink noise,這里簡單在pytorch上實現(xiàn)了Perlin噪聲作為對比,之后會放出相關(guān)代碼的Colab和提交訓(xùn)練腳本的PR供大家探索。
但限于本人沒有系統(tǒng)學(xué)習(xí)過數(shù)字信號處理的內(nèi)容,以下內(nèi)容非常主觀,如果有錯誤或者更好的解釋歡迎提出。
不同噪聲的頻譜和相位譜可視化
高斯噪聲(白噪聲)
可以看到白噪聲的頻率分布非常均勻,并且像素之間的關(guān)聯(lián)度是0。這是模型默認(rèn)使用的噪聲。

金字塔噪聲
相位譜中可以看出相鄰的像素之間有一定的關(guān)聯(lián)。同時從頻率譜中可以看出低頻部分大概在7-8之間,高頻的部分在0-6之間。
iteration控制疊加次數(shù),并不是越高越好,因為根據(jù)圖片分辨率不同,噪聲的分辨率可能超過圖像本身分辨率,效果提升非常微弱。6-8已經(jīng)足夠。
discount控制低分辨率(低頻部分)的權(quán)重,如果使用過低的值那和高斯噪聲區(qū)別不大。越高的值對低頻的增強越多。一般設(shè)置0.4-0.8之間即可。

Perlin噪聲(無擾動)
Perlin噪聲是一種用于生成模擬自然隨機紋理和漸變效果的算法,其特點是平滑且連續(xù)。常用于自然地形、紋理生成等,最著名的應(yīng)用應(yīng)該是Minecraft里面的地形生成。
Octave相當(dāng)于多分辨率噪聲中的疊加次數(shù)。
Persistence相當(dāng)于多分辨率噪聲中的discount。
可以從頻譜中看到低頻的部分被增強了非常多,同時相位譜中可以看出圖像的一些結(jié)構(gòu)化的特征。

Perlin噪聲(有擾動)
因為原生的Perlin噪聲不夠隨機,可能導(dǎo)致無法在訓(xùn)練過程中完全將圖片變?yōu)楦咚狗植?,我嘗試加入一些隨機擾動來去除圖中的固有屬性,同時保留部分低頻信息??梢钥吹竭@時候的相位譜已經(jīng)幾乎看不出原圖的特征了,然后頻譜也和金字塔噪聲比較相似。

實驗設(shè)置和樣本
全部使用相同的圖片和標(biāo)簽來訓(xùn)練lycoris模型??紤]有色噪聲會增加擬合難度,base模型訓(xùn)練15個epoch,其余都訓(xùn)練30個epoch。訓(xùn)練集的標(biāo)簽沒有經(jīng)過裁剪和調(diào)整,所以細(xì)節(jié)的特征不具有代表性。
同時我還為Perlin噪聲引入了同樣的噪聲偏移機制來改變零頻率,因為我無法復(fù)現(xiàn)金字塔噪聲作者的效果。我認(rèn)為可能的原因是Lora對模型的控制不夠,需要進(jìn)一步在大模型上微調(diào)來驗證。另外一種可能的解釋是噪聲的零頻率期望值是不變的,但是我的實驗結(jié)果不能支撐這一點。還有一種可能是訓(xùn)練集中例子過少導(dǎo)致模型無法學(xué)習(xí)。
以下兩張圖是我自己寫的prompt:


下面是用原圖的prompt生成:
原圖:

相同prompt生成的圖:

結(jié)論
首先這個初步結(jié)論只對Lora訓(xùn)練有效,大模型微調(diào)的效果還需要進(jìn)一步驗證。
噪聲偏移可以很好改善極亮或者極暗圖片的生成,但是會出現(xiàn)色溫偏移的問題,例子里的圖片明顯偏冷色調(diào)。
金字塔噪聲無法改善亮度問題,但是生成的圖片對原圖的還原度最高,但是有時候會有涂抹感。(也有可能是其他方法擬合太慢)
Perlin噪聲的效果基本與金字塔噪聲相同,同時在圖片顏色上有更平滑的過渡。我只實驗了非常少的幾組參數(shù),其他的需要更多實驗驗證。
對于不同噪聲的主觀的感受還需要各位自己評價,如果不知道使用什么就用金字塔噪聲吧。
這里只是拋磚引玉,有興趣的同學(xué)可以等我放出代碼后試一下Perlin噪聲的各種參數(shù),還可以嘗試使用IDFT實現(xiàn)粉色噪聲等有色噪聲。
下篇看心情更新吧,最近比較忙,各位諒解。

引文
https://arxiv.org/abs/2208.12242
https://www.crosslabs.org/blog/diffusion-with-offset-noise
https://wandb.ai/johnowhitaker/multires_noise/reports/Multi-Resolution-Noise-for-Diffusion-Model-Training--VmlldzozNjYyOTU2