[Lora] 訓練集與提詞

AIGC with Caline

寫在最前面的,本篇文章的內容僅為個人實驗以及在各種訓練產生的結果上,總結出來的一些結論,並無法完全通用在各種情況。如果以下所提及的所有內容與結果與你有所雷同,那就雷同吧。


前言

以下的訓練皆使用 Kohya_ss GUI 24.1.4 進行,整個運作環境版本如下:

  • torch 2.2.2
  • torchvision 0.17.2
  • xformers 0.0.25.post1
  • lycoris_lora 3.0.0.post1

附帶一題,我個人所使用的 kohya-ss 訓練工具中,有經過特殊的客製化,包含了:

  • 使用 LogNorm 干涉 timesteps,請參考這個 Issue
  • 使用 min-SNR 5 + Debiased 兩階段訓練

所以我所跑出來的訓練可能會跟大家不太一樣。就當作是一個提醒就好,使用本文章所提及的任何資料,所訓練出來的結果,可能比較好,也可能比較差,差異可能在於我的訓練工具跟你的不太一樣。


提詞工具

我目前所使用的提詞工具,是由 @gesne2egee 所提供的,加上我額外撰寫的 phi3,

當然還有純手動提詞,但這個方法實在太地獄,除非你有精準標示的需求,不然還是先用工具跑一次會比較快一點。

無論你用上述哪一種提詞工具,我們目前所使用的提詞都是使用 --enable_wildcard 的方式進行,也就是說,提詞出來的結果會包含多行的提詞結果。同時,如果需要,也會使用 --keep_tokens_separator="___" 來固定特定區塊標籤。

如果不清楚 --enable_wildcard--keep_tokens_separator 可以參考一下 kohya 那邊的說明:

Dataset settings


提詞方法

對於一張圖片的描述,概括目前所知道對於特徵描述的方式,大概有以下幾種:

  1. 刪除特徵標籤
  2. 保留部分特徵標籤,刪除特定特徵標籤
  3. 全保留不刪除
  4. 使用觸發詞

對於標記方式,整篇文章我都會使用自行製作甲冑 Lora 來當作例子,雖然絕大部分他是手動標籤,但也恰好可以說明自動標籤與手動標籤的差異性。


特徵標籤

如其名,我們會希望畫面中的「特徵」被學起來。因此,這個部分就有了兩種作法,各有各的擁護者,

  1. 刪除特徵標籤
  2. 不刪除特徵標籤

對於第一次接觸訓練的人來說,或許會有個疑問,為什麼要 刪除特徵標籤 ?這裡必需要提及一下在 Kohya 訓練當中的 Class token 這件事情,也就是,在你的訓練概念資料夾名稱的 10_Concept 這件事。

所謂的 Concept 就是一種 Class token,當你把這張圖片的特徵標籤 刪除 時,在整個訓練過程中,相對於基底模型是全新概念的情況下,而你又沒有將他標記,那麼他就會被歸類到這個 Class token 裡面。

但是,當你有使用觸發詞時,整個畫面當中的全新概念,是會有高機率會被歸類到你的觸發詞當中(當你的訓練使用 Shuffle caption,並使用 Keep n Token = 1 時)。

而,不刪除特徵標籤的情況,則會因為你是否有使用觸發詞,且 Shuffle captionKeep n Token = 1 時,這個特徵標籤的強度會因此而改變。

另外,所謂的「特徵標籤」對於基底模型來說,是不是你要的那個東西,那又是另外一個故事了。我在後面 觸發詞 會再提及這件事情。

整體而言,特徵標籤的整理順序可以照這個方向去做,

  1. 觸發詞(如果你需要的話)
  2. 最明顯的主要目標
  3. 依附在主要目標上面的細節
  4. 次要明顯的目標
  5. 依附在次要明顯的目標上面的細節
  6. 整體攝影鏡位、角度、光影等
  7. 背景

舉例來說,

日本甲冑圖

上述的圖片,一般來說標記的方向為:

  • 觸發詞 samurai armor
  • 特殊物件
    • 家徽
    • 腰帶
    • 胸甲
    • 上胸甲
    • 其他細節
    • 動作或姿勢
    • 背景

