-
Notifications
You must be signed in to change notification settings - Fork 2
/
perceptual_loss.py
62 lines (47 loc) · 1.96 KB
/
perceptual_loss.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#coding: utf-8
import chainer.functions as F
import chainer.links as L
from chainer import Chain
from chainer.backends import cuda
class PerceptualLoss(Chain):
def __init__(self, opt):
super().__init__()
with self.init_scope():
self.detecter = L.VGG16Layers().to_gpu(0)
self.layer_names = ['conv1_2', 'conv2_2', 'conv3_3', 'conv4_3', 'conv5_3']
if opt.perceptual_model == 'VGG19':
self.detecter = L.VGG19Layers().to_gpu(0)
self.layer_name = ['conv1_2', 'conv2_2', 'conv3_4', 'conv4_4', 'conv5_4']
self.weight = [32 ** -1,
16 ** -1,
8 ** -1,
4 ** -1,
1]
self.coef = opt.perceptual_coef
self.criterion = F.mean_absolute_error
if opt.perceptual_mode == 'MAE':
self.criterion = F.mean_absolute_error
if opt.perceptual_mode == 'MSE':
self.criterion = F.mean_squared_error
self.coef *= 0.5
def prepare(self, variable_img):
#out = F.resize_images(variable_img, (224, 224))
out = variable_img
out = (out + 1) / 2
out = out[:, ::-1, :, :]
out = F.transpose(out, (0, 2, 3, 1))
out *= 255
xp = cuda.get_array_module(variable_img.array)
out -= xp.array([103.939, 116.779, 123.68], dtype=variable_img.dtype)
out = F.transpose(out, (0, 3, 1, 2))
return out
def __call__(self, real, fake):
loss = 0
real = self.prepare(real)
fake = self.prepare(fake)
real_feat = self.detecter(real, layers=self.layer_names)
fake_feat = self.detecter(fake, layers=self.layer_names)
for i, name in enumerate(self.layer_names):
loss += self.weight[i] * self.criterion(real_feat[name].array, fake_feat[name]) / 255
loss *= self.coef
return loss