From: Francois Fleuret Date: Thu, 23 Aug 2018 22:10:57 +0000 (+0200) Subject: Update. X-Git-Url: https://www.fleuret.org/cgi-bin/gitweb/gitweb.cgi?p=pytorch.git;a=commitdiff_plain;h=e111e52ea09f03fc309052b00a452ced52668f70 Update. --- diff --git a/ae_size.py b/ae_size.py index 25ecc4a..8afb101 100755 --- a/ae_size.py +++ b/ae_size.py @@ -12,9 +12,9 @@ def minimal_input_size(w, layer_specs): return w else: kernel_size, stride = layer_specs[0] - w = math.ceil((w - kernel_size) / stride) + 1 - w = minimal_input_size(w, layer_specs[1:]) - return int((w - 1) * stride + kernel_size) + v = int(math.ceil((w - kernel_size) / stride)) + 1 + v = minimal_input_size(v, layer_specs[1:]) + return (v - 1) * stride + kernel_size ###################################################################### @@ -22,9 +22,10 @@ def minimal_input_size(w, layer_specs): if __name__ == "__main__": - layer_specs = [ (11, 5), (5, 4), (3, 2), (3, 2) ] + layer_specs = [ (17, 5), (5, 4), (3, 2), (3, 2) ] layers = [] + for kernel_size, stride in layer_specs: layers.append(nn.Conv2d(1, 1, kernel_size, stride)) diff --git a/blacklab.jpg b/blacklab.jpg new file mode 100644 index 0000000..fd85537 Binary files /dev/null and b/blacklab.jpg differ diff --git a/hallu-result.png b/hallu-result.png new file mode 100644 index 0000000..5911382 Binary files /dev/null and b/hallu-result.png differ diff --git a/hallu.py b/hallu.py new file mode 100755 index 0000000..6b0b303 --- /dev/null +++ b/hallu.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +# ImageMagick's montage to make the mosaic +# +# montage hallu-*.png -tile 5x6 -geometry +1+1 result.png + +import PIL, torch, torchvision +from torch.nn import functional as F + +class MultiScaleEdgeEnergy(torch.nn.Module): + def __init__(self): + super(MultiScaleEdgeEnergy, self).__init__() + k = torch.exp(- torch.tensor([[-2., -1., 0., 1., 2.]])**2 / 2) + k = (k.t() @ k).view(1, 1, 5, 5) + self.register_buffer('gaussian_5x5', k / k.sum()) + + def forward(self, x): + u = x.view(-1, 1, x.size(2), x.size(3)) + result = 0.0 + while min(u.size(2), u.size(3)) > 5: + blurry = F.conv2d(u, self.gaussian_5x5, padding = 2) + result += (u - blurry).view(u.size(0), -1).pow(2).sum(1) + u = F.avg_pool2d(u, kernel_size = 2, padding = 1) + return result.view(x.size(0), -1).sum(1) + +img = torchvision.transforms.ToTensor()(PIL.Image.open('blacklab.jpg')) +img = img.view((1,) + img.size()) +ref_input = 0.5 + 0.5 * (img - img.mean()) / img.std() + +mse_loss = torch.nn.MSELoss() +edge_energy = MultiScaleEdgeEnergy() + +layers = torchvision.models.vgg16(pretrained = True).features +layers.eval() + +if torch.cuda.is_available(): + edge_energy.cuda() + ref_input = ref_input.cuda() + layers.cuda() + +for l in [ 5, 7, 12, 17, 21, 28 ]: + model = torch.nn.Sequential(layers[:l]) + ref_output = model(ref_input).detach() + + for n in range(5): + input = ref_input.new_empty(ref_input.size()).uniform_(-0.01, 0.01).requires_grad_() + optimizer = torch.optim.Adam( [ input ], lr = 1e-2) + for k in range(1000): + output = model(input) + loss = mse_loss(output, ref_output) + 1e-3 * edge_energy(input) + optimizer.zero_grad() + loss.backward() + optimizer.step() + + img = 0.5 + 0.2 * (input - input.mean()) / input.std() + result_name = 'hallu-l%02d-n%02d.png' % (l, n) + torchvision.utils.save_image(img, result_name) + + print('Wrote ' + result_name)