目錄
1 Unet
1.0 介紹
1.1詳細(xì)整體結(jié)構(gòu)
1.2 縮小版整體結(jié)構(gòu)
1.3 時間步編碼
1.4?CrossAttnDownBlock2D
1.4.1 ResnetBlock2D
1.4.2?Transformer2DModel
1.4.2.1?BasicTransformerBlock
1.4.2.1.1?SelfAttention
1.4.2.1.2?CrossAttention
1.4.2.1.3?FeedForward
1.4.3?DownSample2D
1.5?DownBlock2D
1.6?UnetMidBlock2DCrossAttn
1.7?UpBlock2D
1.7.1?UpSample2D
1.8?CrossAttnUpBlock2D
2 VAE
2.0 介紹
2.1 AE
2.2 VAE
2.3 整體結(jié)構(gòu)?
2.4?DownEncoderBlock2D
2.4.1??ResnetBlock2D
2.4.2?UpSample2D
2.5?UnetMidBlock2D
2.6?Sample
2.7?UpDecoderBlock2D
?2.7.1??UpSample2D
3 CLIP
3.1? CLIPTextEmbeddings
3.2??CLIPEncoderLayer
繪制軟件:ProcessOn,以下圖片保存可高清查看
1 Unet
1.0 介紹
????????負(fù)責(zé)預(yù)測噪聲
1.1詳細(xì)整體結(jié)構(gòu)
1.2 縮小版整體結(jié)構(gòu)
1.3 時間步編碼
1.4?CrossAttnDownBlock2D
每個ResnetBlock2D的輸入有兩個
1,一個是來自上一層的輸出lattent,
2,另一個來自時間步編碼模塊的輸出time_embeds ( shape=[2, 1280], 后面省略說明,默認(rèn)[2, 1280]這種寫法是tersor的形狀)
每個Transformer2DModel輸入有兩個
1,上一層的輸出
2, CLIP text_encoder的文本編碼text embedding,或者叫提示詞編碼prompt embedding,其shape=[2, 77, 768]
后面凡是有ResnetBlock2D和Transformer2DModel的模塊,其輸入形式都是如此,為了方便,后面有些模塊的time_embeds和prompt? embedding這兩個輸入就默認(rèn)不畫了,例如UnetMidBlock2DCrossAttn、UpBlock2D、CrossAttnUpBlock2D
1.4.1 ResnetBlock2D
需要注意的點(diǎn)
1, ResnetBlock2D的輸入有兩個,一個是來自上一層的lattent,另一個來自時間步編碼模塊的輸出time_embeds ( shape=[2, 1280], 后面省略說明,默認(rèn)[2, 1280]這種寫法是tersor的形狀)
2, Conv3x3和Linear的輸入輸出Channel,不同層會不一樣
3, 輸入輸出通道數(shù)不一致的時候,殘差連接會用一個1x1的卷積
1.4.2?Transformer2DModel
Transformer2DModel輸入有兩個
1,上一層的輸入
2, CLIP text_encoder的文本編碼text embedding,或者叫提示詞編碼prompt embedding,其shape=[2, 77, 768]
1.4.2.1?BasicTransformerBlock
1.4.2.1.1?SelfAttention
1.4.2.1.2?CrossAttention
1.4.2.1.3?FeedForward
1.4.3?DownSample2D
1.5?DownBlock2D
1.6?UnetMidBlock2DCrossAttn
1.7?UpBlock2D
UNet右邊部分的ResnetBlock2D模塊,其輸入除了有來自上一層的輸出和time_embedd之外,還有自UNet左邊部分輸入,具體做法是將上一層的輸出和UNet左邊部分輸入進(jìn)行concat之后送進(jìn)ResnetBlock2D模塊,然后和time_embedd相加,后面的CrossAttnUpBlock2D也是如此,具體查看1.1 詳細(xì)整體結(jié)構(gòu)
1.7.1?UpSample2D
1.8?CrossAttnUpBlock2D
注意, 最后一個CrossAttnUpBlock2D沒有UpSample2D模塊,該模塊具體輸入輸出shape看1.1 詳細(xì)整體結(jié)構(gòu)
2 VAE
2.0 介紹
將擴(kuò)散過程從512x512的圖像空間映射降維到64x64的潛空間,內(nèi)存和運(yùn)算量減小64倍
2.1 AE
注意:下面說的特征向量,編碼向量,潛變量,code是同一個意思
普通的自編碼器,分為編碼器和解碼器,編碼器Encoder負(fù)責(zé)將編碼圖像,把圖像從高維映射到低維,得到特征向量,例如把3x512x512的圖像編碼成4x64x64的特征向量,這個特征向量可以表示原始圖像,包含原始圖像的特征,比如顏色,紋理等其他抽象特征,解碼器Decoder負(fù)責(zé)把低維的特征向量還原回原始圖像.但這種編碼是固定的,一張圖片只能編碼成一個固定的向量,反過來,解碼也是唯一的,一個固定的編碼向量只會被解碼成一張確定的圖像,如果來一張你訓(xùn)練集沒見過的圖片,對其編碼后再解碼,生成的圖像大概率是個無意義的圖像,因此AE是一個單值映射關(guān)系,潛變量(即編碼向量)具有不連續(xù)性,潛變量是確定性值,選擇一個隨機(jī)的潛在變量可能會產(chǎn)生垃圾輸出,潛在空間缺乏生成能力(即潛空間不是所有的潛變量都是有效的),
舉個李宏毅老師的例子:
假設(shè)我們訓(xùn)練好的AE將“新月”圖片encode成code=1(這里假設(shè)code只有1維),將其decode能得到“新月”的圖片;將“滿月”encode成code=10,同樣將其decode能得到“滿月”圖片。這時候如果我們給AE一個code=5,我們希望是能得到“半月”的圖片,但由于之前訓(xùn)練時并沒有將“半月”的圖片編碼,或者將一張非月亮的圖片編碼為5,那么我們就不太可能得到“半月”的圖片。
其他博客解釋:
????????AE的Encoder是將圖片映射成“數(shù)值編碼”,Decoder是將“數(shù)值編碼”映射成圖片。這樣存在的問題是,在訓(xùn)練過程中,隨著不斷降低輸入圖片與輸出圖片之間的誤差,模型會過擬合,泛化性能不好。也就是說對于一個訓(xùn)練好的AE,輸入某個圖片,就只會將其編碼為某個確定的code,輸入某個確定的code就只會輸出某個確定的圖片,并且如果這個code來自于沒見過的圖片,那么生成的圖片也不會好。
????????自動編碼器是數(shù)據(jù)相關(guān)的(data-specific 或 data-dependent),這意味著自動編碼器只能壓縮那些與訓(xùn)練數(shù)據(jù)類似的數(shù)據(jù),反過也是一類數(shù)據(jù)對應(yīng)一種編碼器,無法拓展一種編碼器去應(yīng)用于另一類數(shù)據(jù)。
2.2 VAE
而VAE不是將圖像編碼成一個固定的值,而是編碼成一個連續(xù)的分布,這樣,只要滿足這個分布,我就能重建原始圖像,滿足這個分布的值會有很多,不再是一個固定的code了,例如,我把編碼器的輸出約束成一個標(biāo)準(zhǔn)正態(tài)分布,重建圖像我只需要從標(biāo)準(zhǔn)正態(tài)分布采樣在送到就解碼器即可,
這里其實不一定非得要是標(biāo)準(zhǔn)正態(tài)分布,只要是連續(xù)的分布理論上都可以,但由于標(biāo)準(zhǔn)正態(tài)分布有良好的性質(zhì):1,高維正態(tài)分布采樣的向量模長近似一致,兩兩近似正交,兩點(diǎn)之間的歐式距離與期望值近似,這是一個很好的約束,對模型的學(xué)習(xí)有利;2,良好的數(shù)學(xué)性質(zhì),但你對多個分布進(jìn)行運(yùn)算時(像Diffusion),正態(tài)分布會帶來很大的便利,可以通過標(biāo)準(zhǔn)化,變換等方式處理,便于模型的訓(xùn)練和優(yōu)化;3,用標(biāo)準(zhǔn)正態(tài)分布對潛變量進(jìn)行建模,能利用正態(tài)分布的性質(zhì)進(jìn)行隨機(jī)采樣和重構(gòu)(重參數(shù)化)
舉個例子:來自https://www.cnblogs.com/amazingter/p/14686450.html
針對上面的半月問題,我們轉(zhuǎn)變思路,不將圖片映射成“數(shù)值編碼”,而將其映射成“分布”。我們將“新月”圖片映射成μ=1的正態(tài)分布,那么就相當(dāng)于在1附近加了噪聲,此時不僅1表示“新月”,1附近的數(shù)值也表示“新月”,只是1的時候最像“新月”。將"滿月"映射成μ=10的正態(tài)分布,10的附近也都表示“滿月”。那么code=5時,就同時擁有了“新月”和“滿月”的特點(diǎn),那么這時候decode出來的大概率就是“半月”了。這就是VAE的思想。
關(guān)于VAE還可以參考【VAE學(xué)習(xí)筆記】全面通透地理解VAE(Variational Auto Encoder)_vae的作用-CSDN博客
寫的很好,接下來正式上圖
2.3 整體結(jié)構(gòu)?
由于csdn查看大圖很撈,可雙擊另存為查看高清大圖
2.4?DownEncoderBlock2D
注意:VAE的ResnetBlock2D模塊是沒有時間步的輸入的,即time_embeds=None, 其他的和上面Unet中的ResnetBlock2D一致
2.4.1??ResnetBlock2D
2.4.2?UpSample2D
2.5?UnetMidBlock2D
SelfAttention參考Unet中的
2.6?Sample
重參數(shù)化技巧:
現(xiàn)在均值mean和方差var(實際是log方差,這里先以方差為例)是網(wǎng)絡(luò)的輸出,也就是現(xiàn)在編碼器的輸出服從N~(mean, var)這個正態(tài)分布,我們要從這個正態(tài)分布采樣出一個樣本,送進(jìn)解碼器,這個樣本是服從N~(mean, var)正態(tài)分布的,但采樣這個操作是不可導(dǎo)的,采樣操作是指從某個概率分布中隨機(jī)抽取樣本的過程,因為梯度是損失函數(shù)關(guān)于模型參數(shù)的變化率,而采樣操作的非確定性使得無法直接計算關(guān)于參數(shù)的精確梯度。如果將采樣操作視為一個具有參數(shù)的函數(shù),并嘗試計算其導(dǎo)數(shù),通常會遇到兩個問題:
-
不可導(dǎo)性: 由于采樣操作引入了離散性和不可導(dǎo)性,它們在大多數(shù)情況下是不可導(dǎo)的。導(dǎo)數(shù)描述的是函數(shù)在某一點(diǎn)上的變化率,而采樣操作在這方面表現(xiàn)得很突變和不連續(xù),因此沒有明確定義的導(dǎo)數(shù)。
-
梯度的方差: 即使我們忽略不可導(dǎo)性,嘗試使用梯度信息來更新參數(shù),由于采樣引入的隨機(jī)性,梯度的方差可能會非常高,導(dǎo)致不穩(wěn)定的優(yōu)化過程。
所以無法對mean和var求偏導(dǎo),因為這里mean和var就是網(wǎng)絡(luò)的參數(shù),這個時候可以從標(biāo)準(zhǔn)正態(tài)分布N(0,1)采樣一個sample(一般會用概率密度的分布函數(shù)去采樣), 這個時候sample就是一個確定的值,把sample當(dāng)成常數(shù),std是標(biāo)準(zhǔn)差,等于var開根號
令z=mean + sample * std,這個時候z就可以對mean和std求偏導(dǎo)了,z就等價從N~(mean, var)這個分布采樣,可以對z求期望和方差,根據(jù)高斯分布的性質(zhì)以及期望和方差的公式,能得出z也服從正態(tài)分布,切均值=mean, 方差=std的平方=var,這樣做其實是把隨機(jī)性轉(zhuǎn)移到了sample這個常數(shù)
但代碼里是log方差,是因為方差是正的,加log讓它取值范圍也能取負(fù)值,這樣就不用加激活函數(shù)了,所以后面再用exp還原方差
2.7?UpDecoderBlock2D
?2.7.1??UpSample2D
3 CLIP
CLIP這里用到的是文本編碼器,結(jié)構(gòu)如下
3.1? CLIPTextEmbeddings
灰色的框框text_inoputs和embedding不是操作,是表示輸入輸出
3.2??CLIPEncoderLayer
CLIPEncoderLayer就是普通的Transformer的Encoder層了文章來源:http://www.zghlxwxcb.cn/news/detail-758735.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-758735.html
到了這里,關(guān)于Stable Diffusion1.5網(wǎng)絡(luò)結(jié)構(gòu)-超詳細(xì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!