對於這麼複雜的學習目標,首先我們必需要釐清幾個重點,

  1. 他沒有人物,所以描述詞不能出現 1girl, 1boy 這種描述。
  2. 局部描寫,所以需要說明他是 close-up shotmedium shot 等鏡位。
  3. 有特徵被裁切,所以要把被切掉的特徵稍微描述,例如 XXX out of frame
  4. 去掉畫面沒有的描述(自動標籤很容易有幻覺)。

那麼,我們使用 Phi3 來對剛剛的圖片自動下標籤,會得到這樣的結果,

自然語言的長描述,

the image features a large black drum with a gold emblem on it, the drum is adorned with blue and white patterns and has two golden tassels hanging from its sides, in front of the drum lies a blue and gold robe draped over a chair, the drum is set against a dark gray background, the drum occupies a significant portion of the frame and is positioned centrally, the chair is located in the lower right corner of the frame, the drum's design is intricate with a combination of geometric shapes and floral motifs.

而以下是 Phi3 所整理出來的短標籤,

focus on drum, the main object in the foreground, shadows, the main object, still life, close-up, the main object is a drum in front of a drum, drum, chair, the main object is a drum, indoors, the main object is a drum in front of a drummer, the main object is a drum with a gold emblem, objects, the main object in the center, portraits, background

首先,我們需要先解決「幻覺」的部分,

the main object is a drum in front of a drummer

他不是鼓,你會發現上面出現了很多關於鼓的描述,所以 Phi3 把這個胸甲誤認為「鼓」了,所以必須清理這個部分。畢竟這個物件太特殊,所以你要做的手動的部分就會特別多。

清理過程我就不贅述了。


刪除特定特徵標籤

當你的資料集不夠豐富,或是單一特徵素材過於稀少時,為了不要讓特徵鎖定的狀況過於嚴重,那麼可以採用這種方式來「擴充」資料集的資料。

比較簡單的作法是,

  1. 有一張圖片 A1,特徵標籤 B, C, D, E
  2. 複製一張圖片 A2,特徵標籤 C, D, E
  3. 複製一張圖片 A3,特徵標籤 B, E

你會有三張 A 的圖片,你可以讓他有些微的不同,例如尺寸裁切、左右翻轉、上下翻轉等。而這三張訓練集的差異在於,

  • A1 包含了所有特徵標籤
  • A2 刪除了 B 特徵標籤
  • A3 刪除了 C, D 特徵標籤

在訓練的時候,A2 缺少的 B 特徵,就會被歸入觸發詞或 Class token 裡面,同樣的道理,對於 A3 來說,C, D 特徵也會被歸入觸發詞或 Class token 裡。

這樣的作法是利用刪除特定標籤,將特定標籤所指定的「特徵」塞到觸發詞或 Class token 裡面,用以強調該特徵在觸發詞或 Class token 的表現。

而通常,這種訓練方式需要額外做概念平衡,避免過多的概念被集中。換句話說,你需要將這樣「複製」的訓練資料集,分別放到不同的概念資料夾中,去做步數平衡。

舉例來說,我所製作的這個 Lora 對於「小面積臉部」有修正效果,那麼,怎麼定義「小面積臉部」?

Maybe Better Face In Full Body XL

說穿了就是區分為三個概念,

4_close up
6_portrait
12_full body

在這三個概念中,都包含了有人臉的照片,但是,在 full body 的概念裡面,就不會特別描述臉部,而著重在肢體表現,將臉、上半身、髮型的特徵全數刪除。


全標籤

老實說我一開始訓練的時候也是使用全標籤的方式進行,而實際操作的結果也沒有特徵練不好的問題。底下這兩個結果你看得出來哪一個有刪標籤嗎?

AIGC Caline with dress

訓練集中不刪除特徵標籤的訓練,對於細節特徵的保留上會偏弱,但這個「偏弱」的程度取決於你的資料夾品質的好壞,跟是否有針對概念作一些特殊的平衡動作。

在全標籤的操作下,操作的手法可以跟刪除特定標籤雷同,將需要強化的部分「多看幾次」,也就是說,當我需要針對臉部特徵作強化時,我們的概念資料夾就可以這樣來區分,

