講在最前面,市面上的 Stable Diffusion, Lora 的相關影片相當多,如果有興趣的人可以去找影片看看,我這邊僅只是記錄一些實驗性的東西。
Lora 相關硬資料
基本的論文跟相關資料在這邊,由於在下英文很爛,加上本身是做水電的,所以多半是有看沒有懂,只能一直問 Google 或是 ChatGPT(但後者其實...)。
- LoRA: Low-Rank Adaptation of Large Language Models
- High-Resolution Image Synthesis with Latent Diffusion Models
- Cheng-Han Chiang, Yung-Sung Chuang, Hung-yi Lee, “AACL_2022_tutorial_PLMs,” 2022.
- Huggingface, Using LoRA for Efficient Stable Diffusion Fine-Tuning
- What are LoRA models and how to use them in AUTOMATIC1111
- Microsoft Lora
- Huggingface PEFT
- Low-rank Adaptation for Fast Text-to-Image Diffusion Fine-tuning
關於教學影片看這個就好了,不過這邊就是講個大概,剩下的得自己嘗試。
Youtube, ULTIMATE FREE LORA Training In Stable Diffusion! Less Than 7GB VRAM!
Lora 訓練準備
上面的影片可以解決大概 8 成以上的問題,不過本著實驗精神,所以我還是準備了一些東西來驗證。這邊有一個關於 Lora 訓練圖片準備細節 可以參考。
根據 Lora 的訓練圖集,所以我準備了這些圖片。
- 98 張訓練集圖片
- 520 張正規化圖片 (REGULARIZATION IMAGES)
我實在不知道要怎麼把 REGULARIZATION 翻譯成比較合適的文字,只好用比較通用的中文翻譯來寫。這邊說明一下 REGULARIZATION IMAGES 做了什麼事情。主要的功能有兩個,
- 識別類 (Class)
- 避免過度擬合 (Overfitting)
舉個比較淺顯易懂的例子,如果你的訓練圖片是你自己設計的未來汽車,那麼,你的 REGULARIZATION IMAGES 就得準備一些「汽車」的圖片 (除非你的汽車沒有四顆輪子),訓練集的圖片會與 REGULARIZATION IMAGES 去做比對,取用 REGULARIZATION IMAGES 有的,並排除訓練集裡沒有的部分。換句話說,以汽車為例子,你的 REGULARIZATION IMAGES 就是一大堆汽車的圖片,這樣就可以避免在訓練時,他變成自行車或機車之類的東西。這樣一來,你在訓練的過程中就能確保「汽車」這個類 (Class) 會被保存,而且不會歪掉。
接著,這些圖片該怎麼準備?我參考了不少作法,但大部分(例如說 b 站)都是二次元的訓練,真的要拿到三次元來用其實是不太合用的。所以,我就自己弄了一個生成老婆的 Lora 來驗證關於訓練輪次 (Epochs) 與權重 (Block weight)、過度擬合 (Overfitting) 之間的數據實驗。
回到剛剛我所準備的圖片,為了實驗這些數據,所以這些圖片都有經過預處理。
- 訓練集圖片僅以人臉五官為主,並特別去背,尺寸為 768x768 的大小。
- 正規化圖片 (REGULARIZATION IMAGES),為 人物本人 半身、全身照,並裁切成 768x768 的大小。
以訓練人臉五官的概念來說,REGULARIZATION IMAGES 的基本用意在於,確保人的頭部(或臉部)的相對位置,在 REGULARIZATION IMAGES 是正確的。換句話說,這樣做的用意,是不會讓你訓練出來的人臉出現在不該出現的位置上。如果以剛才的汽車為例子,就是你不會產出臉長在肚子上的情況。請留意,我這邊是使用 本人 的照片來當作 REGULARIZATION 的圖片使用,如果你的訓練集圖片與 REGULARIZATION IMAGES 是不同的人,我還是建議把 REGULARIZATION IMAGES 裡面的人臉抹掉,避免訓練出什麼奇怪的東西。
同理,衣服、鞋子或是其他飾品的概念也是雷同,我後面會提到。
好的,根據 剛剛那篇文章,我們準備的資料夾如下,
TrainData
- 50_hina wife a woman
- IMG_01.png
- IMG_01.txt
- ...
- ...
- reg
- 20_hina wife a woman
- IMG_123.png
- IMG_456.png
其中 100_hina a woman
就放有我們的訓練集圖片,而 20_hina a woman
則放有我們的正規化圖片 (REGULARIZATION IMAGES)。這邊就不解釋 100_
跟 20_
是什麼意思了。至於 .txt
檔案怎麼產生?你可以使用 Stable Diffusion WEBUI 的 Train/Preprocess images
工具來產生,或是使用 Kohya_ss GUI 的 Utilities/BLIP Captioning
來產生都可以。產出的檔案記得要打開來確認一下,有沒有跟圖片不符合的描述。 例如我老婆的照片有 12 張被加上 1boy 的提詞(我沒有業配),檢查並且調整好提詞之後,再繼續往下做。
請注意!正規化圖片 (REGULARIZATION IMAGES) 可以不使用提詞文字檔,你堅持要用也可以。
Lora 訓練設定與過程
接著,我把他放到 Kohya_ss GUI 裡面,使用 Dreambooth LoRA 開始跑訓練模型,基本上的參數大概是這樣,
{
ss_batch_size_per_device: "1",
ss_bucket_no_upscale: "True",
ss_cache_latents: "True",
ss_caption_dropout_every_n_epochs: "0",
ss_caption_dropout_rate: "0.0",
ss_caption_tag_dropout_rate: "0.0",
ss_clip_skip: "2",
ss_color_aug: "False",
ss_enable_bucket: "True",
ss_epoch: "10",
ss_face_crop_aug_range: "None",
ss_flip_aug: "True",
ss_full_fp16: "False",
ss_gradient_accumulation_steps: "1",
ss_gradient_checkpointing: "False",
ss_keep_tokens: "0",
ss_learning_rate: "5e-05",
ss_lowram: "False",
ss_lr_scheduler: "constant",
ss_lr_warmup_steps: "0",
ss_max_bucket_reso: "768",
ss_max_token_length: "150",
ss_min_bucket_reso: "320",
ss_mixed_precision: "bf16",
ss_network_alpha: "128.0",
ss_network_dim: "128",
ss_network_module: "networks.lora",
ss_noise_offset: "None",
ss_num_epochs: "10",
ss_optimizer: "bitsandbytes.optim.adamw.AdamW8bit",
ss_output_name: "hina_lora_v2",
ss_resolution: "(768, 768)",
ss_sd_model_name: "runwayml/stable-diffusion-v1-5",
ss_seed: "1234",
ss_shuffle_caption: "False",
ss_text_encoder_lr: "5e-05",
ss_total_batch_size: "1",
ss_training_comment: "None",
ss_unet_lr: "0.0001",
ss_v2: "False"
}
上面的內容翻譯一下大概是(請注意!以下設定是基於實驗,如果你的設備撐不下來請斟酌使用),
- Source Model 使用
runwayml/stable-diffusion-v1-5
。 - Mixed precision, Mixed precision 使用
bf16
你要改用fp16
也可以。 - Caption Extension 填入
.txt
。 - Learning rate 預設是
0.0001
,而我使用的是0.00005
。 - LR Scheduler 選
constant
也有人建議cosine_with_restarts
(效果更好?)。 - LR warmup 目前看得到的教學都寫
0
,但 Kohya_ss GUI 預設是10
,我這次訓練使用0
。 - Optimizer 選擇
AdamW8bit
。 - Network Rank (Dimension)、Network Alpha 我都使用
128
,後者 (Network Alpha) 可以比前者小,用64
之類的。 - Max resolution 我們準備的圖片是 768x768,這邊就寫
768
。 - Clip skip 寫
2
(魔術數字,效果較好)。 - 勾選
Enable buckets
。 - Max Token Length 我這次使用
150
。 - 勾選
Use xformers
,Flip augmentation
。 - 如果你的顯卡 VRAM 在 8GB 以下,請勾選
Memory efficient attention
。
以下為了實驗所以才這樣設定,
- 勾選
Save training state
- Max train epoch 寫
10
,大家都說訓練10
次,甚至20
次,真的會比較好? - Max num workers for DataLoader 我這邊使用
8
。
另外,大部分的教學會提及 Train batch size
的設定,這個數字的意思是每次跑的步數要放幾份資料進去跑,換句話說,如果你的步數是 4,000
,而 Train batch size
這裡設定為 2 的話,那麼你的總步數就會變成 2,000
步。
具體來說,比較高的 Train batch size
數字,會加速整個學習的過程,但是相對的,學習精度會下降,所以基本上,這邊必須要看你所提供的訓練集的數量,來決定你是不是要提高這個數字。
通常,市面上的教學都會說「少量的訓練集」訓練出高品質的模型。嗯,關於這一點我還是有點存疑就是。不過由於我是實驗性的測試,所以這個數字我維持在 1
讓他每次學習就跑一個 batch 就好。
當然,我也試過 2
或是 3
甚至是 4
,以結果論來說,1
的效果還是比較好,特別是當你的訓練集圖片的數量相當少的時候。
再提醒一次,由於這是實驗,我先說一下使用的機器規格,
- Intel 13th i5 with 64GB DDR5
- NVIDIA A4500 20GB GDDR6 ECC
Lora 訓練初步結果
我說明一下上述的訓練過程所使用到的「步數」,在 Kohya_ss 中的訓練,「步數」是由資料夾、圖片數量以及剛剛的 Max train epoch
來決定,所以,根據我準備的資料,我所需要跑的訓練「步數」大概是,
「步數」 = 98 x 100 x 10 = 98,000
也就是說,如果你照抄我的設定,那麼你就會跑 98,000 步,才會把整個訓練跑完。我的機器跑 1 個輪次 (Epoch) 大概要花兩個半小時,
所以跑完 10 個輪次,大概花了我 27 個小時左右。
那麼,這 27 個小時訓練了 10 次的結果如何?我們來看一下。這是每一個輪次會自動輸出的 Sample 圖檔,由左上到右下依序,無固定種子,使用 Euler a
產出圖片。
你可以看到大概是 5, 6, 7 次的訓練輸出是比較理想,而第 8, 9 次就已經出現過度訓練的狀況,第 10 次更是明顯。
接著,我使用 X/Y/Z Polt 分別將每一次的模型,依照權重 0.2, 0.25, 0.4, 0.5, 0.75, 0.8, 1.0 來輸出固定種子檔案,用以比較差異。
從上述結果中,紅色框線的部分是我個人比較可以接受的區塊。所以就結論來看,我們準備了 98,000 步的訓練,其實在第 7 個輪次 (Epoch) 就已經能符合預期。換句話說,多次的訓練並不一定能拿到比較好的結果。但是,這邊我必須打個問號,如果是高解析度圖片,訓練步數真的可以少一點嗎?
LoRA Block Weight 權重調配
這是一個 Stable Diffusion 的外掛,他可以將 LoRA 所作用域的 17 層分別給予權重(至於哪 17 層就不要問我了)。
這個外掛可以自定義權重調配的變數,也就是說你可以在各層中間去調配每一層的權重,用以去跟其他的 Lora 做混搭,或是與原本的模型調配做出更好的輸出。這邊的範例調配數值是,
HINA4:0.25,0.25,0.25,0.25,0.75,0.5,0.75,0.75,0.8,0.8,0.8,0.85,0.85,0.85,1,1,1
人物由於沒有「畫風」的問題,所以中間層可以拉大,至於 OUT 的部分是否要放大就看訓練的資料,每一種 Lora 的調配都不太一樣,需要慢慢嘗試才知道什麼結果比較好。
LoRA 高解析度訓練
最初我們提及了訓練的資料夾結構與正規化圖片 (REGULARIZATION IMAGES),我這邊也測試了一個高解析度的輸出,有興趣的人可以參考一下,
TrainData
- 100_hina wife a woman
- IMG_01.png
- IMG_01.txt
- ...
- ... 共 20 張,1024x1024 圖片,去背五官,多角度照片。
- 20_hina portrait
- IMG_001.png
- IMG_001.txt
- ...
- ... 共 50 張,768x768 圖片,全身、半身,適度去背,多角度照片。
- reg
- 5_hina wife a woman
- IMG_123.png
- IMG_456.png
- ...
- ... 共 500 張,全身、半身,多角度照片(可以跟底下資料夾共用同一份圖檔)。
- 5_hina portrait
- IMG_123.png
- IMG_456.png
- ...
- ... 共 500 張,全身、半身,多角度照片(可以跟上方資料夾共用同一份圖檔)。
請注意 reg
底下正規化圖片 (REGULARIZATION IMAGES) 資料夾的名稱,必須與訓練集相同,只有步數不同。接著關於訓練輪次 (Epoch) 的問題,這樣的訓練總共需要,
「步數」 = (20 x 100 + 20 x 50) x epoch = 3000 x epoch
另外在 Additional parameters
的地方,由於我這邊所使用的圖片介於 512px ~ 1024px 之間,所以額外填入了參數,
--min_bucket_reso=512 --max_bucket_reso=1024
關於訓練所使用的參數,可以參考這個地方:
我使用的輪次 (Epoch) 是 8
,這樣跑下去的結果大概是這樣:
那麼,準備資料集怎麼做會比較好?剛剛有說了,扣除掉你想要訓練的人臉跟要準備的正規化圖片 (REGULARIZATION IMAGES) 之外,這邊具體用一張圖片來說明訓練集的安排。
根據上面這張照片,你可以提取的部分有:
- 紅框:臉部照片。
- 橘框:單純訓練「衣服」。
- 綠框:單純訓練「鞋子」。
- 藍框:去除臉部照片,可用於訓練身體動作。
- 紫框:全身照片,可用於正規化圖片 (REGULARIZATION IMAGES)。
所以說,對於模型訓練你就能分的更細:
TrainData
- X_hina wife a woman
- IMG_01.png
- IMG_01.txt
- ...
- ... 放紅框的照片。
- Y_hina portrait
- IMG_001.png
- IMG_001.txt
- ...
- ... 放籃框的照片。
- Z_hina clothing
- IMG_001.png
- IMG_001.txt
- ...
- ... 放橘框的照片。
- W_hina shoes
- IMG_001.png
- IMG_001.txt
- ...
- ... 放綠框的照片。
- reg
- R_hina wife a woman
- IMG_123.png
- IMG_456.png
- ...
- ... 放紫色框照片。
- O_hina portrait
- IMG_123.png
- IMG_456.png
- ...
- ... 放紫色框照片。
其中的 X
,Y
,Z
,W
,R
,O
請自行依照你的圖片數量,來斟酌你每張圖片所要訓練的次數。另外,我這邊只針對臉部及半身照片有做正規化 (REGULARIZATION),鞋子跟衣服的部分沒有,你要做也可以,這樣可以在學習過程中,不要讓衣服或是鞋子長在不對的地方。
結語
其實最難的是調整提詞文字檔。