使用 kohya_ss 訓練 LoRA 時的一些技巧與想法

Jason Kuan
11 min readMar 29, 2023

隨著 Stable Diffusion 風潮的興起,在網路和 YouTube 上出現了不少有關訓練的教學文。我自己在玩了 SD 之後,也馬上拿了自己的照片訓練了一番,為的就是可以在 SD 上面盡情地惡搞自己…XD

然而,訓練了一段時間後,我開始好奇在 koyha_ss 上有不少訓練參數,那這些參數代表的意義是什麼?又如果我今天想要快速產出人臉 LoRA,要怎麼樣的設定才能達成呢?以下依序分享:

LoRA基本概念

LoRA (Low-Rank Adaptation) 是微軟提出的一種 Domain Adaptation 方法,詳細可以參考台大 Hung-yi Lee 的 YouTube 教學影片。這邊簡單說明,LoRA 是一種不改變 SD 本身模型前提下,用額外附加權重的方式來轉移學習的方法。以 SD1.5 為例,如下圖:

在龐大的 4.3GB 之中,UNet共含有 16 個 Attention Blocks。這 16 塊 Blocks 每個都會局部地影響生成的結果,有些可能影響了整體的畫風,有些則影響了某些人物的細節。

這是SD裡面UNet的架構,存著大量生圖的權種值

SD 基底模型花了好幾天和好幾張顯卡(這過程非常耗費金錢)才訓練出來。然而,在訓練時他們所採用的資料集是比較通用的 LAION 資料集,因此它生成的圖片都較為單一和無聊。社群為了將這個模型訓練成能夠生成其他風格的圖片,就需要進行 Domain Adaption,而 LoRA 就是其中一種方法。

為了避免變動 SD 基底模型, LoRA額外設置了一個獨立的區域存放權種值。整個 SD1.5 包含 UNet 中 16 塊和 Text Encoder 的 1 塊,共 17 個 Transformer Blocks,LoRA 模型的工作就是輔助這 17 塊 Blocks 去生成我們想要的圖片。

這17塊在 lora-block-weight 分別叫 BASE,IN01,IN02,IN04,IN05,IN07,IN08,MID,OUT03,OUT04,OUT05,OUT06,OUT07,OUT08,OUT09,OUT10,OUT11

訓練出來的LoRA不但檔案比SD基底模型小,而且可以搭配其他LoRA去疊加,再去設定權重去影響圖片,這種模式給了使用者很大的組合空間。

圖片並非真的生成,只是網路找圖來解釋生成原理,現實應該不會這麼理想XD…

但要注意的是,有些LoRA如果訓練出來的權重值差異很大,會嚴重影響到產圖的結果,這也是為什麼在組合多個LoRA時,圖片翻車的機率會特別高。

如下圖的翻車現場…就是權種值過大

當我發現 SD 可以做 LoRA 時,我也很興奮地參考網路上的教學影片。然而,隨著訓練次數的增加,開始了解一些設定參數的含義後,發現有些參數如果調整得當,可以省下很多時間和精力。以下是我分享的幾個方法:

1. 資料夾命名與訓練epoch設定

很多教學都會告訴你在 image/ 底下要有一個以數字加內容命名的資料夾。他們的說法是:

「理想步數是 1500 步左右,用 1500 張圖片除以圖片數量,如果小於 100 就用 100。」

我第一次訓練 LoRA 時,使用了將近 200 張照片,1500/200 < 100,因此我把資料夾命名為 100_JasonKuan,即使是使用 Epoch=1,我也訓練了快 20,000 步。雖然可以達到預期的效果,但是這樣的訓練時間相當漫長。

經過我多次實測,目前的 1500 步只是供參考。我用一些朋友的照片進行測試,有些可以在 1000 步以內生成不錯的效果,有些則需要訓練到 6000 多步才能像本人。以下 Demo 會先以 1500 步介紹為主。

如果照原先網路上教法,像我資料夾中有40張,設成100,要跑4000個Steps

然而,這樣的訓練方法有一個很大的缺點。在 kohya_ss 上,如果你要中途儲存訓練的模型,設定是以 Epoch 為單位而非以Steps。如果你設定 Epoch=1,那麼中途訓練的模型不會保存,只會存最後的結果。若你使用了很多張圖片來訓練,結果不小心過度訓練了,你就直接得到了一個訓練爛掉的模型,這中間訓練的時間就全部浪費了。

我是怎麼做的?

首先,在資料夾命名上的數字代表的含意是「在這個資料夾中,每張圖片要看 X 次,才算一個 Epoch」。因此,我索性直接把資料夾名稱命名為 1_JasonKuan,表示每張圖片只需要看一次就算一個 Epoch。

然後回到 kohya_ss 中,我把 Epoch 設為 38,每 8 個 Epoch 存一次模型。這樣的設定可以讓我更有效率地訓練模型,也可以在中途存下模型,避免因訓練失敗而浪費時間和資源。

這樣一來,我們就可以像先前一樣訓練將近 1500 步,而且中途訓練生成的模型也可以後續拿來檢驗。

那麼,資料夾名稱前的數值什麼時候會用到大於1呢?

