AI繪畫入門:擴(kuò)散模型,Stable Diffusion,LoRA,ControlNet相關(guān)技術(shù)原理整理

轉(zhuǎn)載自本人知乎https://zhuanlan.zhihu.com/p/611310582,由于b站不支持鏈接和公式因此刪掉了部分內(nèi)容。本文禁止轉(zhuǎn)載。
相關(guān)資源整理
社區(qū)
civitai:比較主流的AI繪畫模型分享網(wǎng)站??梢钥吹酱罄袀兣艹龅膱D,并復(fù)現(xiàn)別人的tag或者下載別人finetune的模型。使用webui的時候這個網(wǎng)站用起來比較方便。
Huggingface:一個數(shù)據(jù)集、模型分享的網(wǎng)站,很多業(yè)界大牛也在使用和提交新模型,我們可以從stable diffusion分區(qū)下載一些作者訓(xùn)練的模型。個人感覺使用diffusers的時候這個網(wǎng)站比較方便。個人常用的模型是"runwayml/stable-diffusion-v1-5"和"Linaqruf/anything-v3.0"(類似NovelAI的leak模型)
代碼庫及工具
Stable Diffusion(Latent Diffusion Model):目前比較火的AI繪畫大部分都是基于Stable Diffusion的,比如之前比較火的NovelAI。這個代碼庫可以用來學(xué)習(xí)Stable Diffusion的算法細(xì)節(jié),因為其他工具都對代碼進(jìn)行了封裝,不容易看懂算法流程。
stable-diffusion-webui: 這是目前大家最常用的工具,是一個Gradio庫開發(fā)的瀏覽器UI界面,其后端依舊是Stable Diffusion以及一系列相關(guān)的工具包。其優(yōu)點是操作簡單,調(diào)參方便,方便分享模型,并且方便組合各種模塊,非常適合廣大沒有相關(guān)基礎(chǔ)的人使用。
diffusers:一個進(jìn)行擴(kuò)散模型訓(xùn)練、推理、Fine-Tuning的工具包。通過幾行代碼就可調(diào)用各種模塊,比如Stable Diffusion,當(dāng)然它還支持很多其他的擴(kuò)散模型。當(dāng)我們要批量處理或者魔改代碼時,webUI改起來不太方便,這個時候就可以用一用這個庫。并且diffusers可以自動幫你下載Hungingface社區(qū)的模型,缺點是civitai社區(qū)中分享的模型有的需要手動轉(zhuǎn)換,比如lora目前還沒有官方的支持,不過可以方便地找到大佬寫好的代碼來跑。
擴(kuò)散模型相關(guān)技術(shù)
Denoising Diffusion Probabilistic Models(DDPM)
參考資料:論文,大佬的blog , 跟李沐學(xué)AI - DALL·E 2(含擴(kuò)散模型介紹)
個人理解的擴(kuò)散模型可以看成一種逐步去噪的網(wǎng)絡(luò),且網(wǎng)絡(luò)的輸出還condition on給定的噪聲等級參數(shù)。擴(kuò)散模型需要從噪聲圖像中逐步恢復(fù)出原圖像,從而達(dá)到從隨機(jī)噪聲中逐步生成圖片的效果。

上圖中從右側(cè)的原始圖像到左側(cè)的噪聲圖像就是擴(kuò)散過程,每一步都會添加高斯噪聲,最終圖像就接近完全隨機(jī)了。這個擴(kuò)散過程可以當(dāng)成制作訓(xùn)練數(shù)據(jù)的過程,我們要做的是訓(xùn)練一個網(wǎng)絡(luò),從每一步噪聲圖像估計出擴(kuò)散過程時在這一步添加的噪聲(或直接估計去除噪聲的圖像)。
由于去除噪聲的過程中我們使用的是同一個網(wǎng)絡(luò),而每一步的噪聲的總量并不相同,因此可以給網(wǎng)絡(luò)一個額外的輸入T,告訴網(wǎng)絡(luò)現(xiàn)在是在哪一步了。大佬的blog中指出網(wǎng)絡(luò)可以根據(jù)噪聲等級的不同,自動選擇關(guān)注全局特征還是局部特征。因為圖像中每一個像素添加的高斯噪聲是獨立的,當(dāng)噪聲較多時(對應(yīng)上圖左側(cè))網(wǎng)絡(luò)只能將更大范圍里所有像素的特征合并起來考慮,這樣各個像素特征中的高斯噪聲能夠在融合的過程中相互抵消,此時網(wǎng)絡(luò)只能恢復(fù)出圖像的大致輪廓。當(dāng)噪聲比較少時(對應(yīng)上圖右側(cè)),網(wǎng)絡(luò)可以更關(guān)注更小范圍內(nèi)的細(xì)節(jié),從而恢復(fù)出圖像細(xì)節(jié)。
綜上所述,擴(kuò)散模型在生成圖像時,網(wǎng)絡(luò)首先從一個隨機(jī)噪聲圖像中“幻視”出某個物體(比如以為這個噪聲圖像是一個人臉),然后網(wǎng)絡(luò)會從噪聲圖像中恢復(fù)出人臉的輪廓。之后網(wǎng)絡(luò)會逐步在更小的范圍內(nèi)“幻視”出一些細(xì)節(jié)(比如眼睛鼻子等),最終恢復(fù)出一張比較真實的圖片。整個過程由額外輸入的時間參數(shù)T來控制網(wǎng)絡(luò)應(yīng)該關(guān)注整體輪廓還是局部細(xì)節(jié)。
Guidance
參考資料:Diffusion Models Beat GANs 論文,Classifier-free guidance 論文,大佬的blog
上文所述的擴(kuò)散模型只能隨機(jī)生成圖片,然而我們在使用時一般希望能夠指定生成的內(nèi)容,比如給網(wǎng)絡(luò)提供額外的輸入y作為條件,比如物體類別或者文字描述。Classifier guidance 就是額外訓(xùn)練一個分類器,從而將無條件的擴(kuò)散模型變成有條件的擴(kuò)散模型。

