DIFFUSION 系列筆記|DDIM 數學、思考與 ppdiffuser 程式碼探索 論文:DENOISING DIFFUSION IMPLICIT MODELS
參考 部落格open in new window ; 參考 aistudio notebook 連結,其中包含詳細的公式與程式碼探索: linkopen in new window
該文章主要對 DDIM 論文中的公式進行小白推導,同時筆者將使用 ppdiffuser 中的 DDIM 與 DDPM 探索兩者之間的聯絡。讀者能夠對論文中的大部分公式如何得來,用在了什麼地方有初步的瞭解。
本文將包括以下部分:
總結 DDIM。 Non-Markovian Forward Processes: 從 DDPM 出發,記錄論文中公式推導 探索與思考: 驗證當 η = 1 \eta=1 DDIMScheduler 的結果與 DDPMScheduler 基本相同。 DDIM 的加速取樣過程 DDIM 取樣的確定性 INTERPOLATION IN DETERMINISTIC GENERATIVE PROCESSES DDIM 總覽 不同於 DDPM 基於馬爾可夫的 Forward Process,DDIM 提出了 NON-MARKOVIAN FForward Processes。(見 Forward Process) 基於這一假設,DDIM 推匯出了相比於 DDPM 更快的取樣過程。(見探索與思考 ) 相比於 DDPM,DDIM 的取樣是確定的,即給定了同樣的初始噪聲 x t x_t ,DDIM 能夠生成相同的結果 x 0 x_0 。(見探索與思考 ) DDIM 和 DDPM 的訓練方法相同 ,因此在 DDPM 基礎上加上 DDIM 取樣方案即可。(見探索與思考 ) Forward process DDIM 論文中公式的符號與 DDPM 不相同,如 DDIM 論文中的 α \alpha 相當於 DDPM 中的 α ˉ \bar\alpha ,而 DDPM 中的 α t \alpha_t 則在 DDIM 中記成 α t α t − 1 \frac {\alpha_t}{\alpha_{t-1}} ,但是運算思路一致,如 DDIM 論文中的公式 ( 1 ) − ( 5 ) (1)-(5) 都在 DDPM 中能找到對應公式。
以下我們統一採用 DDPM 中的符號進行標記。即 α ˉ t = α 1 α 2 . . . α t \bar\alpha_t = \alpha_1\alpha_2...\alpha_t
在 DDPM 筆記 擴散模型探索:DDPM 筆記與思考open in new window 中,我們總結了 DDPM 的取樣公式推導過程為:
x t → m o d e l ϵ θ ( x t , t ) → P ( x t ∣ x 0 ) → P ( x 0 ∣ x t , ϵ θ ) x ^ 0 ( x t , ϵ θ ) → 推導 μ ( x t , x ^ 0 ) , β t → P ( x t − 1 ∣ x t , x 0 ) x ^ t − 1 x_t\xrightarrow{model} \epsilon_\theta(x_t,t) \xrightarrow {P(x_t|x_0)\rightarrow P(x_0|x_t,\epsilon_\theta)}\hat x_0(x_t, \epsilon_\theta) \\ \xrightarrow {\text{ 推導 }}\mu(x_t, \hat x_0),\beta_t\xrightarrow{P(x_{t-1}|x_t, x_0)}\hat x_{t-1}
而後我們用 x ^ t − 1 \hat x_{t-1} 來近似 x t − 1 x_{t-1} ,從而一步步實現取樣的過程。不難發現 DDPM 取樣和最佳化損失函式過程中,並沒有使用到 p ( x t − 1 ∣ x t ) p(x_{t-1}|x_t) 的資訊。因此 DDIM 從一個更大的角度,大膽地將 Forward Process 方式更換了以下式子(對應 DDIM 論文公式 ( 7 ) (7) ):
q σ ( x t − 1 ∣ x t , x 0 ) = N ( x t − 1 ; α ˉ t − 1 x 0 + 1 − α ˉ t − 1 − σ t 2 x t − α ˉ t x 0 1 − α ˉ t , σ t 2 I ) (1) q_\sigma\left(\mathbf{x}_{t-1} \mid \mathbf{x}_t, \mathbf{x}_0\right)=\mathcal{N}\left(\mathbf{x}_{t-1} ; \sqrt{\bar\alpha_{t-1}} \mathbf{x}_0+\sqrt{1-\bar\alpha_{t-1}-\sigma_t^2} \frac{\mathbf{x}_t-\sqrt{\bar\alpha_t} \mathbf{x}_0}{\sqrt{1-\bar\alpha_t}}, \sigma_t^2 \mathbf{I}\right)\tag1
論文作者提到了 ( 1 ) (1) 式這樣的 non-Markovian Forward Process 滿足 :
q ( x t ∣ x 0 ) = N ( x t ; α ˉ t x 0 , ( 1 − α ˉ t ) I ) , α ˉ t = ∏ T α t (2) q(x_t|x_0) =N (x_t; \sqrt {\bar \alpha_t} x_0, (1-\bar\alpha_t)I),\bar \alpha_t=\prod_T\alpha_t\tag 2
公式 ( 1 ) (1) 能夠透過貝葉斯公式:
q ( x t ∣ x t − 1 , x 0 ) = q ( x t − 1 ∣ x t , x 0 ) q ( x t ∣ x 0 ) q ( x t − 1 ∣ x 0 ) (3) q(x_t|x_{t-1},x_0) = \frac{q(x_{t-1}|x_t,x_0)q(x_t|x_0)}{q(x_{t-1}|x_0)}\tag 3
推導得來。至於如何推導,生成擴散模型漫談(四):DDIM = 高觀點 DDPMopen in new window 中透過待定係數法給出了詳細的解釋,由於解釋計算過程較長,此處就不展開介紹了。
根據 ( 1 ) (1) ,將 DDPM 中得到的公式(同 DDIM 論文中的公式 ( 9 ) (9) ):
x 0 = x t − 1 − α ˉ t ϵ θ ( t ) ( x t ) α ˉ t (4) x_0 = \frac{\boldsymbol{x}_t-\sqrt{1-\bar\alpha_t} \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}{\sqrt{\bar\alpha_t}}\tag 4
帶入,我們能寫出取樣公式(即論文中的核心公式 ( 12 ) (12) ):
x t − 1 = α ˉ t − 1 ( x t − 1 − α ˉ t ϵ θ ( t ) ( x t ) α ˉ t ) ⏟ " predicted x 0 " + 1 − α ˉ t − 1 − σ t 2 ⋅ ϵ θ ( t ) ( x t ) ⏟ "direction pointing to x t " + σ t ϵ t ⏟ random noise (5) \boldsymbol{x}_{t-1}=\sqrt{\bar\alpha_{t-1}} \underbrace{\left(\frac{\boldsymbol{x}_t-\sqrt{1-\bar\alpha_t} \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}{\sqrt{\bar\alpha_t}}\right)}_{\text {" predicted } \boldsymbol{x}_0 \text { " }}+\underbrace{\sqrt{1-\bar\alpha_{t-1}-\sigma_t^2} \cdot \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}_{\text {"direction pointing to } \boldsymbol{x}_t \text { " }}+\underbrace{\sigma_t \epsilon_t}_{\text {random noise }}\tag 5
其中,σ \sigma 可以參考 DDIM 論文的公式 ( 16 ) (16) :
σ t = η ( 1 − α ˉ t − 1 ) / ( 1 − α ˉ t ) 1 − α ˉ t / α ˉ t − 1 (6) \sigma_t =\eta \sqrt {(1-\bar\alpha_{t-1})/(1-\bar\alpha_t)} \sqrt{1-\bar\alpha_t/\bar\alpha_{t-1}}\tag 6
如果 η = 0 \eta = 0 ,那麼生成過程就是確定的,這種情況下為 DDIM。
論文中指出, 當 η = 1 \eta=1 ,該 forward process 變成了馬爾科夫鏈,該生成過程等價於 DDPM 的生成過程 。也就是說當 η = 1 \eta=1 時,公式 ( 5 ) (5) 等於 DDPM 的取樣公式,即公式 ( 7 ) (7) :
x ^ t − 1 = 1 α t ( x t − 1 − α t 1 − α ˉ t ϵ θ ( x t , t ) ) + σ t z where z = N ( 0 , I ) (7) \begin{aligned} \hat x_{t-1}&=\frac 1{\sqrt { \alpha_t}}(x_t-\frac{1-\alpha_t}{\sqrt{1-\bar\alpha_t}}\epsilon_\theta(x_t,t)) + \sigma_t z\\ &\text{where }z=N(0,I) \end{aligned}\tag 7
將 ( 6 ) (6) 式帶入到 ( 1 ) (1) 式中得到 DDPM 分佈公式(本文章標記依照 DDPM 論文,因此有 α ˉ t = ∏ T α t \bar \alpha_t=\prod_T\alpha_t ):
1 − α ˉ t − 1 − σ t 2 = 1 − α ˉ t − 1 1 − α ˉ t α t (8) \sqrt{1-\bar\alpha_{t-1}-\sigma_t^2} =\frac{1-\bar\alpha_{t-1}}{\sqrt{1-\bar\alpha_t}}\sqrt{\alpha_t} \tag 8
上式的推導過程 1 − α ˉ t 1 − α ˉ t 1 − α ˉ t − 1 − σ t 2 = [ ( 1 − α ˉ t − 1 − ( 1 − α ˉ t − 1 1 − α ˉ t ) ( 1 − α t ) ] ( 1 − α ˉ t ) 1 − α ˉ t = ( 1 − α ˉ t − 1 ) ( 1 − ( 1 − α ˉ t − 1 1 − α ˉ t ) ( 1 − α t ) ) ( 1 − α ˉ t − 1 ) 1 − α ˉ t = ( 1 − α ˉ t − 1 ) ( 1 − α ˉ t − 1 + α ˉ t α ˉ t − 1 ) 1 − α ˉ t = ( 1 − α ˉ t − 1 ) ( 1 − α ˉ t − 1 ) α ˉ t α ˉ t − 1 1 − α ˉ t = 1 − α ˉ t − 1 1 − α ˉ t α t \begin{aligned} \frac {\sqrt{1-\bar\alpha_t}}{\sqrt{1-\bar\alpha_t}} \sqrt{1-\bar\alpha_{t-1}-\sigma_t^2} &= \frac{\sqrt{[(1-\bar\alpha_{t-1}-(\frac{1-\bar\alpha_{t-1}}{1-\bar\alpha_t})(1-\alpha_t)](1-\bar\alpha_t)}}{\sqrt{1-\bar\alpha_t}}\\ &=\frac{\sqrt{(1-\bar\alpha_{t-1})(1-(\frac{1-\bar\alpha_{t-1}}{1-\bar\alpha_t})(1-\alpha_t))(1-\bar\alpha_{t-1})}}{\sqrt{1-\bar\alpha_t}} \\ &= \frac{\sqrt{(1-\bar\alpha_{t-1})(1-\bar\alpha_t-1+\frac{\bar\alpha_t}{\bar\alpha_{t-1}})}}{\sqrt{1-\bar\alpha_t}}\\ &= \frac{\sqrt{(1-\bar\alpha_{t-1})(1-\bar\alpha_{t-1})\frac{\bar\alpha_t}{\bar\alpha_{t-1}}}}{\sqrt{1-\bar\alpha_t}} \\&=\frac{1-\bar\alpha_{t-1}}{\sqrt{1-\bar\alpha_t}}\sqrt{\alpha_t} \end{aligned}
因此
x t − 1 = α ˉ t − 1 ( x t − 1 − α ˉ t ϵ θ ( t ) ( x t ) α ˉ t ) ⏟ " predicted x 0 " + 1 − α ˉ t − 1 − σ t 2 ⋅ ϵ θ ( t ) ( x t ) ⏟ "direction pointing to x t " + σ t ϵ t ⏟ random noise = α ˉ t − 1 α ˉ t x t − α ˉ t − 1 α ˉ t 1 − α ˉ t ϵ θ ( t ) + 1 − α ˉ t − 1 1 − α ˉ t α t ϵ θ ( t ) + σ t ϵ t = 1 α t x t − 1 α t 1 − α ˉ t ( 1 − α ˉ t + ( 1 − α ˉ t − 1 ) α t ) ϵ θ ( t ) + σ t ϵ t = 1 α t ( x t − 1 − α t 1 − α ˉ t ϵ θ ( t ) ) + σ t ϵ t = 1 α t ( x t − β t 1 − α ˉ t ϵ θ ( t ) ) + σ t ϵ t (9) \begin{aligned} \boldsymbol{x}_{t-1}&=\sqrt{\bar\alpha_{t-1}} \underbrace{\left(\frac{\boldsymbol{x}_t-\sqrt{1-\bar\alpha_t} \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}{\sqrt{\bar\alpha_t}}\right)}_{\text {" predicted } \boldsymbol{x}_0 \text { " }}+\underbrace{\sqrt{1-\bar\alpha_{t-1}-\sigma_t^2} \cdot \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}_{\text {"direction pointing to } \boldsymbol{x}_t \text { " }}+\underbrace{\sigma_t \epsilon_t}_{\text {random noise }} \\&= \sqrt \frac{\bar\alpha_{t-1}}{\bar\alpha_t} x_t-\sqrt \frac{\bar\alpha_{t-1}}{\bar\alpha_t} \sqrt {1-\bar\alpha_t} \epsilon_\theta^{(t)} + \frac{1-\bar\alpha_{t-1}}{\sqrt{1-\bar\alpha_t}}\sqrt{\alpha_t} \epsilon_\theta^{(t)} + \sigma_t \epsilon_t \\&=\frac 1{\sqrt\alpha_t}x_t - \frac 1{\sqrt\alpha_t \sqrt{1-\bar\alpha_t}}\left(1-\bar\alpha_t+(1-\bar\alpha_{t-1})\alpha_t \right)\epsilon_\theta^{(t)} + \sigma_t \epsilon_t\\ &=\frac 1{\sqrt\alpha_t}\left(x_t - \frac{1-\alpha_t}{\sqrt{1-\bar\alpha_t}} \epsilon_\theta^{(t)} \right)+ \sigma_t \epsilon_t\\ &=\frac 1{\sqrt\alpha_t}\left(x_t - \frac{\beta_t}{\sqrt{1-\bar\alpha_t}} \epsilon_\theta^{(t)} \right)+ \sigma_t \epsilon_t \end{aligned} \tag 9
因此,根據推導,η = 1 \eta=1 時候的 Forward Processes 等價於 DDPM,我們將在 notebook 後半部分,透過程式碼的方式驗證當 η = 1 \eta=1 DDIM 的結果與 DDPM 基本相同。
探索與思考 接下來將根據飛槳開源的 PaddleNLP/ppdiffusers
,探索以下四個內容:
驗證當 η = 1 \eta=1 DDIM 的結果與 DDPM 基本相同。 DDIM 的加速取樣過程 DDIM 取樣的確定性 INTERPOLATION IN DETERMINISTIC GENERATIVE PROCESSES 讀者可以在 Aistudio 上使用免費 GPU 體驗以下的程式碼內容。連結:擴散模型探索:DDIM 筆記與思考open in new window
DDIM 與 DDPM 探索 驗證當 η = 1 \eta=1 DDIM 的結果與 DDPM 基本相同。
我們使用 DDPM 模型訓練出來的 google/ddpm-celebahq-256
人像模型權重進行測試,根據上文的推導,當 η = 1 \eta=1 時,我們期望 DDIM 論文中的 Forward Process 能夠得出與 DDPM 相同的取樣結果。由於 DDIM 與 DDPM 訓練過程相同,因此我們將使用 DDPMPipeline
載入模型權重 google/ddpm-celebahq-256
,而後採用 DDIMScheduler()
進行圖片取樣,並將取樣結果與 DDPMPipeline
原始輸出對比。如下:
# DDPM 生成圖片
pipe = DDPMPipeline.from_pretrained( "google/ddpm-celebahq-256" )
paddle.seed( 33 )
ddpm_output = pipe() # 原始 ddpm 輸出
# 我們採用 DDPM 的訓練結果,透過 DDIM Scheduler 來進行取樣。
pipe.scheduler = DDIMScheduler()
# 設定與 DDPM 相同的取樣結果,令 DDIM 取樣過程中的 eta = 1.
paddle.seed( 33 )
ddim_output = pipe( num_inference_steps = 1000 , eta = 1 )
imgs = [ddpm_output.images[ 0 ], ddim_output.images[ 0 ]]
titles = [ "ddpm" , "ddim" ]
compare_imgs(imgs, titles) # 該函式在 notebook_utils.py 宣告
輸出結果:
程式碼輸出結果: DDPM 與 DDIM 取樣下的圖片對比 透過執行以上程式碼,我們可以看出 η = 1 \eta=1 時, 預設配置下 DDPM 與 DDIM 取樣結果有著明顯的區別。但這並不意味著論文中的推導結論是錯誤的,差異可能源於以下兩點:
計算機浮點數精度問題 Scheduler 取樣過程中存在的 clip 操作導致偏差。 嘗試去除 Clip 操作 Scheduler 取樣過程中存在的 clip 操作導致偏差。Clip 操作對取樣過程中生成的 x_0
預測結果進行了截斷,儘管 DDPM, DDIM 均在預測完 x 0 x_0 後進行了截斷,但根據上文的推導公式,兩者取樣過程中 x 0 x_0 權重的不同,可能導致了使用 clip 時,兩者的取樣結果有著明顯區別。
將 clip 配置設定成 False
後, DDPM 與 DDIM(η = 1 \eta=1 ) 的取樣結果基本上相同了。如以下程式碼,我們嘗試測試去除 clip 配置後的取樣結果:
pipe = DDPMPipeline.from_pretrained( "google/ddpm-celebahq-256" )
pipe.progress_bar = lambda x:x # uncomment to see progress bar
# 我們採用 DDPM 的訓練結果,透過 DDIM Scheduler 來進行取樣。
# print("Default setting for DDPM:\t",pipe.scheduler.config.clip_sample) # True
pipe.scheduler.config.clip_sample = False
paddle.seed( 33 )
ddpm_output = pipe()
pipe.scheduler = DDIMScheduler()
# print("Default setting for DDIM:\t",pipe.scheduler.config.clip_sample) # True
pipe.scheduler.config.clip_sample = False
paddle.seed( 33 )
ddim_output = pipe( num_inference_steps = 1000 , eta = 1 )
imgs = [ddpm_output.images[ 0 ], ddim_output.images[ 0 ]]
titles = [ "DDPM no clip" , "DDIM no clip" ]
compare_imgs(imgs, titles)
可以驗證得到 DDPM 與 DDIM 論文中提出的 η = 1 \eta=1 情況下的取樣結果基本一致。
img DDIM 加速取樣 論文附錄 C 有對這一部分進行詳細闡述。DDIM 最佳化時與 DDPM 一樣,對噪聲進行擬合,但 DDIM 提出了透過一個更短的 Forward Processes 過程,透過減少取樣的步數,來加快取樣速度:
從原先的取樣序列 { 1 , . . . , T } \{1,...,T\} 中選擇一個子序列來生成影像。如原序列為 1 到 1000,抽取子序列可以是 1, 100, 200, ... 1000 (類似 arange(1, 1000, 100)
)。抽取方式不固定。在生成時同樣採用公式 ( 1 ) (1) ,其中的 timestep t t ,替換為子序列中的 timestep。其中的 α ˉ t \bar\alpha_t 對應到訓練時候的數值,比如取樣 1, 100, 200, ... 1000
中的第二個樣本,則使用訓練時候採用的 α ˉ 100 \bar\alpha_{100} (此處只能替換 alphas_cumprod
α ˉ \bar\alpha ,不能直接替換 alpha
引數 α t \alpha_t )。
參考論文中的 Figure 3,在加速生成的情況下,η \eta 越小,生成的圖片效果越好,同時 η \eta 的減小能夠很大程度上彌補取樣步數減少帶來的生成質量下降問題。
我們嘗試對論文中提到的上述方法進行復現:
pipe.progress_bar = lambda x:x # cancel process bar
etas = [ 0 , 0.4 , 0.8 ]
steps = [ 10 , 50 , 100 , 1000 ]
fig = plt.figure( figsize = ( 7 , 7 ))
for i in range ( len (etas)):
for j in range ( len (steps)):
plt.subplot( len (etas), len (steps), j + i * len (steps) + 1 )
paddle.seed( 77 )
sample1 = pipe( num_inference_steps = steps[j], eta = etas[i])
plt.imshow(sample1.images[ 0 ])
plt.axis( "off" )
plt.title( f "eta { etas[i] } |step { steps[j] } " )
plt.show()
img 透過論文中的示例說明,以及上述實現結果可以發現幾點:
η \eta 越小,取樣步數產生的 圖片質量和風格差異 就越小。η \eta 的減小能夠很大程度上彌補取樣步數減少帶來的生成質量下降問題。 DDIM 取樣的確定性 由於 DDIM 在生成過程中 η = 0 \eta=0 ,因此取樣過程中不涉及任何隨機因素,最終生成圖片將由一開始輸入的圖片噪聲 x t x_t 決定。我們採用不同的 random seed 進行取樣:
paddle.seed( 77 )
x_t = paddle.randn(( 1 , 3 , 256 , 256 ))
paddle.seed( 8 )
sample1 = pipe( num_inference_steps = 50 , eta = 0 , x_t = x_t)
paddle.seed( 9 )
sample2 = pipe( num_inference_steps = 50 , eta = 0 , x_t = x_t)
compare_imgs([sample1.images[ 0 ], sample2.images[ 0 ]], [ "sample(seed 8)" , "sample(seed 9)" ])
DDIM 取樣的確定性 影像重建 在 DDIM 論文中,其作者提出了可以將一張原始圖片 x 0 x_0 經過足夠長的步數 T T 加噪為 x T x_T ,而後透過 ODE 推匯出來的取樣方式,儘可能的還原原始圖片。 根據公式 ( 5 ) (5) (即論文中的公式 12),我們能夠推理得到論文中的公式 ( 13 ) (13) :
x t − Δ t α t − Δ t = x t α t + ( 1 − α t − Δ t α t − Δ t − 1 − α t α t ) ϵ θ ( t ) ( x t ) (10) \frac{\boldsymbol{x}_{t-\Delta t}}{\sqrt{\alpha_{t-\Delta t}}}=\frac{\boldsymbol{x}_t}{\sqrt{\alpha_t}}+\left(\sqrt{\frac{1-\alpha_{t-\Delta t}}{\alpha_{t-\Delta t}}}-\sqrt{\frac{1-\alpha_t}{\alpha_t}}\right) \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right) \tag {10}
大致推導過程 x t − 1 = α ˉ t − 1 ( x t − 1 − α ˉ t ϵ θ ( t ) ( x t ) α ˉ t ) ⏟ " predicted x 0 " + 1 − α ˉ t − 1 − σ t 2 ⋅ ϵ θ ( t ) ( x t ) ⏟ "direction pointing to x t " + σ t ϵ t ⏟ random noise x t − 1 α ˉ t − 1 = x t α ˉ t − 1 − α ˉ t α ˉ t ϵ θ ( t ) + 1 − α ˉ t − 1 α ˉ t − 1 ϵ θ ( t ) ( x t ) 當 t 足夠大時可以看做 x t − Δ t α ˉ t − Δ t = x t α ˉ t + ( 1 − α ˉ t − Δ t α ˉ t − Δ t − 1 − α ˉ t α ˉ t ) ϵ θ ( t ) ( x t ) \begin{aligned} \boldsymbol{x}_{t-1}&=\sqrt{\bar\alpha_{t-1}} \underbrace{\left(\frac{\boldsymbol{x}_t-\sqrt{1-\bar\alpha_t} \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}{\sqrt{\bar\alpha_t}}\right)}_{\text {" predicted } \boldsymbol{x}_0 \text { " }}+\underbrace{\sqrt{1-\bar\alpha_{t-1}-\sigma_t^2} \cdot \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}_{\text {"direction pointing to } \boldsymbol{x}_t \text { " }}+\underbrace{\sigma_t \epsilon_t}_{\text {random noise }} \\\frac{x_{t-1}}{\sqrt {\bar\alpha_{t-1}}}&= \frac {x_t}{\sqrt {\bar\alpha_t}} - \frac{\sqrt{1-\bar\alpha_t}}{\sqrt {\bar\alpha_t}}\epsilon_\theta^{(t)} + \frac{\sqrt {1-\bar\alpha_{t-1}}}{\sqrt {\bar\alpha_{t-1}}}\epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)\\ &\text {當 t 足夠大時可以看做}\\\frac{\boldsymbol{x}_{t-\Delta t}}{\sqrt{\bar\alpha_{t-\Delta t}}} &=\frac {x_t}{\sqrt {\bar\alpha_t}} + \left(\sqrt{\frac{1-\bar\alpha_{t-\Delta t}}{\bar\alpha_{t-\Delta t}}}-\sqrt{\frac{1-\bar\alpha_t}{\bar\alpha_t}}\right) \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right) \end{aligned}
而後進行換元,令 σ = ( 1 − α ˉ / α ˉ ) , x ˉ = x / α ˉ \sigma=(\sqrt{1-\bar\alpha}/\sqrt{\bar\alpha}), \bar x = x/\sqrt{\bar\alpha} ,帶入得到:
d x ‾ ( t ) = ϵ θ ( t ) ( x ‾ ( t ) σ 2 + 1 ) d σ ( t ) (11) \mathrm{d} \overline{\boldsymbol{x}}(t)=\epsilon_\theta^{(t)}\left(\frac{\overline{\boldsymbol{x}}(t)}{\sqrt{\sigma^2+1}}\right) \mathrm{d} \sigma(t)\tag{11}
於是,基於這個 ODE 結果,能透過 x ˉ ( t ) + d x ˉ ( t ) \bar x({t}) + d\bar x(t) 計算得到 x ˉ ( t + 1 ) \bar x(t+1) 與 x t + 1 x_{t+1}
根據 github - openai/improved-diffusionopen in new window ,其實現根據 ODE 反向取樣的方式為:直接根據公式 ( 5 ) (5) 進行變換,把 t − 1 t-1 換成 t + 1 t+1 :
x t + 1 = α ˉ t + 1 ( x t − 1 − α ˉ t ϵ θ ( t ) ( x t ) α ˉ t ) ⏟ " predicted x 0 " + 1 − α ˉ t + 1 ⋅ ϵ θ ( t ) ( x t ) ⏟ "direction pointing to x t " + σ t ϵ t ⏟ random noise (12) \boldsymbol{x}_{t+1}=\sqrt{\bar\alpha_{t+1}} \underbrace{\left(\frac{\boldsymbol{x}_t-\sqrt{1-\bar\alpha_t} \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}{\sqrt{\bar\alpha_t}}\right)}_{\text {" predicted } \boldsymbol{x}_0 \text { " }}+\underbrace{\sqrt{1-\bar\alpha_{t+1}} \cdot \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)}_{\text {"direction pointing to } \boldsymbol{x}_t \text { " }}+\underbrace{\sigma_t \epsilon_t}_{\text {random noise }}\tag{12}
而參考公式 ( 11 ) (11) 的推導過程,( 12 ) (12) 可以看成下面這種形式:
x t + Δ t α ˉ t + Δ t = x t α ˉ t + ( 1 − α ˉ t + Δ t α ˉ t + Δ t − 1 − α ˉ t α ˉ t ) ϵ θ ( t ) ( x t ) (13) \frac{\boldsymbol{x}_{t+\Delta t}}{\sqrt{\bar\alpha_{t+\Delta t}}} =\frac {x_t}{\sqrt {\bar\alpha_t}} + \left(\sqrt{\frac{1-\bar\alpha_{t+\Delta t}}{\bar\alpha_{t+\Delta t}}}-\sqrt{\frac{1-\bar\alpha_t}{\bar\alpha_t}}\right) \epsilon_\theta^{(t)}\left(\boldsymbol{x}_t\right)\tag {13}
以下我們嘗試對自定義的輸入圖片進行反向取樣(reverse sampling)和原圖恢復,我們匯入本地圖片:
img 根據公式 12 編寫反向取樣過程。ppdiffusers 中不存在 reverse_sample
方案,因此我們根據本文中的公式 ( 12 ) (12) 來實現一下 reverse_sample
過程,具體為:
def reverse_sample (self, model_output, x, t, prev_timestep):
"""
Sample x_{t+1} from the model and x_t using DDIM reverse ODE.
"""
alpha_bar_t_next = self .alphas_cumprod[t]
alpha_bar_t = self .alphas_cumprod[prev_timestep] if prev_timestep >= 0 else self .final_alpha_cumprod
inter = (
(( 1 - alpha_bar_t_next) / alpha_bar_t_next) ** ( 0.5 ) - \
(( 1 - alpha_bar_t) / alpha_bar_t) ** ( 0.5 )
)
x_t_next = alpha_bar_t_next ** ( 0.5 ) * (x / (alpha_bar_t ** ( 0.5 )) + \
(
model_output * inter
)
)
return x_t_next
而後進行不斷的迭代取樣與圖片重建(具體的方式可以檢視 擴散模型探索:DDIM 筆記與思考open in new window )。以下右圖為根據原圖進行反向 ODE 加噪後的結果,可以看出加噪後和電視沒訊號畫面相當。以下左圖為根據噪聲圖片取樣得來的結果,基本上取樣的結果還原了 90%以上原圖的細節,不過還有如右上角部分的一些顏色沒有被還原。
img 潛在的風格融合方式 透過兩個能夠生成不同圖片的噪聲 z 1 , z 2 z_1, z_2 ,進行 spherical linear interpolation 球面線性插值。而後作為 x T x_T 生成具有兩張畫面共同特點的圖片。有點類似風格融合的效果。參考 linkopen in new window 。首先我們選取兩個不同的圖片進行融合:
paddle.seed( 77 )
pipe.scheduler.config.clip_sample = False
z_0 = paddle.randn(( 1 , 3 , 256 , 256 ))
sample1 = pipe( num_inference_steps = 50 , eta = 0 , x_t = z_0)
paddle.seed( 2707 )
z_1 = paddle.randn(( 1 , 3 , 256 , 256 ))
sample2 = pipe( num_inference_steps = 50 , eta = 0 , x_t = z_1)
compare_imgs([sample1.images[ 0 ], sample2.images[ 0 ]], [ "sample from z_0" , "sample from z_1" ])
輸出結果:
img 以上選擇 seed 為 77 和 2707 的噪聲進行取樣,他們的取樣結果分別展示在上方。
以下參考 ermongroup/ddim/blob/main/runners/diffusion.pyopen in new window ,對噪聲進行插值,方式大致為:
x t = sin ( ( 1 − α ) θ ) sin ( θ ) z 0 + s i n ( α θ ) sin ( θ ) z 1 , w h e r e θ = arccos ( ∑ z 1 z 0 ∣ ∣ z 1 ∣ ⋅ ∣ ∣ z 0 ∣ ∣ ) x_t = \frac {\sin\left((1-\alpha)\theta\right)}{\sin(\theta)}z_0 + \frac{sin(\alpha\theta)}{\sin(\theta)}z_1,\\where\ \theta=\arccos\left(\frac{\sum z_1z_0}{||z_1|·||z_0||}\right)
def slerp (z1, z2, alpha):
theta = torch.acos(torch.sum(z1 * z2) / (torch.norm(z1) * torch.norm(z2)))
return (
torch.sin(( 1 - alpha) * theta) / torch.sin(theta) * z1
+ torch.sin(alpha * theta) / torch.sin(theta) * z2
)
img 可以看出,當 α \alpha 為 0.2, 0.8 時,我們能夠看到以下融合的效果,如頭髮顏色,無關特徵等。但在中間部分(α = 0.4 , 0.5 , 0.6 \alpha=0.4,0.5,0.6 ),取樣的圖片質量就沒有那麼高了。
那根據前兩節的闡述,我們可以實現一個小的 pipeline, 具備接受使用 DDIM 接受兩張圖片,而後輸出一張兩者風格融合之後的圖片。
參考 Denoising Diffusion Implicit Modelsopen in new window
蘇建林 - 生成擴散模型漫談 系列筆記open in new window
小小將 - 擴散模型之 DDIMopen in new window
github - openai/improved-diffusionopen in new window