我認為只有在需要識別多個物件時才需要修改。舉個例子,如果我今天要訓練台灣常見的美食 LoRA,我找了 20 張滷肉飯的照片和 5 張牛肉麵的照片。如果你的資料夾命名為 “1_braised_pork_rice” 和 “1_beef_noodle_soup”,那麼每個 Epoch 就只會學習 20 張滷肉飯和 5 張牛肉麵,這會導致牛肉麵的學習次數偏少。

這種情況下,我會把牛肉麵資料夾的命名改成 “4_beef_noodle_soup”,這樣每個 Epoch 都可以看到 20 張滷肉飯和牛肉麵了。

2. Network Dimension and Network Alpha

在下方的設定中,有一個 Network 的設定也是很重要的。Dimension 可以看作是 LoRA 的腦容量大小。這個數值調得越高,你的 LoRA 模型就會越大。概念上有點像記憶力,如果你今天有很多物件要 LoRA 學習,就需要比較大的數值。

而 Alpha 值所代表的是模型廣義化 (Generalization) 的能力,你可以把它當作是模型的想像力。因此,綜合上面所述,如果你要訓練的是:

一個物件(人臉、角色等),我會調中度 Dimension(只學一個東西)、低 Alpha(同一張人臉,不需要太有想像力)。這樣訓練出來的模型會比較精確,而且不容易產生奇怪的圖像。

一種風格,那麼高 Dimension 和中度 Alpha 會比較適合。但是,Alpha 不宜設得太高,通常 Dimension 的一半以下會比較好。如果 Alpha 太高,你可能會看到 SD 產生出一些鬼畫圖(神機錯亂XD?)。

這邊我要訓練的是人臉,所以 Dimension 設為 48,Alpha 設為 4。

3. 訓練結果檢驗

在本次示範中,我訓練了自己的 LoRA。因為 Dimension 設置很低,所以只跑了 1520 步,花了 12 分鐘,共產生了 5 個模型,每個模型大小約為 56.7MB。

我使用的配備是:
Intel(R) Core(TM) i5–9400F CPU @ 2.90GHz
16GB RAM
NVIDIA GeForce RTX 3070 8GB VRAM

1520 Steps
花了12分鐘5秒
每個模型56.7MB

現在讓我們來看看訓練結果吧!

RAW photo, photo of Jason Kuan <lora:JasonKuanFace-000008:1>, (high detailed skin:1.2), 8k uhd, dslr, soft lighting, high quality, film grain, Fujifilm XT3
Negative prompt: (deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime:1.4), text, close up, cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck
Steps: 30, Sampler: DPM++ SDE Karras, CFG scale: 7, Seed: 2285227022, Size: 512x512, Model hash: c35782bad8, Model: realisticVisionV13_v13, ControlNet-0 Enabled: True, ControlNet-0 Module: openpose, ControlNet-0 Model: control_openpose-fp16 [9ca67cc5], ControlNet-0 Weight: 1, ControlNet-0 Guidance Start: 0, ControlNet-0 Guidance End: 1

下圖由左至右分別代表第 8、16、24、32、38 個 Epoch,最右邊的是不套用 LoRA 的對比。從圖中可以看出,LoRA 慢慢地抓到了人臉的特徵,但仍有許多可以加強的地方。例如,增加 Dimension 或加入更多樣的照片等等。

點圖可放大

4.如果訓練的 LoRA 時間過長,會有什麼變化嗎?

為了展示訓練時間過長的 LoRA 會有怎樣的變化,我額外訓練了一個模型,步數算到了 12,000 步。

首先,讓我們看看不同 Epoch 的結果:

從圖中可以看出,整體來說畫面沒有明顯崩潰的問題。
那麼,如果混合其他 LoRA 呢?我們來看看由上到下分別混合 epi_noiseoffset墨心 MoXin 和兩者都一起混合的 LoRA,所有權重都是 1。

在 epi_noiseoffset 的表現上,Epoch 30 的畫面具有最好的光線立體感,後面的 Epoch 畫面立體感逐漸變弱。墨心 MoXin 的表現也類似,Epoch 30 的畫面比較穩定,而越高的 Epoch 畫面的雜訊越高。而兩者混合的表現更不用說了。

不過,值得一提的是,epi_noiseoffset 和墨心 MoXin 的 LoRA 作者可能已經進行了一些優化,因為即使是在我訓練 300 個 Epoch 時,畫面仍然沒有太大的崩潰。而我這邊也拿早期訓練的台灣鐵皮屋 LoRA 來測試,這個 LoRA 是我用 30 張圖片訓練了 3,300 步得到的,當時沒有使用太多訓練技巧,因此畫面有很高的機率會被污染。

Epoch 30 的背景沒什麼太大問題,但最右邊的 Epoch 300 已經可以看到畫面因為過度訓練,兩個LoRA權重差異化很大,導致畫面崩掉。

以上是我訓練超過幾百次摸出來的心得,其他還有block weight、Latent couple、Composable LoRA 等內容,還可以繼續介紹,但還要看有沒有時間寫XD..

Ref

繪圖工具 https://excalidraw.com/

https://www.youtube.com/watch?v=Mnk_oUrgppM

臉書Facebook

--

--