一、normalizingflow的概念
當我們討論概率分布時,通常默認該分布能夠被歸一化。“正則分布”和“標準高斯分布”是兩個經典的例子。但是對於很多概率分布,如“beta分布”,它們並不能被簡單地歸一化。此時,我們可以考慮採用normalizingflow。normalizingflow是一個可逆映射,它能夠將一個簡單的概率分布轉換為我們感興趣的概率分布,如高斯混合模型。這種方法不僅適用於生成模型,也適用於deepinference。
二、normalizingflow的基本原理
給定一個簡單的概率分布$z$,普通的深度學習生成模型試圖學習一個非線性函數$f$,把輸入$s$轉化為目標概率分布$x$。類似的,normalizingflow也定義了一個可逆函數$f$,將隨機向量$z$轉化為$x$,其中$z$是先驗分布,$x$是要生成的分布。與其他深度生成模型類似,normalizingflow同樣使用反向傳播來學習$f$的參數。但與其他模型不同的是,我們需要設計一個可逆的函數$f$,這樣我們就可以應對概率密度不能直接計算的情況。
一種簡單的normalizingflow被稱為可逆自回歸流(invertibleautoregressiveflow,IAF),它針對神經網絡進行了改進,使得變換是可逆的。在IAF中,$f$由多個單層的可逆自回歸函數組合而成。在每一層中,我們定義一個可逆變換$\phi$,將輸入$z$映射為$\mu$和$\sigma$。然後,我們將$\sigma$作為原始向量的元素來乘,然後加上$\mu$。這種逐層自回歸的結構可以應對概率密度不能直接計算的情況。
三、normalizingflow在生成模型中應用
normalizingflow作為一種流模型,可以被看作是一種更一般的生成模型。它非常適合生成從複雜分布中採樣的高質量樣本。通常,我們可以將生成模型的目標視為計算高維積分或求解高維函數的最大值。然而,這些問題在高維空間中是非常困難的。normalizingflow允許我們將這些問題轉化為低維空間中的簡單積分問題和函數優化問題,因此它是一個非常強大的生成模型類型。
常見的高維數據類型為圖像,因此使用normalizingflow來生成圖像是自然的選擇。我們可以訓練一個生成模型來生成高質量的圖像,例如使用celebA,cifar,imagenet等數據集。具體來說,我們可以從一個簡單的分布(如高斯分布)中採樣,然後通過normalizingflow轉換為目標分布(如人臉圖像)。然後,我們可以使用生成模型從目標分布中進行採樣。通過這種方式,我們可以生成高質量的人臉以及其他圖像類型,從而為許多應用場景(如圖像生成、數據增強和降噪)提供了新的解決方法。
四、normalizingflow在deepinference中應用
除了生成模型之外,normalizingflow還可用於深度推斷。深度推斷主要關注的是推理複雜概率分布的參數。這對於數值計算、分類、聚類和時間序列分析等應用非常重要。normalizingflow可以將通常難以處理的後驗分布轉換為其他分布。這種轉換可以通過maximumlikelihoodtraining進行優化。
通常情況下,我們對變量的後驗分布關注不高,而更關注分布中的某些重要值,如期望值、求和或積分。在這種情況下,我們可以計算每個變量的預期值,然後用推理結果來代替實際值。這樣,我們就可以使用期望最大化(em)、變分推理和其他推理方法來計算概率值。
五、normalizingflow的優缺點
normalizingflow作為一種生成模型,具有以下優點:
1. normalizingflow實現簡單,沒有複雜的訓練過程,可以使用常規的反向傳播算法進行優化;
2. normalizingflow可以對數據進行變換,使其更加高斯化,這可以提高一些流模型的訓練效果;
3. normalizingflow可以在數據量較少的情況下生成高質量的訓練樣本。
當然,normalizingflow也存在一些缺點:
1. 由於其基本原理是嵌入低維空間,所以適用範圍有限,很難在無監督學習或其他學習任務中實現更好的表現;
2. normalizingflow的計算複雜度很高,計算慢,因此需要大量的計算資源。
六、代碼示例
import torchimport torch.nn.functional as Ffrom torch import nnclass NormalizingFlow(nn.Module): def __init__(self, dim, flow_length=16): super().__init__() self.transforms = nn.ModuleList() self.dims = [] for i in range(flow_length): transform = NormalizingFlowTransform(dim) self.transforms.append(transform) self.dims = tuple(self.dims) def forward(self, x): log_det = torch.zeros(len(x)) for transform in self.transforms: x, ld = transform(x) log_det += ld return x, log_detclass NormalizingFlowTransform(nn.Module): def __init__(self, dim): super().__init__() self.t1 = nn.Sequential( nn.Linear(dim, 2 * dim), nn.LeakyReLU(), nn.Linear(2 * dim, 2 * dim), ) self.t2 = nn.Sequential( nn.Linear(2 * dim, 2 * dim), nn.LeakyReLU(), nn.Linear(2 * dim, dim), ) self.t3 = nn.Sequential( nn.Linear(2 * dim, 2 * dim), nn.LeakyReLU(), nn.Linear(2 * dim, dim), ) self.t4 = nn.Sequential( nn.Linear(2 * dim, 2 * dim), nn.LeakyReLU(), nn.Linear(2 * dim, dim), ) def forward(self, x): px, log_det_x = self.t1(x).chunk(2, dim=-1) x = x + F.softplus(log_det_x) * px py, log_det_y = self.t2(x).chunk(2, dim=-1) y = x + F.softplus(log_det_y) * py pz, log_det_z = self.t3(y).chunk(2, dim=-1) z = y + F.softplus(log_det_z) * pz pw, log_det_w = self.t4(z).chunk(2, dim=-1) w = z + F.softplus(log_det_w) * pw log_det = log_det_x + log_det_y + log_det_z + log_det_w return w, log_det
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/205827.html