日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

53_Auto-Encoders和Variational AutoEncoders(VAE)、PCA降维和Auto-Encoders降维的比较、Auto-Encoders变种、pytorch实现等

發布時間:2024/9/27 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 53_Auto-Encoders和Variational AutoEncoders(VAE)、PCA降维和Auto-Encoders降维的比较、Auto-Encoders变种、pytorch实现等 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.53.Auto-Encoders和Variational AutoEncoders(VAE)
1.53.1.無監督學習
1.53.2.Auto-Encoders
1.53.3.How to Train?
1.53.4.Auto-Encoders的訓練
1.53.5.PCA降維和Auto-Encoders降維的比較
1.53.6.Auto-Encoders變種
1.53.6.1.Denoising AutoEncoders,去噪 AutoEncoders
1.53.6.2.Dropout AutoEncoders
1.53.6.3.Adversarial AutoEncoders,對抗AutoEncoders
1.53.6.4.q分布和p分布
1.53.6.5.對 KL(p◎q)的直觀理解
1.53.6.6.Maximize Likelihood(極大似然)
1.53.6.7.Minimize KL Divergence (最小化KL散度)
1.53.6.8.在q(z)和p(z)之間怎么計算KL?
1.53.7.Variational AutoEncoders
1.53.8.AutoEncoder的PyTorch實現
1.53.9.Variational AutoEncoders
1.53.10.參考文章

1.53.Auto-Encoders和Variational AutoEncoders(VAE)

1.53.1.無監督學習

無監督學習常見的兩種類型是:數據集變換聚類

數據集變換,就是創建數據集新的表示算法,與數據的原始表示相比,新的表示可能更容易被人或其他機器學習算法所理解。

常見的應用有降維,就是對許多特征表示的高維數據,找到該數據的一種新方法,用較少的特征就可以概括其重要特征。另一個應用就是找到”構成”數據的各個組成部分,比如對文本文檔的關鍵字提取。

聚類,就是將數據劃分成不同的組,每組包含相似的物項。

1.53.2.Auto-Encoders

自編碼AutoEncoder是一種無監督學習的算法,他利用反向傳播算法,讓目標等于輸入值。什么意思呢,下面舉個例子:

有一個神經網絡,它在做的事情是,輸入一張圖片,通過一個Encoder神經網絡,輸出一個比較”濃縮的”feature map。之后將這個feature map通過一個Decoder網絡,結果又將這張圖片還原回去了。

你也可以這么理解,整個Encoder + Decoder是一個神經網絡,中間的code只是暫存的數據。

感覺就像是,現在有一鍋紅糖水,你不停的煮它,最終水都被煮干了,只剩下紅糖,這個紅糖就是上圖的”Code”。然后你再向紅糖里面注水、加熱,結果又還原回了一鍋紅糖水。

假設上線的神經網絡展開如下圖所示,可以看出,圖片經過了一個壓縮,再解壓的工序。當壓縮的時候,原有的圖片質量被縮減。解壓時,用信息量少卻包含所有關鍵信息的文件恢復出了原本的圖片。為什么要這樣做呢?

因為有時候神經網絡要接受大量的輸入信息,比如說輸入信息是高清圖片時,信息量可能高達上千萬,讓神經網絡直接從上千萬信息中學習是很吃力的。所以,為何不壓縮一下,提取原圖片中最具代表性的信息,縮減信息量,再把縮減后的信息帶入進行網絡學習。這樣學習起來就輕松多了。

在無監督學習中,Auto-Encoders的目標是重建自己,它是一個特殊的全連接層,輸入和輸出的維度是一樣的,這樣能保證自己能夠重建。中間有一個neck(脖子),這樣既可以升維也可以降維,這里降到兩維的好處是,二維的圖片是可視化的,不僅已經降維,而且在空間中還保證了語義的相關性(通過無監督的聚類可以發現)。

1.53.3.How to Train?



1.53.4.Auto-Encoders的訓練

?下面Loss Function,如果輸入是binary的,即01值,那么就用第一種。
?如果是實數作為輸入,Loss function就是第二種。


  ②MSE