10_close up face
4_hina ai girl

在這樣的描述詞的情況下,礙於訓練器對於 Text Encoder 訓練的權重問題,根據實驗,在前 20 個 Token 的表現會是最好的,而越後面的 Token 的表現就會偏弱。所以,因為全保留的關係,你的描述詞就需要稍微調整一下。

全描述的表達方式以下方結構是對於訓練來說比較有效的,

觸發詞, ___特徵 1, 特徵 2, ..., 特徵 n___ 其他短描述, 長描述

無論你是否要刪除標籤,這樣的結構基本上一體適用,只是對於全保留的情況下,這樣的描述在標籤平衡上會比較好一點。

由於標籤權重的關係,所以即便使用這樣的結構,你的標籤也需要將比較重要的放在前面,即便在有使用 Shuffle caption--keep_tokens_separator="___" 的情況下,雖然順序會被打亂,但請在 ___ 之前盡可能不要讓特徵超出 20 個 Token 數。

在全長標籤(自然語言標籤)的訓練當中,不使用 Shuffle caption 也不使用觸發詞的情況下,訓練出來的效果會偏弱(不考慮過度訓練的情況)。所以若你使用的是自然語言描述標籤,也請將重點放在前面。


觸發詞

使用觸發詞的狀況有幾種方式,先以觸發詞、基底模型之間的反應來看,

觸發詞是否有反應 訓練目標說明 訓練難度
無反應 獨立特定概念 中等
完全不相符 可用於清洗概念,若非此目的,則不適合在這個基底模型訓練
接近 混合、融合概念,將訓練集的特徵融入模型中,用於泛化或多型表現 中等
幾乎完全相符 可用於清洗概念,若非此目的,則此訓練效果很低

所以挑選觸發詞請先從你訓練的基底模型開始測試。而,除了觸發詞之外,上面所提到的特徵標籤也是有相同的問題。在訓練的時候,我們可能需要避免的是特定特徵被基底模型污染這件事。

舉例來說,當我呼叫 samurai armor 的時候,他告訴我的是什麼東西?當基底模型告訴你的結果跟你想訓練的概念相近的時候,那麼這個觸發詞就很適合使用。

然而,觸發詞也是會有污染的情況,例如:

  • shoulder armor
  • neck armor
  • arm armor
  • body armor

因為都有 armor 這個字,在 samurai armor 的使用上,提詞權重就有機會被這幾個提示詞「分走」。所以,如果要避免觸發詞與其他用詞有干擾的情況,觸發詞可能需要更換會比較保險。


提詞結構

我在上面有提到了提詞工具跟標籤整理順序,我們這邊就來看 --enable_wildcard--keep_tokens_separator="___" 訓練設定相關的提詞結構。

目前實作了約 100 爐 SDXL 測試 MoE/Florence2/Phi 提詞、手動提詞等等,目前實驗下來比較好的結構為:

觸發詞, ___特徵 1, 特徵 2, ..., 特徵 n___ 其他短描述, 長描述
觸發詞, 長描述
觸發詞, 其他短描述, 長描述
觸發詞, ___特徵 1, 特徵 2, ..., 特徵 n___

使用 --enable_wildcard 的情況下,會使用上述四組提示標籤來隨機抽一組使用,這樣的方式我們的目的為,

  1. 第一組等於全標籤,不刪標籤,平衡第二、三組帶來的特徵鎖定,增加泛化能力
  2. 第二組刪除所有特徵標籤,自然語言,將所有模型不認識的特徵全部交給觸發詞
  3. 第三組同第二組,但保留非特徵標籤的其他短描述,增加泛化能力
  4. 第四組全特徵標籤,將部分非特徵標籤交給觸發詞,降低觸發詞特徵鎖定,增加多型能力

這麼一來,我們在上面所提到的複製圖片的方式,在這邊就可以使用完全相同的提詞,僅需要複製圖片,並且把圖片作適當的修剪即可。

舉例來說,

