Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90,819 changes: 90,819 additions & 0 deletions homework/1-AE/HW.ipynb

Large diffs are not rendered by default.

91 changes: 84 additions & 7 deletions homework/1-AE/autoencoder.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,92 @@
import torch
import torch.nn as nn
import torch.nn.functional as F

from itertools import chain
from block import Block


class AutoEncoder(nn.Module):
def __init__(self):
super().__init__()
# YOUR CODE

def forward(self, x):
# YOUR CODE
return x
self.encoder = nn.Sequential()
self.decoder = nn.Sequential()

def forward(self, x, l1_mode=False):
l1_loss = 0.
for module in chain(self.encoder.children(), self.decoder.children()):
out = module(x, l1_mode)
if l1_mode:
x = out[0]
l1_loss += out[1]
else:
x = out
x = torch.sigmoid(x)
return x, l1_loss

def get_latent_features(self, x):
return # YOUR CODE
return self.encoder(x)


class DummyAutoEncoder(AutoEncoder):
def __init__(self):
super().__init__()
self.encoder = nn.Sequential(Block(1, 16,
kernel_size=3, stride=2, padding=1),
Block(16, 32,
kernel_size=3, stride=2, padding=1),
Block(32, 32,
kernel_size=3, stride=2, padding=1),
Block(32, 32,
kernel_size=3, stride=2, padding=1,
only_conv=True))
self.decoder = nn.Sequential(Block(32, 32,
kernel_size=3, stride=1, padding=1,
upsample=True),
Block(32, 32,
kernel_size=3, stride=1, padding=1,
upsample=True),
Block(32, 16,
kernel_size=3, stride=1, padding=1,
upsample=True),
Block(16, 16,
kernel_size=3, stride=1, padding=1,
upsample=True),
Block(16, 16,
kernel_size=3, stride=1, padding=1,
upsample=True),
Block(16, 1, only_conv=True))



class DenoisingAutoEncoder(AutoEncoder):
def __init__(self):
super().__init__()
self.encoder = nn.Sequential(Block(1, 16,
kernel_size=3, stride=2, padding=1,
denoise=True),
Block(16, 32,
kernel_size=3, stride=2, padding=1,
denoise=True),
Block(32, 32,
kernel_size=3, stride=2, padding=1,
denoise=True),
Block(32, 32,
kernel_size=3, stride=2, padding=1,
only_conv=True))
self.decoder = nn.Sequential(Block(32, 32,
kernel_size=3, stride=1, padding=1,
upsample=True, denoise=True),
Block(32, 32,
kernel_size=3, stride=1, padding=1,
upsample=True, denoise=True),
Block(32, 16,
kernel_size=3, stride=1, padding=1,
upsample=True, denoise=True),
Block(16, 16,
kernel_size=3, stride=1, padding=1,
upsample=True, denoise=True),
Block(16, 16,
kernel_size=3, stride=1, padding=1,
upsample=True, denoise=True),
Block(16, 1, only_conv=True))

65 changes: 65 additions & 0 deletions homework/1-AE/block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.distributions import Normal


class UpSample(nn.Module):
def __init__(self):
super().__init__()

def forward(self, x):
return F.interpolate(x, scale_factor=2,
mode='bilinear',
align_corners=False,
recompute_scale_factor=False)


class DenoiseLayer(nn.Module):
def __init__(self, sigma=0.05, p=0.3):
super().__init__()
self.noise = Normal(loc=0.0, scale=sigma)
self.dropout = nn.Dropout(p)

def forward(self, x):
noise_part = self.noise.sample(x.shape)
if x.is_cuda:
noise_part = noise_part.to('cuda')
return self.dropout(x + noise_part)


class Block(nn.Module):
def __init__(self, in_features, out_features,
kernel_size=3, stride=2, padding=1,
upsample=False, only_conv=False, denoise=False):
super().__init__()
self.conv = nn.Conv2d(in_features,
out_features,
kernel_size=kernel_size, stride=stride,
padding=padding, bias=False)

if only_conv:
self.before_conv = nn.Sequential()
self.after_conv = nn.Sequential()
return

self.before_conv = []
self.after_conv = []
if upsample:
self.before_conv.append(UpSample())
if denoise:
self.before_conv.append(DenoiseLayer())
self.after_conv.extend([nn.BatchNorm2d(out_features),
nn.LeakyReLU(0.2)])
self.before_conv = nn.Sequential(*self.before_conv)
self.after_conv = nn.Sequential(*self.after_conv)



def forward(self, x, l1_mode=False):
x = self.before_conv(x)
x_conv = self.conv(x)
x = self.after_conv(x_conv)
if l1_mode:
return x, torch.abs(x_conv).sum(dim=1).mean()
return x
20 changes: 19 additions & 1 deletion homework/1-AE/calculate_fid.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,25 @@ def calculate_activation_statistics(dataloader, model, classifier):
# В целом все как в подсчете оригинального FID, но с вашей кастомной моделью классификации
# note: не забывайте на каком девайсе у вас тензоры
# note2: не забывайте делать .detach()
# YOUR CODE
acts_real = []
acts_decoded = []
# Все без detach, тк calculate_fid с torch.no_grad
for image, _ in dataloader:
image = image.to(device)
decoded, _ = model(image)
acts_real.append(classifier.get_activations(image).cpu().numpy())
acts_decoded.append(classifier.get_activations(decoded).cpu().numpy())
acts_real = np.concatenate(acts_real, axis=0)
acts_decoded = np.concatenate(acts_decoded, axis=0)
m1 = np.mean(acts_real, axis=0)
m2 = np.mean(acts_decoded, axis=0)
s1 = np.cov(acts_real, rowvar=False)
s2 = np.cov(acts_decoded, rowvar=False)

return m1, s1, m2, s2




@torch.no_grad()
def calculate_fid(dataloader, model, classifier):
Expand Down
43 changes: 38 additions & 5 deletions homework/1-AE/classifier.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
import torch
import torch.nn as nn
from block import Block


class Classifier(nn.Module):
def __init__(self, n_classes=10):
super().__init__()
# YOUR CODE
super().__init__()
self.cnns = nn.Sequential(
# 1 x 64 x 64
Block(1, 16,
kernel_size=3, stride=2, padding=1),
# 16 x 32 x 32
Block(16, 16,
kernel_size=3, stride=2, padding=1),
# 16 x 16 x 16
Block(16, 16,
kernel_size=3, stride=2, padding=1),
# 16 x 8 x 8
Block(16, 32,
kernel_size=3, stride=2, padding=1))
# 32 x 4 x 4
self.linears = nn.Sequential(nn.Linear(512, 256),
nn.LeakyReLU(0.2),
nn.Linear(256, n_classes))


def forward(self, x):
# YOUR CODE
return x
for layer in self.cnns:
x = layer(x)
return self.linears(x.view(x.shape[0], -1))

def get_activations(self, x):
return # YOUR CODE
x = self.cnns(x)
x = self.linears[:-1](x.view(x.shape[0], -1))
return x


class MLP(nn.Module):
def __init__(self, in_features, n_classes):
super().__init__()
self.layers = nn.Sequential(nn.Linear(in_features, 256),
nn.LeakyReLU(0.2),
nn.Linear(256, 256),
nn.LeakyReLU(0.2),
nn.Linear(256, n_classes))
def forward(self, x):
return self.layers(x.view(x.shape[0], -1))
Loading