Files
cvpr/stylegan2/discriminator.py
T
2022-05-25 19:54:48 +02:00

163 lines
5.9 KiB
Python

import tensorflow as tf
from stylegan2.layers.dense import Dense
from stylegan2.layers.conv import Conv2D
from stylegan2.layers.bias_act import BiasAct
from stylegan2.layers.from_rgb import FromRGB
from stylegan2.layers.mini_batch_std import MinibatchStd
class DiscriminatorBlock(tf.keras.layers.Layer):
def __init__(self, n_f0, n_f1, res, **kwargs):
super(DiscriminatorBlock, self).__init__(**kwargs)
self.gain = 1.0
self.lrmul = 1.0
self.n_f0 = n_f0
self.n_f1 = n_f1
self.res = res
self.resnet_scale = 1. / tf.sqrt(2.)
# conv_0
self.conv_0 = Conv2D(in_res=res, in_fmaps=self.n_f0, fmaps=self.n_f0, kernel=3, up=False, down=False,
resample_kernel=None, gain=self.gain, lrmul=self.lrmul, name='conv_0')
self.apply_bias_act_0 = BiasAct(lrmul=self.lrmul, act='lrelu', name='bias_0')
# conv_1 down
self.conv_1 = Conv2D(in_res=res, in_fmaps=self.n_f0, fmaps=self.n_f1, kernel=3, up=False, down=True,
resample_kernel=[1, 3, 3, 1], gain=self.gain, lrmul=self.lrmul, name='conv_1')
self.apply_bias_act_1 = BiasAct(lrmul=self.lrmul, act='lrelu', name='bias_1')
# resnet skip
self.conv_skip = Conv2D(in_res=res, in_fmaps=self.n_f0, fmaps=self.n_f1, kernel=1, up=False, down=True,
resample_kernel=[1, 3, 3, 1], gain=self.gain, lrmul=self.lrmul, name='skip')
def call(self, inputs, training=None, mask=None):
x = inputs
residual = x
# conv0
x = self.conv_0(x)
x = self.apply_bias_act_0(x)
# conv1 down
x = self.conv_1(x)
x = self.apply_bias_act_1(x)
# resnet skip
residual = self.conv_skip(residual)
x = (x + residual) * self.resnet_scale
return x
def get_config(self):
config = super(DiscriminatorBlock, self).get_config()
config.update({
'n_f0': self.n_f0,
'n_f1': self.n_f1,
'gain': self.gain,
'lrmul': self.lrmul,
'res': self.res,
'resnet_scale': self.resnet_scale,
})
return config
class DiscriminatorLastBlock(tf.keras.layers.Layer):
def __init__(self, n_f0, n_f1, res, **kwargs):
super(DiscriminatorLastBlock, self).__init__(**kwargs)
self.gain = 1.0
self.lrmul = 1.0
self.n_f0 = n_f0
self.n_f1 = n_f1
self.res = res
self.minibatch_std = MinibatchStd(group_size=4, num_new_features=1, name='minibatchstd')
# conv_0
self.conv_0 = Conv2D(in_res=res, in_fmaps=self.n_f0 + 1, fmaps=self.n_f0, kernel=3, up=False, down=False,
resample_kernel=None, gain=self.gain, lrmul=self.lrmul, name='conv_0')
self.apply_bias_act_0 = BiasAct(lrmul=self.lrmul, act='lrelu', name='bias_0')
# dense_1
self.dense_1 = Dense(self.n_f1, gain=self.gain, lrmul=self.lrmul, name='dense_1')
self.apply_bias_act_1 = BiasAct(lrmul=self.lrmul, act='lrelu', name='bias_1')
def call(self, x, training=None, mask=None):
x = self.minibatch_std(x)
# conv_0
x = self.conv_0(x)
x = self.apply_bias_act_0(x)
# dense_1
x = self.dense_1(x)
x = self.apply_bias_act_1(x)
return x
def get_config(self):
config = super(DiscriminatorLastBlock, self).get_config()
config.update({
'n_f0': self.n_f0,
'n_f1': self.n_f1,
'gain': self.gain,
'lrmul': self.lrmul,
'res': self.res,
})
return config
class Discriminator(tf.keras.Model):
def __init__(self, d_params, **kwargs):
super(Discriminator, self).__init__(**kwargs)
# discriminator's (resolutions and featuremaps) are reversed against generator's
self.labels_dim = d_params['labels_dim']
self.r_resolutions = d_params['resolutions'][::-1]
self.r_featuremaps = d_params['featuremaps'][::-1]
# stack discriminator blocks
res0, n_f0 = self.r_resolutions[0], self.r_featuremaps[0]
self.initial_fromrgb = FromRGB(fmaps=n_f0, res=res0, name='{:d}x{:d}/FromRGB'.format(res0, res0))
self.blocks = list()
for index, (res0, n_f0) in enumerate(zip(self.r_resolutions[:-1], self.r_featuremaps[:-1])):
n_f1 = self.r_featuremaps[index + 1]
self.blocks.append(DiscriminatorBlock(n_f0=n_f0, n_f1=n_f1, res=res0, name='{:d}x{:d}'.format(res0, res0)))
# set last discriminator block
res = self.r_resolutions[-1]
n_f0, n_f1 = self.r_featuremaps[-2], self.r_featuremaps[-1]
self.last_block = DiscriminatorLastBlock(n_f0, n_f1, res, name='{:d}x{:d}'.format(res, res))
# set last dense layer
self.last_dense = Dense(max(self.labels_dim, 1), gain=1.0, lrmul=1.0, name='last_dense')
self.last_bias = BiasAct(lrmul=1.0, act='linear', name='last_bias')
# conditional output
self.last_block_condition = DiscriminatorLastBlock(n_f0, n_f1, res, name='{:d}x{:d}'.format(res, res))
self.condition_dense = Dense(self.labels_dim, gain=1.0, lrmul=1.0, name='last_dense')
self.condition_bias = BiasAct(lrmul=1.0, act='linear', name='last_bias')
def call(self, inputs, training=None, mask=None):
images, _ = inputs
x = self.initial_fromrgb(images)
for block in self.blocks:
x = block(x)
features = x
# score output
x = self.last_block(features)
x = self.last_dense(x)
x = self.last_bias(x)
# condition output
cond = self.last_block_condition(features)
cond = self.condition_dense(cond)
cond = self.condition_bias(cond)
scores_out = x
return scores_out, cond
def compute_output_shape(self, input_shape):
return input_shape[0][0], max(self.labels_dim, 1)