Variational Autoencoder (VAE) ialah model generatif berdasarkan rangkaian saraf. Matlamatnya adalah untuk mempelajari perwakilan pembolehubah pendam dimensi rendah bagi data dimensi tinggi dan menggunakan pembolehubah pendam ini untuk pembinaan semula dan penjanaan data. Berbanding dengan pengekod auto tradisional, VAE boleh menjana sampel yang lebih realistik dan pelbagai dengan mempelajari pengedaran ruang terpendam. Kaedah pelaksanaan VAE akan diperkenalkan secara terperinci di bawah.
Idea asas VAE ialah untuk mencapai pengurangan dimensi dan pembinaan semula data dengan memetakan data berdimensi tinggi kepada ruang terpendam berdimensi rendah. Ia terdiri daripada dua bahagian: pengekod dan penyahkod. Pengekod memetakan data input x kepada min μ dan varians σ^2 ruang terpendam. Dengan cara ini, VAE boleh mengambil sampel data dalam ruang terpendam dan membina semula hasil sampel ke dalam data asal melalui penyahkod. Struktur penyahkod pengekod ini membolehkan VAE menjana sampel baharu dengan kesinambungan yang baik dalam ruang terpendam, menjadikan sampel serupa lebih dekat dalam ruang terpendam. Oleh itu, VAE bukan sahaja boleh digunakan untuk pengurangan dimensi dan
\begin{aligned} \mu &=f_{\mu}(x)\ \sigma^2 &=f_{\sigma}(x) \end{aligned}
di mana, f_{mu} dan f_{sigma} boleh menjadi mana-mana model rangkaian saraf. Biasanya, kami menggunakan Multilayer Perceptron (MLP) untuk melaksanakan pengekod.
Penyahkod memetakan pembolehubah terpendam z kembali ke ruang data asal, iaitu:
x'=g(z)
di mana, g juga boleh menjadi mana-mana model rangkaian saraf. Begitu juga, kami biasanya menggunakan MLP untuk melaksanakan penyahkod.
Dalam VAE, pembolehubah pendam $z$ diambil sampel daripada pengedaran terdahulu (biasanya pengedaran Gaussian), iaitu:
z\sim\mathcal{N}(0,I)
Dengan cara ini, kita boleh meminimumkan ralat pembinaan semula dan pembolehubah pendam KL divergence digunakan untuk melatih VAE untuk mencapai pengurangan dimensi dan penjanaan data. Secara khusus, fungsi kehilangan VAE boleh dinyatakan sebagai:
\mathcal{L}=\mathbb{E}_{z\sim q(z|x)}[\log p(x|z)]-\beta\mathrm{KL}[q(z|x)||p(z)]
di mana, q(z|x) ialah taburan posterior, iaitu taburan bersyarat bagi pembolehubah pendam z apabila input x diberi; z) ialah taburan penjanaan , iaitu, taburan data yang sepadan apabila pembolehubah pendam $z$ diberi p(z) ialah taburan terdahulu, iaitu taburan marginal pembolehubah terpendam z ialah hiperparameter yang digunakan untuk mengimbangi ralat pembinaan semula dan perbezaan KL.
Dengan meminimumkan fungsi kehilangan di atas, kita boleh mempelajari fungsi transformasi f(x), yang boleh memetakan data input x kepada taburan q(z|x) ruang pendam, dan boleh mencuba pembolehubah pendam daripada ia z, dengan itu mencapai pengurangan dimensi dan penjanaan data.
Di bawah kami akan memperkenalkan cara melaksanakan model asas VAE, termasuk definisi pengekod, penyahkod dan fungsi kehilangan. Kami mengambil set data digit tulisan tangan MNIST sebagai contoh Set data ini mengandungi 60,000 sampel latihan dan 10,000 sampel ujian, setiap sampel ialah imej skala kelabu 28x28. . Kodnya adalah seperti berikut:
# python import torch import torchvision.transforms as transforms from torchvision.datasets import MNIST # 定义数据预处理 transform = transforms.Compose([ transforms.ToTensor(), # 将图像转换成Tensor格式 transforms.Normalize(mean=(0.
Seterusnya, kita perlu mentakrifkan struktur model VAE, termasuk pengekod, penyahkod dan fungsi pensampelan pembolehubah pendam. Dalam contoh ini, kami menggunakan MLP dua lapisan sebagai pengekod dan penyahkod, dengan bilangan unit tersembunyi dalam setiap lapisan masing-masing ialah 256 dan 128. Dimensi pembolehubah pendam ialah 20. Kodnya adalah seperti berikut:
import torch.nn as nn class VAE(nn.Module): def __init__(self, input_dim=784, hidden_dim=256, latent_dim=20): super(VAE, self).__init__() # 定义编码器的结构 self.encoder = nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim//2), nn.ReLU(), nn.Linear(hidden_dim//2, latent_dim*2) # 输出均值和方差 ) # 定义解码器的结构 self.decoder = nn.Sequential( nn.Linear(latent_dim, hidden_dim//2), nn.ReLU(), nn.Linear(hidden_dim//2, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, input_dim), nn.Sigmoid() # 输出范围在[0, 1]之间的概率 ) # 潜在变量的采样函数 def sample_z(self, mu, logvar): std = torch.exp(0.5*logvar) eps = torch.randn_like(std) return mu + eps*std # 前向传播函数 def forward(self, x): # 编码器 h = self.encoder(x) mu, logvar = h[:, :latent_dim], h[:, latent_dim:] z = self.sample_z(mu, logvar) # 解码器 x_hat = self.decoder(z) return x_hat, mu, logvar
Dalam kod di atas, kami menggunakan MLP dua lapisan sebagai pengekod dan penyahkod. Pengekod memetakan data input kepada min dan varians ruang terpendam, di mana dimensi min ialah 20 dan dimensi varians juga 20, yang memastikan bahawa dimensi pembolehubah pendam ialah 20. Penyahkod memetakan pembolehubah terpendam kembali ke ruang data asal, di mana lapisan terakhir menggunakan fungsi Sigmoid untuk mengehadkan julat output kepada [0, 1].
Apabila melaksanakan model VAE, kita juga perlu menentukan fungsi kehilangan. Dalam contoh ini, kami menggunakan ralat pembinaan semula dan perbezaan KL untuk menentukan fungsi kehilangan, di mana ralat pembinaan semula menggunakan fungsi kehilangan entropi silang dan perbezaan KL menggunakan taburan normal piawai sebagai taburan terdahulu. Kodnya adalah seperti berikut:
# 定义损失函数 def vae_loss(x_hat, x, mu, logvar, beta=1): # 重构误差 recon_loss = nn.functional.binary_cross_entropy(x_hat, x, reduction='sum') # KL散度 kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp()) return recon_loss + beta*kl_loss
Dalam kod di atas, kami menggunakan fungsi kehilangan entropi silang untuk mengira ralat pembinaan semula dan perbezaan KL untuk mengira perbezaan antara taburan pembolehubah pendam dan taburan terdahulu. Antaranya, beta ialah hiperparameter yang digunakan untuk mengimbangi ralat pembinaan semula dan perbezaan KL.
2.3 Model latihan
Akhir sekali, kita perlu mentakrifkan fungsi latihan dan melatih model VAE pada set data MNIST. Semasa proses latihan, mula-mula kita perlu mengira fungsi kehilangan model, dan kemudian menggunakan algoritma perambatan belakang untuk mengemas kini parameter model. Kodnya adalah seperti berikut:
# python # 定义训练函数 def train(model, dataloader, optimizer, device, beta): model.train() train_loss = 0 for x, _ in dataloader: x = x.view(-1, input_dim).to(device) optimizer.zero_grad() x_hat, mu, logvar = model(x) loss = vae_loss(x_hat, x, mu, logvar, beta) loss.backward() train_loss += loss.item() optimizer.step() return train_loss / len(dataloader.dataset)
Kini, kita boleh menggunakan fungsi latihan di atas untuk melatih model VAE pada dataset MNIST. Kodnya adalah seperti berikut:
# 定义模型和优化器 model = VAE().to(device) optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) # 训练模型 num_epochs = 50 for epoch in range(num_epochs): train_loss = train(model, trainloader, optimizer, device, beta=1) print(f'Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}') # 测试模型 model.eval() with torch.no_grad(): test_loss = 0 for x, _ in testloader: x = x.view(-1, input_dim).to(device) x_hat, mu, logvar = model(x) test_loss += vae_loss(x_hat, x, mu, logvar, beta=1).item() test_loss /= len(testloader.dataset) print(f'Test Loss: {test_loss:.4f}')
2.4 Hasilkan sampel
最后,我们可以使用VAE模型生成新的手写数字样本。生成样本的过程非常简单,只需要在潜在空间中随机采样,然后将采样结果输入到解码器中生成新的样本。代码如下:
# 生成新样本 n_samples = 10 with torch.no_grad(): # 在潜在空间中随机采样 z = torch.randn(n_samples, latent_dim).to(device) # 解码生成样本 samples = model.decode(z).cpu() # 将样本重新变成图像的形状 samples = samples.view(n_samples, 1, 28, 28) # 可视化生成的样本 fig, axes = plt.subplots(1, n_samples, figsize=(20, 2)) for i, ax in enumerate(axes): ax.imshow(samples[i][0], cmap='gray') ax.axis('off') plt.show()
在上述代码中,我们在潜在空间中随机采样10个点,然后将这些点输入到解码器中生成新的样本。最后,我们将生成的样本可视化展示出来,可以看到,生成的样本与MNIST数据集中的数字非常相似。
综上,我们介绍了VAE模型的原理、实现和应用,可以看到,VAE模型是一种非常强大的生成模型,可以学习到高维数据的潜在表示,并用潜在表示生成新的样本。
Atas ialah kandungan terperinci Autoencoders Variasi: Teori dan Pelaksanaan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!