上一篇影像論文講到了U-Net在資料收集的過程中就時常聽聞在鼎鼎大名的diffussion模型中很重要的一部分為U-Net因此這次繼續往下深入探討diffusion模型中的DDPMs。
DDPM是近期蠻流行的影像生成模型,來自加州大學柏克萊分校的團隊所發表,最終表現在無條件CIFAR10數據集上,獲得了9.46的Inception分數和3.17的最佳FID分數。在256x256的LSUN數據集上,也得到了與ProgressiveGAN相似的樣本品質。
🐌Forward process (擴散)
Forward process是diffussion模型中非常重要的一個部分,他的概念就是由一張圖片逐漸添加噪音,而這些雜訊為高斯分布(常態),最後變為高斯分布的噪音圖片。
為什麼diffussion模型要使用高斯分布去做擴散呢?高斯分布:又稱為常態分布(Normal Distribution),會使用的一大原因是因為常態分佈在數學上的簡潔性,像是常態分佈的平均值或是變異數的線性組合也會是常態分佈,另一個原因是因為常態噪音會是連續且平滑的,圖片可以平滑的過渡到常態分佈,不會突然跳躍。
那我們是怎麼去做添加噪音的呢?可以看下方這張圖。
🐌Reverse process (降噪)
降噪的過程就是將我們擴散完的高斯分布的噪音圖片,不斷的去去掉我們添加的雜訊,進而慢慢地讓圖片更加清晰,直到產生一章無雜訊之圖片。
在降噪的時候我們會透過Denoise的方式去做降噪,這邊具體怎麼做呢?
(1)輸入我們想要降噪的圖像+時間序(t)。(2)資料進入雜訊預測的模型(我們要訓練的模型)(U-Net)(3)輸出預測出來的雜訊(4)將想降噪的圖像減掉預測出來的圖像,則為上一時間序之圖像(t-1)
上方是論文中所提供的訓練以及採樣的演算法。我自己看這張圖也是霧颯颯,接下來我們來詳細的解釋吧~
🐌訓練演算法
每次的訓練中我們會重複以下的動作:
(1)隨機選擇一個time step並做encode(2)根據公式增加噪音(3)立用隨機的time step以及噪音圖片訓練U-Net
import numpy as np
#我們需要定義擴散過程中使用的常數和參數,例如時間步數 𝑇、擴散係數、𝛼及其平方根。
T = 1000 # 定義時間步數
alpha = np.linspace(0.0001, 0.02, T) # 定義擴散係數,線性地從0.0001到0.02
sqrt_alpha = np.sqrt(alpha) # 計算擴散係數的平方根
sqrt_one_minus_alpha = np.sqrt(1 - alpha) # 計算 (1 - α) 的平方根
# 訓練算法的目的是優化 𝜖𝜃,使其能夠有效地表示從高斯噪聲轉換回數據的過程。
def train(q_sample, T, alpha, sqrt_alpha, sqrt_one_minus_alpha):
epsilon_theta = np.random.randn() # 初始猜測
for _ in range(10000): # 迭代直到收斂
x0 = q_sample() # 從數據分佈 q(x0) 取樣
t = np.random.randint(1, T + 1) # 從 {1, ..., T} 中均勻取樣 t
epsilon = np.random.randn() # 從 N(0, I) 取樣 epsilon
# 計算梯度下降步驟
epsilon_theta -= 0.001 * (epsilon_theta * sqrt_alpha[t] + sqrt_one_minus_alpha[t] * epsilon - x0) ** 2
# 收斂檢查
if np.linalg.norm(epsilon_theta) < 1e-5:
break
return epsilon_theta
🐌採樣演算法
(1)從高斯分布中隨機選擇一個隨機值(初始樣本):X
(2)逐步從T到1移除噪音(e.g. T = 1000 # 定義時間步數)(3)在每個時間步T,如果 T 大於1,我們從標準高斯分佈中采樣一個隨機噪聲Z。(如果T等於1,則設Z為0。這是因為在最後一步不再需要添加額外的噪聲。)(4)使用去噪步驟更新x
def sample(epsilon_theta, T, alpha, sqrt_alpha, sqrt_one_minus_alpha):
# 從N(0, I)中採樣 xT
x = np.random.randn() # 逐步從T到1進行迴圈
for t in range(T, 0, -1):
# 如果 t > 1,則從N(0, I)中採樣z,否則z = 0
z = np.random.randn() if t > 1 else 0
# 使用去噪步驟更新x
x = (x - (1 - alpha[t]) / sqrt_alpha[t] * epsilon_theta) / sqrt_alpha[t] + sqrt_one_minus_alpha[t] * z
# 返回最終生成的x0
return x
論文:https://arxiv.org/pdf/2006.11239