stable diffusion真的是橫空出世,開(kāi)啟了AIGC的元年。不知你是否有和我一樣的困惑,這AI工具好像并不是那么聽(tīng)話?
前言
我們?cè)撊绾尾拍苡煤胹table diffusion這個(gè)工具呢?AI究竟在stable diffusion中承擔(dān)了什么樣的角色?如何能盡可能快、成本低地得到我們期望的結(jié)果?
源于這一系列的疑問(wèn),我開(kāi)始了漫長(zhǎng)的論文解讀。High-Resolution Image Synthesis with Latent Diffusion Models(地址:https://arxiv.org/abs/2112.10752?spm=ata.21736010.0.0.7d0b28addsl7xQ&file=2112.10752)
當(dāng)然這論文看的云里霧里的,加篇讀了How does Stable Diffusion work?(地址:https://stable-diffusion-art.com/how-stable-diffusion-work/?spm=ata.21736010.0.0.7d0b28addsl7xQ)
先簡(jiǎn)要概括下,stable diffusion的努力基本是為了2個(gè)目的:
低成本、高效驗(yàn)證。設(shè)計(jì)了Latent Space
Conditioning Mechanisms。條件控制,如果不能輸出我們想要的圖片,那這就像Monkey Coding。耗費(fèi)無(wú)限的時(shí)間與資源。
這是整個(gè)內(nèi)容里最重要最核心的兩個(gè)部分。
圖片生成的幾種方式
隨著深度神經(jīng)網(wǎng)絡(luò)的發(fā)展,生成模型已經(jīng)有了巨大的發(fā)展,主流的有以下幾種:
自回歸模型(AutoRegressive model):按照像素點(diǎn)生成圖像,導(dǎo)致計(jì)算成本高。實(shí)驗(yàn)效果還不錯(cuò)
變分自編碼器(Variational Autoencoder):Image to Latent, Latent to Image,VAE存在生成圖像模糊或者細(xì)節(jié)問(wèn)題
基于流的方法(Glow)
生成對(duì)抗網(wǎng)絡(luò)(Generative adversarial network):利用生成器(G)與判別器(D)進(jìn)行博弈,不斷讓生成的圖像與真實(shí)的圖像在分布上越來(lái)越接近。
其中AR與GAN的生成都是在pixel space進(jìn)行模型訓(xùn)練與推理。
?? 模型是如何生成圖片的?
以一只貓作為案例。當(dāng)我們想畫一只貓的時(shí)候,也都是從一個(gè)白板開(kāi)始,框架、細(xì)節(jié)不斷完善。
對(duì)于AI來(lái)說(shuō),一個(gè)純是noise的image就是一個(gè)理想的白板,類似下圖展示的這樣。
從圖中的流程,我們可以看到推理的過(guò)程如下:
生成一個(gè)隨機(jī)的noise image圖片。這個(gè)noise取決于Random這個(gè)參數(shù)。相同的Random生成的noise image是相同的。
使用noise predictor預(yù)測(cè)這個(gè)圖里加了多少noise,生成一個(gè)predicted noise。
使用原始的noise減去predicted noise。
不斷循環(huán)2、3,直到我們的執(zhí)行steps。
最終我們會(huì)得到一只貓。
在這個(gè)過(guò)程中,我們會(huì)以下疑問(wèn):
如何得到一個(gè)noise predictor?
怎么控制我們最終能得到一只貓?而不是一只狗或者其他的東西?
在回答這些疑問(wèn)之前,我先貼一部分公式:
我們定義一個(gè)noise predictor:,
是第 t 個(gè)step過(guò)程中的noise image,t 表示第t個(gè)stop。
???如何得到一個(gè)noise predictor?
這是一個(gè)訓(xùn)練的過(guò)程。過(guò)程如下圖所示:
選擇一張訓(xùn)練用的圖片,比如說(shuō)一張貓
生成一個(gè)隨機(jī)的noise圖片
將noise圖疊加到訓(xùn)練用的圖片上,得到一張有一些noise的圖片。(這里可以疊加1~T步noise
訓(xùn)練noise predictor,告訴我們加了多少noise。通過(guò)正確的noise答案來(lái)調(diào)整模型權(quán)重。
最終我們能得到一個(gè)相對(duì)準(zhǔn)確的noise-predictor。這是一個(gè)U-Net model。在stable-diffusion-model中。
通過(guò)這一步,我們最終能得到一個(gè)noise encoder與noise decoder。
PS: noise encoder在image2image中會(huì)應(yīng)用到。
以上noise與noise-predictor的過(guò)程均在pixel space,那么就會(huì)存在巨大的性能問(wèn)題。比如說(shuō)一張1024x1024x3的RBG圖片對(duì)應(yīng)3,145,728個(gè)數(shù)字,需要極大的計(jì)算資源。在這里stable diffusion定義了一個(gè)Latent Space,來(lái)解決這個(gè)問(wèn)題。
?? Latent Space
Latent Space的提出基于一個(gè)理論:Manifold_hypothesis
它假設(shè)現(xiàn)實(shí)世界中,許多高維數(shù)據(jù)集實(shí)際上位于該高維空間內(nèi)的低維Latent manifolds。像Pixel Space,就存在很多的難以感知的高頻細(xì)節(jié),而這些都是在Latent Space中需要壓縮掉的信息。
那么基于這個(gè)假設(shè),我們先定義一個(gè)在RGB域的圖片
然后存在一個(gè)方法z=varepsilon(x),,z是x在latent space的一種表達(dá)。
這里有一個(gè)因子f=H/h=W/w,通常我們定義,比如說(shuō)stable-diffusion v1.5訓(xùn)練與推理圖片在512x512x3,然后Latent Space的中間表達(dá)則是4x64x64,那么我們會(huì)有一個(gè)decoder D能將圖片從Latent Space中解碼出來(lái)。
在這個(gè)過(guò)程中我們期望
,這倆圖片無(wú)限接近。
整個(gè)過(guò)程如下圖所示:
而執(zhí)行這個(gè)過(guò)程的就是我們的Variational Autoencoder,也就是VAE。
那么VAE該怎么訓(xùn)練呢?我們需要一個(gè)衡量生成圖像與訓(xùn)練圖像之間的一個(gè)距離指標(biāo)。
也就是。
細(xì)節(jié)就不關(guān)心了,但這個(gè)指標(biāo)可以用來(lái)衡量VAE模型的還原程度。訓(xùn)練過(guò)程與noise encoder和noise-predictor非常接近。
貼一個(gè)stable diffusion在FID指標(biāo)上,與其他方法的對(duì)比。下面的表格來(lái)自于無(wú)條件圖片生成?;揪褪潜容^Latent Space是否有丟失重要信息。
為什么Latent Space是可行的?
你可能在想,為什么VAE可以把一張圖片壓縮到更小的latent space,并且可以不丟失信息。
其實(shí)和人對(duì)圖片的理解是一樣的,自然的、優(yōu)秀的圖片都不是隨機(jī)的,他們有高度的規(guī)則,比如說(shuō)臉上會(huì)有眼睛、鼻子。一只狗會(huì)有4條腿和一個(gè)規(guī)則的形狀。
圖像的高維性是人為的,而自然的圖像可以很容易地壓縮為更小的空間中而不丟失任何信息。
可能說(shuō)我們修改了一張圖片的很多難以感知的細(xì)節(jié),比如說(shuō)隱藏水印,微小的亮度、對(duì)比度的修改,但修改后還是同樣的圖像嗎?我們只能說(shuō)它表達(dá)的東西還是一樣的。并沒(méi)有丟失任何信息。
?? 結(jié)合Latent Space與noise predictor的圖像生成過(guò)程
生成一個(gè)隨機(jī)的latent space matrix,也可以叫做latent representation。一種中間表達(dá)
noise-predictor預(yù)測(cè)這個(gè)latent representation的noise.并生成一個(gè)latent space noise
latent representation減去latent space noise
重復(fù)2~3,直到step結(jié)束
通過(guò)VAE的decoder將latent representation生成最終的圖片
直到目前為止,都還沒(méi)有條件控制的部分。按這個(gè)過(guò)程,我們最終只會(huì)得到一個(gè)隨機(jī)的圖片。
條件控制
非常關(guān)鍵,沒(méi)有條件控制,我們最終只能不斷地進(jìn)行Monkey Coding,得到源源不斷的隨機(jī)圖片。
相信你在上面的圖片生成的過(guò)程中,已經(jīng)感知到一個(gè)問(wèn)題了,如果只是從一堆noise中去掉noise,那最后得到的為什么是有信息的圖片,而不是一堆noise呢?
noise-predictor在訓(xùn)練的時(shí)候,其實(shí)就是基于已經(jīng)成像的圖片去預(yù)測(cè)noise,那么它預(yù)測(cè)的noise基本都來(lái)自于有圖像信息的訓(xùn)練數(shù)據(jù)。
在這個(gè)denoise的過(guò)程中,noise會(huì)被附加上各種各樣的圖像信息。
怎么控制noise-predictor去選擇哪些訓(xùn)練數(shù)據(jù)去預(yù)測(cè)noise,就是條件控制的核心要素。
這里我們以tex2img為案例討論。
???Text Conditioning
下面的流程圖,展示了一個(gè)prompt如何處理,并提供給noise predictor。
Tokenizer
從圖中可以看到,我們的每一個(gè)word,都會(huì)被tokenized。stable diffusion v1.5使用的openai ViT-L/14 Clip模型來(lái)進(jìn)行這個(gè)過(guò)程。
tokenized將自然語(yǔ)言轉(zhuǎn)成計(jì)算機(jī)可理解的數(shù)字(NLP),它只能將words轉(zhuǎn)成token。比如說(shuō)dreambeach
會(huì)被CLIP模型拆分成dream
和beach
。一個(gè)word,并不意味著一個(gè)token。同時(shí)dream
與beach
也不等同于dream
和<space>beach
,stable diffusion model目前被限制只能使用75個(gè)tokens來(lái)進(jìn)行prompt,并不等同于75個(gè)word。
Embedding
同樣,這也是使用的openai ViT-L/14 Clip model. Embedding是一個(gè)768長(zhǎng)度的向量。每一個(gè)token都會(huì)被轉(zhuǎn)成一個(gè)768長(zhǎng)度的向量,如上案例,我們最后會(huì)得到一個(gè)4x768的矩陣。
為什么我們需要embedding呢?
比如說(shuō)我們輸入了man
,但這是不是同時(shí)可以意味著gentleman
、guy
、sportsman
、boy
。他們可能說(shuō)在向量空間中,與man
的距離由近而遠(yuǎn)。而你不一定非要一個(gè)完全準(zhǔn)確無(wú)誤的man
。通過(guò)embedding的向量,我們可以決定究竟取多近的信息來(lái)生成圖片。對(duì)應(yīng)stable diffusion的參數(shù)就是(Classifier-Free Guidance scale)CFG。相當(dāng)于用一個(gè)scale去放大距離,因此scale越大,對(duì)應(yīng)的能獲取的信息越少,就會(huì)越遵循prompt。而scale越小,則越容易獲取到關(guān)聯(lián)小,甚至無(wú)關(guān)的信息。
如何去控制embedding?
我們經(jīng)常會(huì)遇到stable diffusion無(wú)法準(zhǔn)確繪制出我們想要的內(nèi)容。那么這里我們發(fā)現(xiàn)了第一種條件控制的方式:textual inversion
將我們想要的token用一個(gè)全新的別名定義,這個(gè)別名對(duì)應(yīng)一個(gè)準(zhǔn)確的token。那么就能準(zhǔn)確無(wú)誤地使用對(duì)應(yīng)的embedding生成圖片。
這里的embedding可以是新的對(duì)象,也可以是其他已存在的對(duì)象。
比如說(shuō)我們用一個(gè)玩具貓訓(xùn)練到CLIP模型中,并定義其Tokenizer對(duì)應(yīng)的word,同時(shí)微調(diào)stable diffusion的模型。而對(duì)應(yīng)
toy cat
就能產(chǎn)生如下的效果。
感覺(jué)有點(diǎn)像Lora的思路,具體還得調(diào)研下lora。
text transformer
在得到embedding之后,通過(guò)text transformer輸入給noise-predictor
transformer可以控制多種條件,如class labels、image、depth map等。
Cross-attention
具體cross-attention是什么我也不是很清楚。但這里有一個(gè)案例可以說(shuō)明:
比如說(shuō)我們使用prompt "A man with blue eyes"。雖然這里是兩個(gè)token,但stable diffusion會(huì)把這兩個(gè)單詞一起成對(duì)。
這樣就能保證生成一個(gè)藍(lán)色眼睛的男人。而不是一個(gè)藍(lán)色襪子或者其他藍(lán)色信息的男人。
(cross-attention between the prompt and the image)
LoRA models modify the cross-attention module to change styles。后面在研究Lora,這里把原話摘到這。
感覺(jué)更像是存在blue
、eyes
,然后有一個(gè)集合同時(shí)滿足blue
和eye
。去取這個(gè)交叉的集合。問(wèn)題:對(duì)應(yīng)的embedding是不是不一樣的?該如何區(qū)分blue planet in eye
和blue eye in planet
的區(qū)別?感覺(jué)這應(yīng)該是NLP的領(lǐng)域了。
總結(jié)下tex2img的過(guò)程
stable diffusion生成一個(gè)隨機(jī)的latent space matrix。這個(gè)由Random決定,如果Random不變,則這個(gè)latent space matrix不變。
通過(guò)noise-predictor,將noisy image與text prompt作為入?yún)?,預(yù)測(cè)predicted noise in latent space
latent noise減去predicted noise。將其作為新的latent noise
不斷重復(fù)2~3執(zhí)行step次。比如說(shuō)step=20
最終,通過(guò)VAE的decoder將latent representation生成最終的圖片
這個(gè)時(shí)候就可以貼Stable diffusion論文中的一張圖了
手撕一下公式:
左上角的定義為一張RGB像素空間的圖。經(jīng)過(guò)
的變化,生成
這個(gè)latent space representation。再經(jīng)過(guò)一系列的noise encoder,得到
,T表示step。
而這個(gè)過(guò)程則是img2img的input。如果是img2img,那么初始的noise latent representation就是這個(gè)不斷加noise之后的。
如果是tex2img,初始的noise latent representation則是直接random出來(lái)的。
再?gòu)挠蚁陆堑?img src="https://imgs.yssmx.com/Uploads/2023/10/725246-26.jpeg" alt="從零開(kāi)始的stable diffusion,stable diffusion,人工智能" referrerpolicy="no-referrer" />,開(kāi)始,y 表示多樣的控制條件的入?yún)ⅲ鐃ext prompts。通過(guò)
(domain specific encoder)將 y 轉(zhuǎn)為intermediate representation(一種中間表達(dá))。而
與
將經(jīng)過(guò)cross-attention layer的實(shí)現(xiàn):
具體的細(xì)節(jié)說(shuō)實(shí)話沒(méi)看懂,而這一部分在controlnet中也有解釋,打算從controlnet的部分進(jìn)行理解。
圖中cross-attention的部分可以很清晰的看到是一個(gè)由大到小,又由小到大的過(guò)程,在controlnet的圖中有解釋:
SD Encoder Block_1(64x64) -> SD Encoder Block_2(32x32) -> SD Encoder Block_3(16x16) -> SD Encoder(Block_4 8x8) -> SD Middle(Block 8x8) -> SD Decoder(Block_4 8x8) -> SD Decoder Block_3(16x16) -> SD Decoder Block_2(32x32) -> SD Decoder Blocker_1(64x64)
是一個(gè)從64x64
?->?8x8
?->?64x64
的過(guò)程,具體為啥,得等我撕完controlnet的論文?;氐竭^(guò)程圖中,我們可以看到denoising step則是在Latent Space的左下角進(jìn)行了一個(gè)循環(huán),這里與上面的流程一直。
最終通過(guò)VAE的decoder D,輸出圖片
最終的公式如下:
結(jié)合上面的圖看,基本還是比較清晰的,不過(guò)這個(gè):=和代表了啥就不是很清楚了。結(jié)合python代碼看流程更清晰~刪掉了部分代碼,只留下了關(guān)鍵的調(diào)用。
pipe = StableDiffusionPipeline.from_pretrained(
"CompVis/stable-diffusion-v1-4", torch_dtype=torch.float16
)
vae = AutoencoderKL.from_pretrained("CompVis/stable-diffusion-v1-4", subfolder="vae")
tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14")
text_encoder = CLIPTextModel.from_pretrained("openai/clip-vit-large-patch14")
unet = UNet2DConditionModel.from_pretrained(
"CompVis/stable-diffusion-v1-4", subfolder="unet"
)
scheduler = LMSDiscreteScheduler.from_pretrained(
"CompVis/stable-diffusion-v1-4", subfolder="scheduler"
)
prompt = ["a photograph of an astronaut riding a horse"]
generator = torch.manual_seed(32)
text_input = tokenizer(
prompt,
padding="max_length",
max_length=tokenizer.model_max_length,
truncation=True,
return_tensors="pt",
)
with torch.no_grad():
text_embeddings = text_encoder(text_input.input_ids.to(torch_device))[0]
max_length = text_input.input_ids.shape[-1]
uncond_input = tokenizer(
[""] * batch_size, padding="max_length", max_length=max_length, return_tensors="pt"
)
with torch.no_grad():
uncond_embeddings = text_encoder(uncond_input.input_ids.to(torch_device))[0]
text_embeddings = torch.cat([uncond_embeddings, text_embeddings])
latents = torch.randn(
(batch_size, unet.in_channels, height // 8, width // 8), generator=generator
)
scheduler.set_timesteps(num_inference_steps)
latents = latents * scheduler.init_noise_sigma
for t in tqdm(scheduler.timesteps):
latent_model_input = torch.cat([latents] * 2)
latent_model_input = scheduler.scale_model_input(latent_model_input, t)
with torch.no_grad():
noise_pred = unet(
latent_model_input, t, encoder_hidden_states=text_embeddings
).sample
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
noise_pred = noise_pred_uncond + guidance_scale * (
noise_pred_text - noise_pred_uncond
)
latents = scheduler.step(noise_pred, t, latents).prev_sample
latents = 1 / 0.18215 * latents
with torch.no_grad():
image = vae.decode(latents).sample
還是很貼合圖中流程的。
在代碼中有一個(gè)Scheduler,其實(shí)就是noising的執(zhí)行器,它主要控制每一步noising的強(qiáng)度。
由Scheduler不斷加噪,然后noise predictor進(jìn)行預(yù)測(cè)減噪。
具體可以看Stable Diffusion Samplers: A Comprehensive Guide(地址:https://stable-diffusion-art.com/samplers/)
?? Img2Img
這個(gè)其實(shí)在上面的流程圖中已經(jīng)解釋了。這里把步驟列一下:
輸入的image,通過(guò)VAE的encoder變成latent space representation
往里面加noise,總共加T個(gè)noise,noise的強(qiáng)度由Denoising strength控制。noise其實(shí)沒(méi)有循環(huán)加的過(guò)程,就是不斷疊同一個(gè)noise T次,所以可以一次計(jì)算完成。
noisy image和text prompt作為輸入,由noise predictor U-Net預(yù)測(cè)一個(gè)新的noise
noisy image減去預(yù)測(cè)的noise
重復(fù)3~4 step次
通過(guò)VAE的decoder將latent representation轉(zhuǎn)變成image
?? Inpainting
基于上面的原理,Inpainting就很簡(jiǎn)單了,noise只加到inpaint的部分。其他和Img2Img一樣。相當(dāng)于只生成inpaint的部分。所以我們也經(jīng)常發(fā)現(xiàn)inpaint的邊緣經(jīng)常無(wú)法非常平滑~如果能接受圖片的細(xì)微變化,可以調(diào)低Denoising strength,將inpaint的結(jié)果,再進(jìn)行一次img2img
Stable Diffusion v1 vs v2
v2開(kāi)始CLIP的部分用了OpenClip。導(dǎo)致生成的控制變得非常的難。OpenAI的CLIP雖然訓(xùn)練集更小,參數(shù)也更少。(OpenClip是ViT-L/14 CLIP的5倍大小)。但似乎ViT-L/14的訓(xùn)練集更好一些,有更多針對(duì)藝術(shù)和名人照片的部分,所以輸出的結(jié)果通常會(huì)更好。導(dǎo)致v2基本沒(méi)用起來(lái)。不過(guò)現(xiàn)在沒(méi)事了,SDXL橫空出世。
SDXL model
SDXL模型的參數(shù)達(dá)到了66億,而v1.5只有9.8億
由一個(gè)Base model和Refiner model組成。Base model負(fù)責(zé)生成,而Refiner則負(fù)責(zé)加細(xì)節(jié)完善??梢灾贿\(yùn)行Base model。但類似人臉眼睛模糊之類的問(wèn)題還是需要Refiner解決。
SDXL的主要變動(dòng):
text encoder組合了OpenClip和ViT-G/14。畢竟OpenClip是可訓(xùn)練的。
訓(xùn)練用的圖片可以小于256x256,增加了39%的訓(xùn)練集
U-Net的部分比v1.5大了3倍
默認(rèn)輸出就是1024x1024
展示下對(duì)比效果:
從目前來(lái)看,有朝一日SDXL遲早替代v1.5。從效果來(lái)說(shuō)v2.1確實(shí)被時(shí)代淘汰了。
Stable Diffusion的一些常見(jiàn)問(wèn)題
???臉部細(xì)節(jié)不足,比如說(shuō)眼部模糊
可以通過(guò)VAE files進(jìn)行修復(fù)~有點(diǎn)像SDXL的Refiner
???多指、少指
這個(gè)看起來(lái)是一個(gè)無(wú)解的問(wèn)題。Andrew給出的建議是加prompt比如說(shuō)beautiful hands
和detailed fingers
,期望其中有部分圖片滿足要求?;蛘哂胕npaint。反復(fù)重新生成手部。(這個(gè)時(shí)候可以用相同的prompt。)
團(tuán)隊(duì)介紹
我們是淘天集團(tuán)-場(chǎng)景智能技術(shù)團(tuán)隊(duì),作為一支專注于通過(guò)AI和3D技術(shù)驅(qū)動(dòng)商業(yè)創(chuàng)新的技術(shù)團(tuán)隊(duì), 依托大淘寶豐富的業(yè)務(wù)形態(tài)和海量的用戶、數(shù)據(jù), 致力于為消費(fèi)者提供創(chuàng)新的場(chǎng)景化導(dǎo)購(gòu)體驗(yàn), 為商家提供高效的場(chǎng)景化內(nèi)容創(chuàng)作工具, 為淘寶打造圍繞家的場(chǎng)景的第一消費(fèi)入口。我們不斷探索并實(shí)踐新的技術(shù), 通過(guò)持續(xù)的技術(shù)創(chuàng)新和突破,創(chuàng)新用戶導(dǎo)購(gòu)體驗(yàn), 提升商家內(nèi)容生產(chǎn)力, 讓用戶享受更好的消費(fèi)體驗(yàn), 讓商家更高效、低成本地經(jīng)營(yíng)。
¤?拓展閱讀?¤
3DXR技術(shù)?|?終端技術(shù)?|?音視頻技術(shù)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-725246.html
服務(wù)端技術(shù)?|?技術(shù)質(zhì)量?|?數(shù)據(jù)算法文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-725246.html
到了這里,關(guān)于從零開(kāi)始的stable diffusion的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!