因此,如果我們在無條件模型的基礎(chǔ)上,訓(xùn)練一個分類器,這個分類器能夠?qū)Σ煌燃壍脑肼晥D像進(jìn)行分類,那么分類器訓(xùn)練完成后,分類器反傳到圖像的梯度也可以優(yōu)化這個圖像,使圖像向著指定類別的方向去優(yōu)化。
Classifier guidance 的優(yōu)點是我們不需要finetune無條件的擴(kuò)散模型,只需要額外增加一個分類器即可實現(xiàn)出有條件的擴(kuò)散模型。因為擴(kuò)散模型通常是在很大的數(shù)據(jù)集上訓(xùn)練的,重新訓(xùn)練一個有條件擴(kuò)散模型非常耗資源,而classifier guidance只需要額外訓(xùn)一個分類器即可將已有的無條件擴(kuò)散模型變成有條件模型。Classifier guidance 的缺點是這個分類器也比較難訓(xùn)練,因為需要讓分類器學(xué)習(xí)各種帶噪聲的圖像輸入。
Classifier-free guidance對有條件的擴(kuò)散模型進(jìn)行直接訓(xùn)練,而不需要訓(xùn)練分類器。其特殊之處在于訓(xùn)練有條件擴(kuò)散模型的過程中,在一些情況下將輸入的條件屏蔽掉,相當(dāng)于訓(xùn)練一個擴(kuò)散模型同時支持無條件和有條件兩種情況。在生成圖像時,我們可以按一定權(quán)重比例混合有條件和無條件模型兩種情況的輸出,達(dá)到控制輸出內(nèi)容的效果,而不需要再單獨訓(xùn)練分類器。
Classifier-free guidance的優(yōu)點是不需要再訓(xùn)練額外的分類器。缺點是模型訓(xùn)練需要更多的資源;且生成圖像時需要跑兩次網(wǎng)絡(luò)分別得到有條件和無條件的輸出。
Latent Diffusion Model (Stable Diffusion)
Latent Diffusion Model 的原理很簡單,其實就是將上面圖像去噪的過程從圖像像素空間的操作變成了隱空間中對圖像特征操作。通過將圖像投影到隱空間可以更多關(guān)注一些語義方面的特征而非像素本身,并在隱空間進(jìn)行操作可以大大降低計算資源的要求,使落地更簡單,讓普通人在一般的GPU上也可以用了。投影到隱空間的過程在論文中對應(yīng)Perceptual Image Compression章節(jié)。這一部分可以通過訓(xùn)練自編碼器的Encoder和Decoder來實現(xiàn)。

有了Encoder和Decoder,就可以在隱空間中添加噪聲,并訓(xùn)練一個擴(kuò)散模型在隱空間中去噪。作者使用了一個類似UNet的架構(gòu),其輸入為隱空間的帶噪聲特征圖 、時間t以及條件y?,其中條件y可以是來自語言、圖像、語義圖等等。作者還在UNet中加入cross-attention層,其中Query是來自圖像特征圖,KV來自輸入條件(的編碼)。
至于比較火的Stable Diffusion主要是Latent Diffusion Model 的一種實現(xiàn)形式。比如v1版本的模型使用VAE來投影圖像至隱空間,并從隱空間采樣并恢復(fù)圖像(用文本生成圖像時只需要VAE的Decoder);條件輸入使用了CLIP ViT-L/14作為文本編碼器;UNet大約是860M參數(shù)量(以float32 的精度存儲大概需要 3.44GB 空間)。
Finetune相關(guān)技術(shù)
擴(kuò)散模型Finetune相關(guān)的技術(shù)都是為了實現(xiàn)這樣的效果:通過對預(yù)訓(xùn)練好的大模型使用少量樣本進(jìn)行finetune,使模型可以根據(jù)用戶自定義的提示詞生成個性化的圖像,同時還基本不會影響模型在其他方面原本生成能力。例如,我們希望用動漫角色的名字作為自定義的提示詞,同時只提供最多幾十張這個角色的圖片,使微調(diào)后的模型能夠在給定動漫角色名字的情況下生成該角色的圖片。但同時我們還希望預(yù)訓(xùn)練模型保留原本強(qiáng)大能力,不希望模型永遠(yuǎn)只會輸出這個角色的圖片,即當(dāng)我們?nèi)サ粼摻巧奶崾驹~時,需要模型能生成和原模型一樣的圖片。
Textual Inversion (TODO)
參考資料:https://textual-inversion.github.io/