1.53.5.PCA降維和Auto-Encoders降維的比較

PCA在高維數據中尋找方差最大的方向,只選擇方差最大的軸。然而,主成分分析(PCA)的線性性對可提取的特征維度的種類有很大的限制。

PCA V.S. AutoEncoder
同樣都是降維,PCA和AutoEncoder誰的效果更好呢?
首先從直覺上分析,PCA本質上是線性的變換,所以它是有局限性的。而AutoEncoder是基于DNN的,由于有activation function的存在,所以可以進行非線性變換,使用范圍更廣。

下圖展示了MNIST數據集分別經過PCA和AutoEncoder 降維再還原 后的效果。第二行是使用AutoEncoder的方法,可以看到幾乎沒什么太大變化;而第四行的圖片很多都變得非常模糊了,說明PCA的效果是不如AutoEncoder的。

Auto-Encoders比PCA降維的效果要好。

1.53.6.Auto-Encoders變種

1.53.6.1.Denoising AutoEncoders,去噪 AutoEncoders

如果只在像素級別的重建,便不能發現一些更加深層次的特征,網路可能會記住一些特征,為了防止這種情況出現,我們可以在原輸入圖片后加入隨機噪聲累加到原圖片上。

Vincent在2008的論文(http://www.iro.umontreal.ca/~lisa/publications2/index.php/publications/show/217)中提出了AutoEncoder的改良版----dA,論文標題叫”Extracting and Composing Robust Features”,譯成中文就是”提取、編碼出具有魯棒性的特征”

首先我們考慮,為什么會產生這樣的變種AutoEncoder。如果我們僅僅只是在像素級別對一張圖片進行Encode,然后再重建,這樣就無法發現更深層次的信息,很有可能會導致網絡記住了一些特征。為了防止這種情況產生,我們可以給輸入圖片加一些噪聲,比方說生成和圖片同樣大小的高斯分布的數據,然后和圖像的像素值相加(見下圖)。如果這樣都能重建原來的圖片,意味著這個網絡能從這些混亂的信息中發現真正有用的特征,此時的Code才能代表輸入圖片的"精華"。

關鍵是,這樣胡亂給原始圖片加噪聲真的科學嗎?Vincent從大腦認知角度給了解釋。Paper中說到:
人類具有認識被阻擋的破損圖像的能力,源于我們高等的聯想記憶感受機能。
就是說,我們能以多種形式去記憶(比如圖像、聲音),所以即便是數據破損丟失,我們也能回想起來。

1.53.6.2.Dropout AutoEncoders

其實這個沒什么特別的,平時我們不論是CNN還是RNN幾乎都會用到Dropout。據說Dropout是當時Hilton在給學生上課的時候提到的,用來幫助提升神經網路訓練效果的小Trick。具體關于Dropout的講解可以看我的這篇文章:https://wmathor.com/index.php/archives/1377/

在訓練的時候隨機對某些連接進行斷開(通過將該連接的w設置為0),那么將會迫使網絡盡可能地提升還存在的連接的表征能力,降低對多個神經元的依賴程度。綠色圖的x軸是訓練時loss的Dropout率,y是loss, 當為1時表示全部斷開,loss最大,然而當dropout率為0時,右邊藍色圖的y軸(test的acc)并不是最大,說明dropout率為0.2時在一定程度上可以緩解過擬合現象。

1.53.6.3.Adversarial AutoEncoders,對抗AutoEncoders

在AutoEncoder中可能存在這樣一個問題,圖片經過Encode之后的vector并不符合我們希望的分布(例如高斯分布),他的分布很有可能如下圖所示。這其實是令我們不太滿意的(雖然我并不知道Code滿足分布到底有重要,但是既然別人認為很重要那就重要吧),那么有什么解決辦法呢?

由University of Toronto、Google Brain和OpenAI合作的文章Adversarial Autoencoders(AAE)(https://arxiv.org/pdf/1511.05644.pdf)提出了一個使用Autoencoder進行對抗學習的idea,某種程度上對上述問題提供了一些新思路

AAE的核心其實就是利用GAN的思想,利用一個生成器G和一個判別器D進行對抗學習,以區分Real data和Fake data。具體思路是這樣的,我現在需要一個滿足p(z)概率分布的 向量,但是 實際上滿足q(z)分布。那么我就首先生成一個滿足p(z)分布的z’向量,打上Real data的標簽,然后將z向量打上Fake data(服從q(z)分布)。由于這里的p(z)可以是我們定義的任何一個概率分布,因此整個對抗學習的過程實際上是可以認為是通過調整Encoder不斷讓其產生的數據的概率分布q(z)接近我們預定的p(z).

在原始的AutoEncoders中,沒有呈現出原有數據的分布,有可能生成的數據是一樣的,Adversarial AutoEncoders額外的添加了一個Discriminator(鑒別器),我們希望生成的Z符合真實的Z‘的分布,將真實的和生成的都送到鑒別器計算差距,如果屬于希望的分布就輸出為1,否則輸出為0。

1.53.6.4.q分布和p分布



假設p和q都服從

1.53.6.5.對 KL(p◎q)的直觀理解:

1.53.6.6.Maximize Likelihood(極大似然)

1.53.6.7.Minimize KL Divergence (最小化KL散度)

?Evidence Lower BOund

1.53.6.8.在q(z)和p(z)之間怎么計算KL?

1.53.7.Variational AutoEncoders

前面的各種AutoEncoder都是將輸入數據轉換為vector,其中每個維度代表學習到的數據。而Variational AutoEncoders(VAE)提供了一種概率分布的描述形式,VAE中Encoder描述的是每個潛在屬性的概率分布,而不是直接輸出一個值。

舉例來說,假設我們已經在一個AutoEncoder上訓練了一個6維的vector,這個6維的vector將學習面部的一些屬性,例如膚色、是否戴眼鏡等。

在上面的示例中,我們使用單個值來描述輸入圖像的潛在屬性。但是,我們可能更喜歡將每個潛在屬性表示為一個范圍。VAE就可以實現這個功能,如下圖所示:

通過這種方法,我們現在將給定輸入的每個潛在屬性表示為概率分布。從狀態解碼(Decode)時,我們將從每個潛在狀態分布中隨機采樣以生成向量來作為解碼器的輸入:


Sample()不可微


再參數化技巧


Too Complex!

生成模型,通過學習得到每一個特征的分布情況。

1.53.8.AutoEncoder的PyTorch實現

其實AutoEncoder就是非常簡單的DNN。在encoder中神經元隨著層數的增加逐漸變少,也就是降維的過程。而在decoder中神經元隨著層數的增加逐漸變多,也就是升維的過程

# -*- coding: UTF-8 -*-import torch""" 安裝pytorch的可視化工具——visdom: 安裝并更新,不更新不能正常使用,會卡在download script。pip install visdom -i https://pypi.tuna.tsinghua.edu.cn/simple pip install --upgrade visdom """ import visdom from torch.utils.data import DataLoader from torchvision import transforms, datasets from torch import nn, optim""" 其實AutoEncoder就是非常簡單的DNN。在encoder中神經元隨著層數的增加逐漸變少,也就是降維的過程。而在decoder 中神經元隨著層數的增加逐漸變多,也就是升維的過程。 """ class AE(nn.Module):def __init__(self):super(AE, self).__init__()self.encoder = nn.Sequential(# [b, 784] => [b, 256]nn.Linear(784, 256),nn.ReLU(),# [b, 256] => [b, 64]nn.Linear(256, 64),nn.ReLU(),# [b, 64] => [b, 20]nn.Linear(64, 20),nn.ReLU())self.decoder = nn.Sequential(# [b, 20] => [b, 64]nn.Linear(20, 64),nn.ReLU(),# [b, 64] => [b, 256]nn.Linear(64, 256),nn.ReLU(),# [b, 256] => [b, 784]nn.Linear(256, 784),nn.Sigmoid())"""上面代碼都是基本操作,有一個地方需要特別注意,在decoder網絡中,最后跟的不是ReLU而是Sigmoid函數,因為我們想要將圖片打印出來看一下,而使用的數據集是MNIST,所以要將tensor里面的值最終都壓縮到0-1之間。"""def forward(self, x):""":param [b, 1, 28, 28]::return [b, 1, 28, 28]:"""batchsz = x.size(0)# flattenx = x.view(batchsz, -1)# encoderx = self.encoder(x)# decoderx = self.decoder(x)# reshapex = x.view(batchsz, 1, 28, 28)return xdef main():mnist_train = datasets.MNIST('mnist', train=True, transform=transforms.Compose([transforms.ToTensor()]), download=True)mnist_train = DataLoader(mnist_train, batch_size=32, shuffle=True)mnist_test = datasets.MNIST('mnist', train=False, transform=transforms.Compose([transforms.ToTensor()]), download=True)mnist_test = DataLoader(mnist_test, batch_size=32)epochs = 1000lr = 1e-3model = AE()# 由于input是0-1之間的實數,所以Loss functionMSEcriteon = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=lr)print(model)"""在通常(監督學習)情況下,我們需要將網絡的輸出output和訓練集的label進行對比,計算loss。但AutoEncoder是無監督學習,不需要label,我們只需要將網絡的輸出output和網絡的輸入input進行對比,計算loss即可"""viz = visdom.Visdom(use_incoming_socket=False)for epoch in range(epochs):# 不需要label,所以用一個占位符"_"代替for batchidx, (x, _) in enumerate(mnist_train):x_hat = model(x)loss = criteon(x_hat, x)# backpropoptimizer.zero_grad()loss.backward()optimizer.step()if epoch % 10 == 0:print(epoch, 'loss:', loss.item())x, _ = iter(mnist_test).next()with torch.no_grad():x_hat = model(x)viz.images(x, nrow=8, win='x', opts=dict(title='x'))viz.images(x_hat, nrow=8, win='x_hat', opts=dict(title='x_hat'))if __name__ == '__main__':main()

得到的效果如下圖所示,普通的AutoEncoder還是差了一點,可以看到很多圖片已經看不清具體代表的數字了。

1.53.9.Variational AutoEncoders



最主要關注一下定義網絡的部分:
Encode以后的變量h要分成兩半兒,利用h.chunk(num, dim)實現,num表示要分成幾塊,dim值表示在什么維度上進行。然后隨機采樣出標準正態分布的數據,用和對其進行變換。這里的kld指的是KL Divergence,它是Loss的一部分:

# -*- coding: UTF-8 -*-import torch import visdom import numpy as np from torch import nn, optim from torch.utils.data import DataLoader from torchvision import transforms, datasetsclass VAE(nn.Module):def __init__(self):super(VAE, self).__init__()# [b, 784] => [b, 20]# u: [b, 10]# sigma: [b, 10]self.encoder = nn.Sequential(# [b, 784] => [b, 256]nn.Linear(784, 256),nn.ReLU(),# [b, 256] => [b, 64]nn.Linear(256, 64),nn.ReLU(),# [b, 64] => [b, 20]nn.Linear(64, 20),nn.ReLU())self.decoder = nn.Sequential(# [b, 10] => [b, 64]nn.Linear(10, 64),nn.ReLU(),# [b, 64] => [b, 256]nn.Linear(64, 256),nn.ReLU(),# [b, 256] => [b, 784]nn.Linear(256, 784),nn.Sigmoid())'''Encode以后的變量h要分成兩半兒,利用h.chunk(num, dim)實現,num表示要分成幾塊,dim值表示在什么維度上進行。然后隨機采樣出標準正態分布的數據,用 和 對其進行變換。'''def forward(self, x):""":param [b, 1, 28, 28]::return [b, 1, 28, 28]:"""batchsz = x.size(0)# flattenx = x.view(batchsz, -1)# encoder# [b, 20] including mean and sigmaq = self.encoder(x)# [b, 20] => [b, 10] and [b, 10]mu, sigma = q.chunk(2, dim=1)# reparameterize trick, epsilon~N(0, 1)q = mu + sigma * torch.randn_like(sigma)# decoderx_hat = self.decoder(q)# reshapex_hat = x_hat.view(batchsz, 1, 28, 28)# KLkld = 0.5 * torch.sum(torch.pow(mu, 2) +torch.pow(sigma, 2) -torch.log(1e-8 + torch.pow(sigma, 2)) - 1) / (batchsz * 28 * 28)return x_hat, klddef main():mnist_train = datasets.MNIST('mnist', train=True, transform=transforms.Compose([transforms.ToTensor()]), download=True)mnist_train = DataLoader(mnist_train, batch_size=32, shuffle=True)mnist_test = datasets.MNIST('mnist', train=False, transform=transforms.Compose([transforms.ToTensor()]), download=True)mnist_test = DataLoader(mnist_test, batch_size=32)epochs = 1000lr = 1e-3model = VAE()criteon = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=lr)print(model)"""如果出現:Visdom python client failed to establish socket to get messages from the server. This feature is optional and can be disabled by initializing Visdom with `use_incoming_socket=False`, which will prevent waiting for this request to timeout.解決辦法:vis = visdom.Visdom(use_incoming_socket=False)"""viz = visdom.Visdom(use_incoming_socket=False)for epoch in range(epochs):# 不需要label,所以用一個占位符"_"代替for batchidx, (x, _) in enumerate(mnist_train):x_hat, kld = model(x)loss = criteon(x_hat, x)if kld is not None:elbo = loss + 1.0 * kldloss = elbo# backpropoptimizer.zero_grad()loss.backward()optimizer.step()if epoch % 10 == 0:print(epoch, 'loss:', loss.item(), 'kld', kld.item())x, _ = iter(mnist_test).next()with torch.no_grad():x_hat, kld = model(x)viz.images(x, nrow=8, win='x', opts=dict(title='x'))viz.images(x_hat, nrow=8, win='x_hat', opts=dict(title='x_hat'))if __name__ == '__main__':main()

輸出結果:

VAE((encoder): Sequential((0): Linear(in_features=784, out_features=256, bias=True)(1): ReLU()(2): Linear(in_features=256, out_features=64, bias=True)(3): ReLU()(4): Linear(in_features=64, out_features=20, bias=True)(5): ReLU())(decoder): Sequential((0): Linear(in_features=10, out_features=64, bias=True)(1): ReLU()(2): Linear(in_features=64, out_features=256, bias=True)(3): ReLU()(4): Linear(in_features=256, out_features=784, bias=True)(5): Sigmoid()) ) Setting up a new session... Without the incoming socket you cannot receive events from the server or register event handlers to your Visdom client. 0 loss: 0.05882733315229416 kld 0.005957949906587601 10 loss: 0.04458034038543701 kld 0.00900172907859087 20 loss: 0.046602990478277206 kld 0.008918660692870617 30 loss: 0.04872169345617294 kld 0.009532256051898003 40 loss: 0.04016539081931114 kld 0.009037637151777744 50 loss: 0.044585954397916794 kld 0.009513779543340206

1.53.10.參考文章

https://www.cnblogs.com/pengzhonglian/p/12159970.html
https://blog.csdn.net/h__ang/article/details/90720579
https://www.cnblogs.com/jeshy/p/11204300.html
https://blog.csdn.net/z_feng12489/article/details/88851163
https://blog.csdn.net/fengdu78/article/details/104337519
https://blog.csdn.net/sleepinghm/article/details/105142959
https://www.cnblogs.com/yongjieShi/p/8371549.html
https://www.freesion.com/article/959958354/
https://blog.csdn.net/u013517182/article/details/93046229
https://blog.csdn.net/qq_41882866/article/details/108200444

總結

以上是生活随笔為你收集整理的53_Auto-Encoders和Variational AutoEncoders(VAE)、PCA降维和Auto-Encoders降维的比较、Auto-Encoders变种、pytorch实现等的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。