Неделя 10: Генеративные модели (GAN и VAE)
1. Теоретическая часть
1.1. Генеративные состязательные сети (GAN)
GAN состоят из двух нейросетей:
Генератор (G): Создает фейковые данные из шума
Дискриминатор (D): Отличает реальные данные от фейковых
Функция потерь
min𝐺max𝐷𝑉(𝐷,𝐺)=𝐸𝑥∼𝑝𝑑𝑎𝑡𝑎[log𝐷(𝑥)]+𝐸𝑧∼𝑝𝑧[log(1−𝐷(𝐺(𝑧)))]GminDmaxV(D,G)=Ex∼pdata[logD(x)]+Ez∼pz[log(1−D(G(z)))]
Архитектуры GAN
DCGAN: Сверточные GAN для изображений
CycleGAN: Преобразование между доменами
StyleGAN: Контроль стиля генерации
1.2. Вариационные автоэнкодеры (VAE)
VAE — генеративная модель с явным вероятностным представлением:
Энкодер: Сжимает данные в скрытое пространство (latent space)
Декодер: Восстанавливает данные из latent space
Функция потерь
𝐿=𝐸𝑞(𝑧∣𝑥)[log𝑝(𝑥∣𝑧)]−𝐷𝐾𝐿(𝑞(𝑧∣𝑥)∥𝑝(𝑧))L=Eq(z∣x)[logp(x∣z)]−DKL(q(z∣x)∥p(z))
2.1. Реализация DCGAN на PyTorch
python
Copy
# Генератор
class Generator(nn.Module):
def __init__(self, latent_dim, img_channels=1):
super(Generator, self).__init__()
self.main = nn.Sequential(
nn.ConvTranspose2d(latent_dim, 512, 4, 1, 0, bias=False),
nn.BatchNorm2d(512),
nn.ReLU(True),
nn.ConvTranspose2d(512, 256, 4, 2, 1, bias=False),
nn.BatchNorm2d(256),
nn.ReLU(True),
nn.ConvTranspose2d(256, 128, 4, 2, 1, bias=False),
nn.BatchNorm2d(128),
nn.ReLU(True),
nn.ConvTranspose2d(128, img_channels, 4, 2, 1, bias=False),
nn.Tanh()
)
def forward(self, z):
return self.main(z)
# Дискриминатор
class Discriminator(nn.Module):
def __init__(self, img_channels=1):
super(Discriminator, self).__init__()
self.main = nn.Sequential(
nn.Conv2d(img_channels, 128, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(128, 256, 4, 2, 1, bias=False),
nn.BatchNorm2d(256),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(256, 512, 4, 2, 1, bias=False),
nn.BatchNorm2d(512),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(512, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
)
def forward(self, img):
return self.main(img).view(-1)
2.2. Обучение GAN на MNIST
python
Copy
# Инициализация
G = Generator(latent_dim=100).to(device)
D = Discriminator().to(device)
optimizer_G = torch.optim.Adam(G.parameters(), lr=0.0002)
optimizer_D = torch.optim.Adam(D.parameters(), lr=0.0002)
criterion = nn.BCELoss()
# Цикл обучения
for epoch in range(epochs):
for i, (real_imgs, _) in enumerate(dataloader):
# Обучение дискриминатора
z = torch.randn(real_imgs.size(0), 100, 1, 1).to(device)
fake_imgs = G(z)
real_loss = criterion(D(real_imgs), torch.ones(real_imgs.size(0), 1).to(device))
fake_loss = criterion(D(fake_imgs.detach()), torch.zeros(real_imgs.size(0), 1).to(device))
d_loss = (real_loss + fake_loss) / 2
optimizer_D.zero_grad()
d_loss.backward()
optimizer_D.step()
# Обучение генератора
g_loss = criterion(D(fake_imgs), torch.ones(real_imgs.size(0), 1).to(device))
optimizer_G.zero_grad()
g_loss.backward()
optimizer_G.step()
2.3. Реализация VAE
python
Copy
class VAE(nn.Module):
def __init__(self, latent_dim):
super(VAE, self).__init__()
self.encoder = nn.Sequential(
nn.Linear(784, 512),
nn.ReLU(),
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 2*latent_dim)
)
self.decoder = nn.Sequential(
nn.Linear(latent_dim, 256),
nn.ReLU(),
nn.Linear(256, 512),
nn.ReLU(),
nn.Linear(512, 784),
nn.Sigmoid()
)
def reparameterize(self, mu, logvar):
std = torch.exp(0.5*logvar)
eps = torch.randn_like(std)
return mu + eps*std
def forward(self, x):
x = x.view(-1, 784)
h = self.encoder(x)
mu, logvar = h.chunk(2, dim=1)
z = self.reparameterize(mu, logvar)
return self.decoder(z), mu, logvar
3. Домашнее задание
Задача 1: Генерация изображений GAN
1. Обучите DCGAN на датасете FashionMNIST.
2. Визуализируйте процесс генерации по эпохам.
Решение:
python
Copy
# Загрузка данных
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.5], [0.5])
])
dataset = datasets.FashionMNIST('./data', train=True, download=True, transform=transform)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=128, shuffle=True)
# Визуализация
with torch.no_grad():
z = torch.randn(64, 100, 1, 1).to(device)
generated = G(z).cpu()
grid = torchvision.utils.make_grid(generated, nrow=8, normalize=True)
plt.imshow(grid.permute(1, 2, 0))
plt.show()
Задача 2: Интерполяция в latent space VAE
1. Обучите VAE на MNIST.
2. Реализуйте интерполяцию между цифрами в latent space.
Решение:
python
Copy
def interpolate(model, z1, z2, n_steps=10):
alphas = torch.linspace(0, 1, n_steps)
interpolations = []
for alpha in alphas:
z = alpha*z1 + (1-alpha)*z2
with torch.no_grad():
img = model.decoder(z).view(28, 28)
interpolations.append(img)
return torch.stack(interpolations)
# Пример использования
z1 = torch.randn(1, latent_dim) # Вектор для цифры 1
z2 = torch.randn(1, latent_dim) # Вектор для цифры 7
interps = interpolate(model, z1, z2)
Задача 3: Conditional GAN
1. Реализуйте cGAN с условием на класс (например, генерируйте конкретные цифры).
2. Добавьте в генератор и дискриминатор embedding классов.
Решение:
python
Copy
class ConditionalGenerator(nn.Module):
def __init__(self, latent_dim, num_classes):
super().__init__()
self.label_emb = nn.Embedding(num_classes, latent_dim)
self.main = nn.Sequential(
# ... аналогично DCGAN, но с конкатенацией label
)
def forward(self, z, labels):
label_emb = self.label_emb(labels).unsqueeze(2).unsqueeze(3)
z = torch.cat([z, label_emb], dim=1)
return self.main(z)
Итоги недели
✅ Изучили архитектуры GAN и VAE.
✅ Реализовали DCGAN для генерации изображений.
✅ Построили VAE с интерполяцией в latent space.
✅ Познакомились с условной генерацией (cGAN).
Следующая тема: Обучение с подкреплением (Reinforcement Learning). 🎮