# SD fine-tuning 常見QA
_2023-03 初稿; 2023-09 微更新_
#### 前言:
模型訓練沒有絕對
以下皆僅供參考
如果效果不如預期請自己調整資料集超參數又或者那個東西本來就不可能練好
#### 還是前言:
圖像生成模型好壞無客觀衡量標準
覺得某個東西效果不好請明確說明問題在哪並且最好給出範例
#### Q1: 模型訓練是什麼?
一般機器學習訓練模型泛指利用資料最佳化模型參數以達到想要的功能
像是什麼alphago,sd,gpt4都是訓練出來的
不過從頭訓練大模型並非一般人能夠負擔
所以接下來要討論的是如何從現有的sd模型進行微調(fine-tuning)以達到想要的效果
#### Q2: 如何對SD進行訓練?目的為何?
如上所述,訓練需要準備相對應的資料集,在SD的情況是圖片以及每張圖片對應的文字描述
訓練的目的是為了得到接近訓練資料的內容,如角色、物品、服裝、畫風、地點、動作、表情以及其他各種抽象概念
常見的訓練方式分為下列幾種
- Textual inversion (~50KB): 幫概念找到相對應的文字embedding,可以用a1111 webui直接練
ref: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Textual-Inversion https://huggingface.co/docs/diffusers/training/text_inversion
- hypernetwork (~100mb): 在unet cross attention上面接上去對更改key跟value的小network,一樣可以用a1111 webui練,現今lora更為流行
ref: https://stable-diffusion-art.com/hypernetwork/
- Native training / dreambooth (~2GB): 直接調整整個模型的參數,理論上效果最好但最耗費資源出來的模型也最肥,可以使用的trainer包括
- EveryDream: https://github.com/victorchall/EveryDream2trainer#readme
- Kohya trainer: https://github.com/kohya-ss/sd-scripts
- Naifu: https://github.com/Mikubill/naifu-diffusion
- StableTuner: https://github.com/devilismyfriend/StableTuner
- SSDT: https://github.com/CCRcmcpe/scal-sdt
- HCP Diffusion: https://github.com/7eu7d7/HCP-Diffusion
- OneTrainer: https://github.com/Nerogar/OneTrainer
- LoRa (5~100mb): 訓練的過程把weight difference預設成兩個low rank matrix的乘積 $\Delta W =AB$ 進而減少對VRAM的使用以及最後檔案的大小
最一開始引來SD的是 https://github.com/cloneofsimo/lora
但目前跟webui可以通用的主流是使用 Kohya trainer https://github.com/kohya-ss/sd-scripts
- LyCORIS (5~100mb): 由台灣這邊琥珀青葉主導的專案,含有多種模型,詳情請看readme或直接來discord問我們
https://github.com/KohakuBlueleaf/Lycoris
- Pivotal Tuning / NTI: 將textual inversion跟其他方式的訓練結合,專注於訓練新概念的embedding以及模型本身unet的部份
原本的Lora repository支援Pivotal Tuning for LoRa不過好像webui沒辦法直接用
Naifu, HCP支援Pivotal Tuning for native fine-tuning,詳情請洽BP系列
#### Q3: 可不可以給我一個明確的訓練流程?
1. 準備資料: 載圖、爬圖、打標
2. 選擇訓練用的基底模型
3. 選擇訓練用的trainer
4. 調整超參數
5. 開始訓練
6. 測試模型,如果不滿意回到前面某一點重新開始
通常1跟6最花時間
7. Optional: 壓縮模型、上傳civitai、用訓練好的模型生圖、寫tutorial、訓練下一個模型...
#### Q4: 基底模型怎麼選擇?
Update: Lora動畫相關一些基本特性可以參考 https://civitai.com/models/26415/a-certain-theory-for-lora-transfer
主要是以套用到其他模型作用的角度出發
大方向是練角色用上游模型
練風格用混合模型
不過更詳細的使用靈活度品質等等依舊不明
否則一般推薦使用訓練出來、跟各個模型血緣關係比較近的,像是動畫使用NAI,真人使用SD1.5 / 2.1等等
實際上個人動畫使用AC跟BP也沒什麼大礙
雖然不推薦使用混合模型當機底但拿anything或者orange練的也大有人在
不同模型訓練出來的效果都不一樣,可以自己實驗
#### Q5: 如何選擇trainer?
市面上的trainer基本上大同小異,一般來說通常選擇大家在用的自己用的順手的就行,不過大致可以分成以下三種
- colab: 適合想要白漂google資源的人使用,缺點是訓練時數受限,檔案傳來傳去很麻煩,想瑟瑟還要小心不要被ban帳號,例
- https://github.com/Linaqruf/kohya-trainer
- https://colab.research.google.com/drive/1fs7oHytA4Va0IzDK-F8q_q9RIJRIh5Dv
- gui: 適合喜歡圖形界面的人使用,例
- StableTuner (https://github.com/devilismyfriend/StableTuner)
- Kohya trainer gui (https://github.com/bmaltais/kohya_ss)
- command line, notebook: 適合遠端使用跟喜歡把東西打好後只要呼叫 python train.py 的人使用,例
- EveryDream (https://github.com/victorchall/EveryDream2trainer)
- lora easy training scripts (https://github.com/derrian-distro/LoRA_Easy_Training_Scripts)
- naifu (https://github.com/Mikubill/naifu-diffusion)
- ssdt (https://github.com/CCRcmcpe/scal-sdt)
另外值得注意的是下面各個功能現在各大trainer都有支援
- Aspect ratio bucketing: 自動把資料集圖片調整到適合大小餵給network(可以是長方形,只需要兩邊都是64的倍數),因此不用自己裁成正方形跟調整大小
- Per folder repeat: 可以調整一個epoch內每個資料夾的圖片要訓練多少次,可以用來平衡不同的概念
- Cache latent: 先用vae把圖片encode到latent space節省訓練時間跟vram使用,只是不知道為什麼現在幾乎都cache deterministic的latent...
- Training at different cilp skip: 顧名思義
其他細節的差異像是Everydream的data loading+cache latent速度是kohya trainer的五倍以上,naifu支援帶embedding訓練,LyCORIS目前基本上是接在kohya trainer上面等等請自行體會
#### Q6: 超參數是什麼?要怎麼調整?
超參數(hyperparameter)是會影響訓練過程乃至訓練結果的各種可以調控的變因,不同方法乃至不同的trainer可以調整的超參數都不一樣,常見而且比較重要的有下列幾種
- Leraning rate: 控制你學的多快,越大學越快但太大可能會學懷,而且也可能導致學的東西比較差(aka過擬合),太小學比較慢甚至小到某個程度會完全學不起來,推薦數值在下面optimizer的部份一起說
- Batch size / gradient accumulation: 決定累積多少sample的訊息再進行一次update,實際影響不明,原則上可以盡量開大,但接近sample size可能會出問題(需實驗證實
- Resolution: 訓練時使用的圖片大小(因為也有長方形所以基本上會縮放到這個大小附近),一般除了native training均推薦使用base model的resolution,像是SD1.5就用512,SD2.1就用768,不過用高resolution訓練可以學到較多的細節,包括更精緻的背景或是瞳孔等等,所以在512 base的模型上面訓練768的LoRa等等的用處尚待證實,值得注意的是從512到768基本上訓練時間會變成兩倍,另外也有逐漸增加resolution的這種方法
- Clip skip: 就是使用模型的那個clip skip,大原則是使用跟訓練要對上,但實際沒對上還是可以加減有效果,雖然很多地方都推薦動畫用clip skip 2訓練但個人長年都是用clip skip 1也沒有大礙,之前在native fine-tuning的比較是發覺clip skip 2比較容易複製貼上,實際差異仍需更多實驗證實
- traning steps / training epochs: 訓練多久,個人衡量對於每個concept大概訓練個1000~10000+ (step X batch size)
- caption dropout rate: 有多少機率會把圖片caption拔掉訓練,會需要這麼做的原因主要是由於使用cfg (classifier free guidance)其實會需要用到沒有guidance的模型,不過對於小規模訓練通常沒什麼差,否則推薦5%-15%
- cilp token length: 訓練時讀caption的多少token當input,原本SD是用75,後來NAI加長到225,實際對訓練的影響仍需實驗
- noise offset: 請看 https://www.crosslabs.org//blog/diffusion-with-offset-noise
- training precision / amp: 一律推薦開amp/使用bf16如果無法的話請乖乖用fp32訓練
- Network dimension / alpha / conv dimension / conv alpha / number of vectors per token / number of layers etc.
對應到 LoRa / LyCORIS / textual inversion / hypernetwork 等個別的 argument,共通點是都影響訓練的內容的大小(除了alpha影響訓練的東西如何作用),雖然直覺是檔案越大可以學到越多東西,但事實是你要學的東西可能不需要那麼大的檔案,而且對這些進行調整後其他超參數(尤其是learning rate)也很可能需要相對應的調整
其他不影響訓練的選項 (應該不能算是超參數就是)
- gradient checkpointing: 以時間換取空間,省vram但訓練久一點
- save_every_....: 多久存檔一次,用來之後做各種比較用
- sample_every_....: 訓練過程多久生成圖片一次,用來看目前學的如何
- sample prompts: 對應到上面,用來生成圖片的prompt
#### Q7: Optimizer是什麼?Learning rate Scheduler是什麼?怎麼選擇?
這些東西簡單來說就是影響模型訓練過程每一步怎麼更新自己的參數,SD fine-tune常見的optimizer包括 Adam, AdamW, DAdaptation, AdaFactor, Lion 以及Adam和AdamW的8bit版本
一般來講是否使用8bit版本對訓練效率跟最後模型品質影響似乎都不大
Learning rate scheduler則是決定這些optimizer使用的learning rate怎麼隨者時間變化,常見的有constant, cosine, cosine with restart等等,另外也可以決定要不要加warmup,各種選項都有人用所以沒有放之四海皆是最佳解的選項
不過個人認知 native fine-tuning Adam(W) lr 大約放在 1e-7 ~ 1e-5 這個範圍,1e-6上下為佳不過SD2.1好像需要比較小
至於 LoRa/LyCORIS 配 Adam(W) 則約莫在 1e-5 ~ 1e-3 這個範圍,1e-4 ~ 1e-3 尤其常見
使用cosine scheduler可以使用的lr會比constant scheduler高些
DAdaptation, adafactor, prodigy 等雖然可以把 learning rate放在1左右讓他們自己調整,但實際效果因資料集而異,常常也需要調整其他參數
剩下的包括Lion或者textual inversion和hypernetwork需要的learning rate請別人補充
#### Q8: 為什麼有unet lr跟text encoder lr?
這是玄學,雖然假設是unet更影響畫風text encoder更影響構圖
unet練壞了會導致出來的圖不堪入目而text encoder練壞了會導致模型不聽從prompt使喚
不過後者由於加加減減都會發生所以理想上對text encoder的訓練要適可而止,但目前要對模型訓練最有效的也是對text encoder進行更改(由於pivotal tuning尚不盛行)
這成為了一個兩難的局面,市面上常見的包括把text encoder lr設置成unet lr一半,或者只訓練text encoder一定步數等等
但個人還是兩個放同lr下去訓練到結束就是
#### Q9: 所以LoRa和LyCORIS那些dimension和alpha到底是什麼?
上面提到的low rank decomposition $\Delta W = AB$, 如果 $W$ 是個 $m\times n$的矩陣,然後dim是$d$,那麼$A$跟$B$大小分別是$m\times d$跟$d\times n$,LoHa也是類似的概念
至於alpha則是對於這個$\Delta W$的scaling,最後使用的weight是 $W + (\alpha/d)\Delta W$
因為一般來說dim越大需要的lr越小,把alpha固定住等於讓它自動去調整lr,否則alpha越大需要的lr越小,雖然很多人把alpha設置成dim或者dim/2,不過lora的paper可是有這麼一段話
> When optimizing with Adam, tuning α is roughly the same as tuning the learning
rate if we scale the initialization appropriately. As a result, we simply set α to the first r we try
and do not tune it. This scaling helps to reduce the need to retune hyperparameters when we vary r (Yang & Hu, 2021).
而且實務上很多training的net dim設置到16頂多32就很夠用了,所以完全把alpha固定到1應該是沒有問題的才對
#### Q10: 訓練講很多了,但我到底要怎麼準備資料集?
大方向是,圖片盡量多元、盡量多,並且有足夠的圖片準確表達你想要訓練的概念,文字描述越精確越好然後用來區分開不同的概念,就算有很多沒那麼符合概念的圖片只要文字說明夠清楚就行。而且模型沒有這麼脆弱,它會盡量自己找到共通點歸納出概念該有的樣子,所以除非你要練一些超難的東西(像是姿勢),必須要極度擬合某些資料才可以穩定出圖,不過通常這樣練出來的模型也很難用就是。
圖片的部份可以自己載或者爬,推薦
- imgbrd grabber: https://github.com/Bionus/imgbrd-grabber
- gallery dl: https://github.com/mikf/gallery-dl
打標可以手動打或者使用自動化工具包括tagger, captioner,可以參考kohya的repository像是
- https://github.com/kohya-ss/sd-scripts/tree/main/finetune
也可以從某些資源大量擷取圖片,像是自己這套從動畫準備資料集的流程
- https://github.com/cyber-meow/anime_screenshot_pipeline
比較關鍵的
- 每個概念對應到一個trigger word:這點所有訓練皆通用,雖然有些lora或hypernet只訓練一個概念不需要trigger word就有效果,但個人認為這樣是很不健康的,理想上你只希望模型一小部份受到改變避免過擬合
- 避免不同概念有過度類似的trigger word或是一個概念有會被tokenizer搞壞的trigger word:在沒有練embedding來取代trigger word的前提下,trigger word會作用全是靠tokenizer拆解後過text encoder,因此過度相似的trigger word, XXX1, XXX2 會導致模型難以對其進行區分,會被拆壞的像是aa3241會導致難有顯著效果
- trigger word 會訓練到的是還沒有被 tag 的東西: 雖然這點有點玄而且也稱不上100%正確,但目前測下來看來在一定的步數內 trigger word 的確會優先補足圖片裡面有而 caption 沒有描述的內容,這代表說
- 訓練畫風描述的越詳細越好,實際上測試訓練畫風不放tag效果很差
- 角色訓練盡量拔掉想要固定在角色的特徵,常見的包括眼睛頭髮顏色,固定服裝對應等等
也可以稍微參考這邊寫的
https://rentry.co/lora_train
#### Q11: Regularization set是什麼?
為了避免模型完全變成訓練資料的模樣(尤其在訓練資料集極度單一的時候),確保模型多樣性而額外準備的資料集,雖然一開始是說使用模型自己生成的圖片但個人覺得這沒什麼意義。
我的做法是,有一個三萬張左右的圖片集,裡面包含各種不同類型的圖片正常打標也有自己的trigger word,每次訓練都會使用,並且利用repeat平衡到跟真正要訓練的概念大概是1:1左右。
#### Q12: 什麼是概念平衡?
想像要練兩個概念,第一個有1000張圖片,第二個只有10張,那麼讓第一個repeat 1第二個repeat 100可以確保在同一個epoch內對兩個概念的訓練是均衡的,雖然概念2的訓練勢必會比較差,不過這是較少圖片的必然結果。
理論上如果不特別給repeat,訓練夠久還是可以學會第二個概念,可是這對第一個概念可能多了很多額外不需要的訓練,所以概念平衡可以看作某種加速訓練的方法。
#### Q13: 可以用AI生成的圖片訓練嗎?
雖然個人不建議不過如果要這麼做的話請慎選拿來訓練用的AI圖片,如此訓練而品質不錯的模型也不少。值得注意的是AI訓練學進去速度特別快跟其他一起學習可能需要分開調整repeat。
#### Q14: 我資料圖片很少,該怎麼辦?
可以考慮各種裁切,翻轉,甚至是先訓練好一個模型多生一些適合的圖重新訓練一次。利用現有工具如controlnet來生成類似圖片也是一個方法。因為圖片少上面提到的regularization set可以有效避免模型過擬合。
#### Q15: 我可以從練到一半的模型繼續練嗎?
技術上可行,實際上因為很多trainer進行resume沒有存optimizer state導致從存的檔案訓練跟直接一直訓練下去並非等價的,所造成的影響仍需評估
(在個人的訓練中用同樣的超參數直接resume會導致模型default風格被大幅固定並且角色跟風格更加綁訂不過還是可以借由prompt更改)
#### Q16: 我使用某某trainer遇到XXX問題
關於xformers請用pip install --pre xformers安裝0.0.17
剩下的我既不會用windows也不會用colab所以除非你也用linux否則請洽別人
#### Q17: 好那我決定開始訓練了,我該怎麼做?
~~買個4090~~
資料準備好後關於動畫相關sd1系列個人推薦
fine-tuning: Everydream trainer, Adam8bit, lr 2.5e-6, cosine scheduler
LoCon: Net dim 16, conv dim 8, alpha 1, AdamW lr 2e-4, constant scheduler
LoHA: Net dim 8, conv dim 4, alpha 1, AdamW lr 2e-4, constant schduer
以上的dimension可以更小但應該不需要更大
關於lr的部份還需要更多實驗不過這個上下應該都是ok的
#### Q18: 我訓練好的lora A跟lora B合起來效果不好
所以為什麼不一起訓練呢,model merge就是黑魔法
會work值得慶幸不會work也正常
model transfer同理
#### Q19: LoRa/LyCORIS比直接訓練模型好因為可以接到不同模型上面
有個東西叫做add difference merge,減掉訓練用的基底模型加到其他模型上面跟LoRA/LyCORIS接到其他模型上面是等價的
#### Q20: 為什麼網路上其他地方看到的跟你這裡說的不一樣?
您不妨自己實驗看看
#### Q21: 一個lora只能訓練一個概念?訓練角色要盡量使用單人圖?訓練集最好要有X1~X2張圖片?LoRA應該要把dimension開到128然後alpha=dim?圖片要裁成正方形?資料集只能有高品質的圖片?圖片需要去背?應該拿透明圖當regularization?
以上皆非,僅供參考
- https://civitai.com/models/14346/umamusume-locon
- https://civitai.com/models/21305/tenten-character-lohafullckpt
#### 延伸閱讀
- https://rentry.org/lora_train
- https://rentry.org/LyCORIS-experiments
- https://rentry.org/lora-training-science
- https://followfoxai.substack.com/p/stable-diffusion-fine-tuning-experiments