a fantasy armor in this image, {rating:general|}, the whole image consists of the following: ___solo, full armor, gauntlets, pauldrons, red cape, knight, breastplate, upper body, gem, standing, arch, long hair, holding sword, horns, 1other, facing viewer, ambiguous gender, indoors, white hair, male focus, statue___, in the image, a man dressed in medieval armor is standing in front of a building, he is holding a sword and appears to be facing the viewer, the scene seems to be a historical or artistic representation, possibly depicting a knight or warrior from a bygone era, the man's attire and the presence of the sword suggest that he might be a figure of historical significance or a symbol of strength and courage.

大概這一類的提詞,我僅使用了一張圖片,分區塊裁切成 12 張不同的素材,用來訓練一個 SDXL 的 Lora,

Fantasy Armor XL/Pony

1 image Lora

訓練不更新 Text Encoder aka. network_train_unet_only

在 SDXL 一開始推出訓練的時候,其實在 Kohya 那邊有建議使用 --network_train_unet_only 這件事情。而,之所以會這樣建議,是因為 SDXL 有兩個 Text Encoder 的關係,所以無法保證 Te 的訓練效果。

而,在 SD1.5 的時代,訓練 Te 這件事情很容易會遇到一個狀況,

絕大部分的 Lora 的 Text Encoder 可能都過度訓練。

為何會這麼說?關於 Text Encoder / Unet 過度訓練的狀況,可以參考這一篇文章:

Overtrained Text Encoder vs Overtrained UNET [Stable Diffusion Experiment]

TL;DR

我先說結論,

  1. 過度訓練的 Text Encoder 會更難以表達 Prompt 的描述
  2. 過度訓練的 Unet 會疊加更多風格,但仍舊會遵循 Prompt 的描述

所以,Text Encoder 過度訓練的結果會讓畫面更偏離,而不是更貼近你的訓練目標。所以針對這個部分,我也做了一連串的實驗。

所謂的 --network_train_unet_only 是在訓練時不更新 Text Encoder 的部分,也就是說,訓練的時候還是有給他提示詞的。關於完全不提詞的情況,我在後面會提出來聊一下。

在完全相同參數、設定、資料集,僅 --network_train_unet_only 的差異下,訓練出來的結果有以下的差別,

  1. 觸發詞、關鍵提詞其實會有反應,但變弱了
  2. 對於背景、非主體相關(或關連)的表現變好
  3. 在高權重下,偽影的狀況少很多
  4. 同樣的高權重下,關鍵細節會略少
  5. 跟其他 Lora 搭配的相容度比較好

同樣的,你應該可以很明確挑出哪一張是 --network_train_unet_only 吧?

AIGC Caline with dress

為了避免提詞偏弱,特別是概念觸發詞或特殊特徵提詞,所以在訓練的時候可以壓低 Text Encoder Lr 來達到類似 --network_train_unet_only 的效果,但是又保有更新 Text Encoder 的部分的好處。

所以,我使用了 Lion8bit 的訓練,並且測試了兩組 Text Encoder Lr 的設定,對我來說,以下的設定還蠻適合我的訓練資料集,

UNet Lr 5e-5
Text Encoder Lr 5e-7

你可以對比一下,在更低的 Text Encoder 學習率的情況下,反應情況會是如何。

AIGC Caline with dress

同時,我們來看有無 --network_train_unet_only 的差異。

Compare --network_train_unet_only

不提詞

我實在不會解釋 unconditional 到底是怎麼回事。但這一篇文章是講提詞的,所以這邊我也不多說什麼,就說一些實驗上遇到的狀況就好,

  1. 垃圾正規化資料集,不提詞有奇效(原因不明)
  2. 訓練集可以少量混入不提詞的資料
  3. 基底模型不提詞如果可以抽到你的概念,拿來當正規化

在這裡所謂的不提詞,並不是單純指不給 .txt 這樣的提詞檔案,而是連訓練資料夾的 Class token 都省略的情況,換句話說,我的資料夾會長這樣,

image/
  10_

reg/
  8_

這樣在訓練時會掉入 unconditional 裡面(理論上),雖然不太清楚原理,但是這樣在某些訓練上有奇妙的效果,有興趣的人可以自行嘗試。

另,我上述所有的訓練,皆使用垃圾正規化資料集,不提詞。


小結

提詞的時候,Google 翻譯或是 ChatGPT 是你的好朋友(認真)。

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei