Skip to content

Commit 2ec08b3

Browse files
author
Arsenii Ashukha
authored
Add files via upload
1 parent 51e2530 commit 2ec08b3

File tree

4 files changed

+156
-0
lines changed

4 files changed

+156
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<h2 align="center">Qualification task DeepBayes 2018</h2>
2+
3+
The strong knowledge of math, programming, and the ability to do research have become the most important skills in machine learning.
4+
In this task, we address unsupervised learning, a very fundamental AI problem.
5+
More specifically, we suggest you to implement Fully Connected Autoencoder using PyTorch for dimensionality reduction, and optionally to do some research with this model.
6+
7+
We define Autoencoder as two parametric differentiable functions, namely the Encoder (E) and the Decoder(D). Parameters of these two functions are adjusted by minimization of the following loss function:
8+
<center>
9+
<div>
10+
<img src="pics/eq.png" align="middle" width="640">
11+
</div>
12+
</center>
13+
where the left part is L2 reconstruction loss, the right part is L1 regularizer, and λ is a scalar regularizer weight.
14+
15+
You are requested to implement the AutoEncoder class.
16+
Use [ ```task.py```]() as a template of the solution; all technical details are described there.
17+
Your solution has to be implemented in _python 3.6_.
18+
Changing prototypes of the functions and using additional libraries (except included) is prohibited, otherwise, the solution will be automatically rejected.
19+
Please copy to the form only the implementation of the AutoEncoder class.
20+
21+
In the optional research assignment, we ask you to study:
22+
23+
- Which recontraction loss and regularizer lead to more natural images?
24+
- How different parameters of your architecture influence the solution? For example, consider a different number of layers and a number of neurons. Is it beneficial to use noisy layers like Dropout?
25+
26+
We suggest you to check the solution via ```test_work``` function.
27+
Please, note that ```test_work``` checks only interfaces, but does not check whether the solution is correct.

deepbayes-school/2018/pics/eq.png

136 KB
Loading

deepbayes-school/2018/task.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import torch
2+
import argparse
3+
import numpy as np
4+
import torch.utils.data
5+
6+
from torch import nn, optim
7+
from torch.autograd import Variable
8+
from torchvision import datasets, transforms
9+
from torchvision.utils import save_image
10+
11+
12+
class AutoEncoder(nn.Module):
13+
def __init__(self, inp_size, hid_size):
14+
super(AutoEncoder, self).__init__()
15+
"""
16+
Here you should define layers of your autoencoder
17+
Please note, if a layer has trainable parameters, it should be nn.Linear.
18+
## !! CONVOLUTIONAL LAYERS MUST NOT BE HERE !! ##
19+
However, you can use any noise inducing layers, e.g. Dropout.
20+
21+
Your network must not have more than six layers with trainable parameters.
22+
:param inp_size: integer, dimension of the input object
23+
:param hid_size: integer, dimension of the hidden representation
24+
"""
25+
pass
26+
27+
def encode(self, x):
28+
"""
29+
Encodes objects to hidden representations (E: R^inp_size -> R^hid_size)
30+
31+
:param x: inputs, Variable of shape (batch_size, inp_size)
32+
:return: hidden represenation of the objects, Variable of shape (batch_size, hid_size)
33+
"""
34+
pass
35+
36+
def decode(self, h):
37+
"""
38+
Decodes objects from hidden representations (D: R^hid_size -> R^inp_size)
39+
40+
:param h: hidden represenatations, Variable of shape (batch_size, hid_size)
41+
:return: reconstructed objects, Variable of shape (batch_size, inp_size)
42+
"""
43+
pass
44+
45+
def forward(self, x):
46+
"""
47+
Encodes inputs to hidden representations and decodes back.
48+
49+
x: inputs, Variable of shape (batch_size, inp_size)
50+
return: reconstructed objects, Variable of shape (batch_size, inp_size)
51+
"""
52+
return self.decode(self.encode(x))
53+
54+
@staticmethod
55+
def loss_function(recon_x, x):
56+
"""
57+
Calculates the loss function.
58+
59+
:params recon_x: reconstructed object, Variable of shape (batch_size, inp_size)
60+
:params x: original object, Variable of shape (batch_size, inp_size)
61+
:return: loss
62+
"""
63+
pass
64+
65+
66+
def train(model, optimizer, train_loader, test_loader):
67+
for epoch in range(10):
68+
model.train()
69+
train_loss, test_loss = 0, 0
70+
for data, _ in train_loader:
71+
data = Variable(data).view(-1, 784)
72+
x_rec = model(data)
73+
loss = model.loss_function(x_rec, data)
74+
75+
optimizer.zero_grad()
76+
loss.backward()
77+
optimizer.step()
78+
train_loss += loss.data[0]
79+
print('=> Epoch: %s Average loss: %.3f' % (epoch, train_loss / len(train_loader.dataset)))
80+
81+
model.eval()
82+
for data, _ in test_loader:
83+
data = Variable(data, volatile=True).view(-1, 784)
84+
x_rec = model(data)
85+
test_loss += model.loss_function(x_rec, data).data[0]
86+
87+
test_loss /= len(test_loader.dataset)
88+
print('=> Test set loss: %.3f' % test_loss)
89+
90+
n = min(data.size(0), 8)
91+
comparison = torch.cat([data.view(-1, 1, 28, 28)[:n], x_rec.view(-1, 1, 28, 28)[:n]])
92+
save_image(comparison.data.cpu(), 'pics/reconstruction_' + str(epoch) + '.png', nrow=n)
93+
return model
94+
95+
96+
def test_work():
97+
print('Start test')
98+
get_loader = lambda train: torch.utils.data.DataLoader(
99+
datasets.MNIST('../data', train=train, download=True, transform=transforms.ToTensor()),
100+
batch_size=50, shuffle=True)
101+
train_loader, test_loader = get_loader(True), get_loader(False)
102+
103+
try:
104+
model = AutoEncoder(inp_size=784, hid_size=20)
105+
optimizer = optim.Adam(model.parameters(), lr=1e-3)
106+
except Exception:
107+
assert False, 'Error during model creation'
108+
return
109+
110+
try:
111+
model = train(model, optimizer, train_loader, test_loader)
112+
except Exception:
113+
assert False, 'Error during training'
114+
return
115+
116+
test_x = Variable(torch.randn(1, 784))
117+
rec_x, hid_x = model(test_x), model.encode(test_x)
118+
submodules = dict(model.named_children())
119+
layers_with_params = np.unique(['.'.join(n.split('.')[:-1]) for n, _ in model.named_parameters()])
120+
121+
assert (hid_x.dim() == 2) and (hid_x.size(1) == 20), 'Hidden representation size must be equal to 20'
122+
assert (rec_x.dim() == 2) and (rec_x.size(1) == 784), 'Reconstruction size must be equal to 784'
123+
assert len(layers_with_params) <= 6, 'The model must contain not more than 6 layers'
124+
assert np.all(np.concatenate([list(p.shape) for p in model.parameters()]) <= 800), 'All hidden sizes must be less than 800'
125+
assert np.all([isinstance(submodules[name], nn.Linear) for name in layers_with_params]), 'All layers with parameters must be nn.Linear'
126+
print('Success!🎉')
127+
128+
129+
test_work()
68.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)