Textual Inversion的原理非常簡單,該方法只向Text Encoder中增加了自定義的token,而模型的其他模塊如Stable Diffusion的UNet和VAE均不會改變。
具體來說,一般我們使用的Text Encoder如CLIP的過程是先將輸入的文本打散成一個個token,每個token會對應(yīng)一個固定embedding(如512維向量),類似于一個字典。Textual Inversion做的就是在字典中新增一個token,這個token可以對應(yīng)自定義的概念,比如動漫的某個角色名字。通過給網(wǎng)絡(luò)這個角色的圖片,以及帶有這個角色名字的文本描述,來優(yōu)化這個token對應(yīng)的embedding(即512維向量)。
那么訓(xùn)練完成后,只要我們的描述文本中有這個角色名,那么相應(yīng)的embedding就會被取出并一起送到后續(xù)的網(wǎng)絡(luò)中,這樣就可以生成對應(yīng)角色的圖片。同理如果從描述文本中去掉這個角色名,相應(yīng)的token沒有被激活,網(wǎng)絡(luò)還會像finetune前一樣正常輸出。
Dreambooth
參考資料:https://dreambooth.github.io/

Dreambooth提出了一種finetune流程,通過Prior-Preservation Loss,使我們finetune后的模型能夠在生成自定義圖片的同時保留預(yù)訓(xùn)練模型保留原本的性能。
方法的大致流程如下(其他的細(xì)節(jié)可參考原論文):
采集數(shù)據(jù):包括少量的(如幾張或幾十張)某種狗的照片(比如你自己的狗)以及你自定義的提示詞(比如狗的名字+"dog")也可以包含其他相關(guān)的描述,如照片中狗的動作,所在的場景等。
用自定義的樣本對應(yīng)的提示詞輸入給網(wǎng)絡(luò),生成圖像,將對應(yīng)的自定義圖像作為真值計算loss。
將提示詞中自定義的部分(比如狗的名字)去掉,只保留“dog”及其他描述,輸入給原本預(yù)訓(xùn)練模型及finetune模型分別生成圖像。
原本預(yù)訓(xùn)練模型輸出的圖像作為真值,和finetune模型生成的圖像計算Prior-Preservation Loss,來約束finetune的過程,使finetune模型能保留原模型的能力。
LoRA
參考資料:論文(原本是用于大語言模型的) 大佬的代碼


Controlnet
參考資料:github 論文

原理介紹
Controlnet主要的功能是將大模型(比如預(yù)訓(xùn)練Stable Diffusion)在自己的小數(shù)據(jù)集上finetune,使新的模型能夠適應(yīng)自己的數(shù)據(jù)集(比如自定義的風(fēng)格/任務(wù))且對原模型的影響較?。ㄟ€保留原模型絕大部分能力)。
主要原理如上圖所示。將我們需要修改的網(wǎng)絡(luò)層復(fù)制一份,并在前后分別增加參數(shù)全為0的卷積層,作為右側(cè)的 trainable分支。trainable分支的輸出和原來的網(wǎng)絡(luò)輸出加在一起作為最終的輸出。由于復(fù)制出來的網(wǎng)絡(luò)前后的增加的卷積層參數(shù)均為0,輸出也一定是0,因此整個網(wǎng)絡(luò)的輸出還和原來的網(wǎng)絡(luò)完全一樣。在自己的數(shù)據(jù)集訓(xùn)練時將原來的網(wǎng)絡(luò)固定,只訓(xùn)練trainable的那個部分即可。
相關(guān)資源
Controlnet的作者為Stable Diffusion訓(xùn)練了各種模型,通過不同的方式控制生成的內(nèi)容,例如通過canny邊緣、人體位姿、甚至線稿等等,可以用webui方便地使用。至于diffuser也有大佬寫了代碼。
我們可以使用這個工具制作自己想要的pose,自己畫人體姿態(tài)或者從圖片生成姿態(tài),例如

當(dāng)然我們還可以將ControlNet與LoRA結(jié)合起來用,例如
