Пример #1
0
def generator_down_sample_hack(input_net, final_num_outputs=16):
    """
  Minic generator_down_sample() but doesn't actually do the downsampling
  """

    # if final_num_outputs % 4 != 0:
    #   raise ValueError('Final number outputs need to be divisible by 4.')

    # Check the rank of input_net.
    input_net.shape.assert_has_rank(4)

    # # Check dimension 1 and dimension 2 are defined and divisible by 4.
    # if input_net.shape[1]:
    #   if input_net.shape[1] % 4 != 0:
    #     raise ValueError(
    #         'Dimension 1 of the input should be divisible by 4, but is {} '
    #         'instead.'.format(input_net.shape[1]))
    # else:
    #   raise ValueError('Dimension 1 of the input should be explicitly defined.')
    #
    # # Check dimension 1 and dimension 2 are defined and divisible by 4.
    # if input_net.shape[2]:
    #   if input_net.shape[2] % 4 != 0:
    #     raise ValueError(
    #         'Dimension 2 of the input should be divisible by 4, but is {} '
    #         'instead.'.format(input_net.shape[2]))
    # else:
    #   raise ValueError('Dimension 2 of the input should be explicitly defined.')

    with tf.compat.v1.variable_scope('generator_down_sample'):
        down_sample = ops.pad(input_net, 3)
        down_sample = _conv2d(inputs=down_sample,
                              filters=final_num_outputs * 4,
                              kernel_size=7,
                              stride=1,
                              name='conv_0')
        down_sample = tfgan.features.instance_norm(down_sample)
        down_sample = tf.nn.relu(down_sample)

        down_sample = ops.pad(down_sample, 2)
        down_sample = _conv2d(inputs=down_sample,
                              filters=final_num_outputs * 2,
                              kernel_size=5,
                              stride=1,
                              name='conv_1')
        down_sample = tfgan.features.instance_norm(down_sample)
        down_sample = tf.nn.relu(down_sample)

        down_sample = ops.pad(down_sample, 2)
        down_sample = _conv2d(inputs=down_sample,
                              filters=final_num_outputs,
                              kernel_size=5,
                              stride=1,
                              name='conv_2')
        # down_sample = tfgan.features.instance_norm(down_sample)
        # down_sample = tf.nn.relu(down_sample)

    return down_sample
Пример #2
0
def _residual_block(input_net,
                    num_outputs,
                    kernel_size,
                    stride=1,
                    padding_size=0,
                    activation_fn=tf.nn.relu,
                    normalizer_fn=None,
                    name='residual_block'):
  """Residual Block.

  Input Tensor X - > Conv1 -> IN -> ReLU -> Conv2 -> IN + X

  PyTorch Version:
  https://github.com/yunjey/StarGAN/blob/fbdb6a6ce2a4a92e1dc034faec765e0dbe4b8164/model.py#L7

  Args:
    input_net: Tensor as input.
    num_outputs: (int) number of output channels for Convolution.
    kernel_size: (int) size of the square kernel for Convolution.
    stride: (int) stride for Convolution. Default to 1.
    padding_size: (int) padding size for Convolution. Default to 0.
    activation_fn: Activation function.
    normalizer_fn: Normalization function.
    name: Name scope

  Returns:
    Residual Tensor with the same shape as the input tensor.
  """
  with tf.variable_scope(name):

    res_block = ops.pad(input_net, padding_size)
    res_block = _conv2d(
        inputs=res_block,
        filters=num_outputs,
        kernel_size=kernel_size,
        stride=stride,
        name='conv_0')
    if normalizer_fn:
      res_block = normalizer_fn(res_block)
    res_block = activation_fn(res_block, name='activation_0')

    res_block = ops.pad(res_block, padding_size)
    res_block = _conv2d(
        inputs=res_block,
        filters=num_outputs,
        kernel_size=kernel_size,
        stride=stride,
        name='conv_1')
    if normalizer_fn:
      res_block = normalizer_fn(res_block)

    output_net = res_block + input_net

  return output_net
Пример #3
0
    def test_padding_with_tensor_of_invalid_shape(self):

        n = 2
        invalid_rank = 1
        h = 128
        w = 64
        c = 3
        pad = 3

        test_input_tensor = tf.random.uniform((n, invalid_rank, h, w, c))

        with self.assertRaises(ValueError):
            ops.pad(test_input_tensor, padding_size=pad)
Пример #4
0
def discriminator_output_source(input_net):
    """Output Layer for Source in the Discriminator.

  Determine if the image is real/fake based on the feature extracted. We follow
  the original paper design where the output is not a simple (batch_size) shape
  Tensor but rather a (batch_size, 2, 2, 2048) shape Tensor. We will get the
  correct shape later when we piece things together.

  PyTorch Version:
  https://github.com/yunjey/StarGAN/blob/fbdb6a6ce2a4a92e1dc034faec765e0dbe4b8164/model.py#L79

  Args:
    input_net: Tensor of shape (batch_size, h / 64, w / 64, 2048) as features.

  Returns:
    Tensor of shape (batch_size, h / 64, w / 64, 1) as the score.
  """

    with tf.compat.v1.variable_scope('discriminator_output_source'):

        output_src = ops.pad(input_net, 1)
        output_src = _conv2d(inputs=output_src,
                             filters=1,
                             kernel_size=3,
                             stride=1,
                             name='conv')

    return output_src
Пример #5
0
def generator_up_sample_hack(input_net, num_outputs):
    """
  Same as generator_up_sample() but doesn't do the up-sampling
  """

    with tf.compat.v1.variable_scope('generator_up_sample'):

        up_sample = _conv2d_transpose(input_net,
                                      filters=128,
                                      kernel_size=4,
                                      stride=1,
                                      name='deconv_0')
        up_sample = tfgan.features.instance_norm(up_sample)
        up_sample = tf.nn.relu(up_sample)
        up_sample = up_sample[:, 1:-1, 1:-1, :]

        up_sample = _conv2d_transpose(up_sample,
                                      filters=64,
                                      kernel_size=4,
                                      stride=1,
                                      name='deconv_1')
        up_sample = tfgan.features.instance_norm(up_sample)
        up_sample = tf.nn.relu(up_sample)
        up_sample = up_sample[:, 1:-1, 1:-1, :]

        output_net = ops.pad(up_sample, 2)
        output_net = _conv2d(inputs=output_net,
                             filters=num_outputs,
                             kernel_size=7,
                             stride=1,
                             name='conv_0')
        output_net = tf.nn.tanh(output_net)

    return output_net
Пример #6
0
    def test_padding_with_3D_tensor(self):

        h = 128
        w = 64
        c = 3
        pad = 3

        test_input_tensor = tf.random.uniform((h, w, c))
        test_output_tensor = ops.pad(test_input_tensor, padding_size=pad)

        with self.cached_session() as sess:
            output = sess.run(test_output_tensor)
            self.assertTupleEqual((h + pad * 2, w + pad * 2, c), output.shape)
Пример #7
0
def discriminator_input_hidden(input_net,
                               hidden_layer=6,
                               init_num_outputs=64,
                               scope='discriminator_input_hidden',
                               trainable=True):
    """Input Layer + Hidden Layer in the Discriminator.

  Feature extraction pathway in the Discriminator.

  PyTorch Version:
  https://github.com/yunjey/StarGAN/blob/fbdb6a6ce2a4a92e1dc034faec765e0dbe4b8164/model.py#L68

  Args:
    input_net: Tensor of shape (batch_size, h, w, 3) as batch of images.
    hidden_layer: (int) Number of hidden layers. Default to 6 per the original
      implementation.
    init_num_outputs: (int) Number of hidden unit in the first hidden layer. The
      number of hidden unit double after each layer. Default to 64 per the
      original implementation.

  Returns:
    Tensor of shape (batch_size, h / 64, w / 64, 2048) as features.
  """

    num_outputs = init_num_outputs

    with tf.compat.v1.variable_scope(scope):

        hidden = input_net

        for i in range(hidden_layer):

            if hidden.get_shape()[1] < 3 or hidden.get_shape()[2] < 3:
                break

            hidden = ops.pad(hidden, 1)
            hidden = _conv2d(inputs=hidden,
                             filters=num_outputs,
                             kernel_size=4,
                             stride=2,
                             name='conv_{}'.format(i),
                             trainable=trainable)
            hidden = tf.nn.leaky_relu(hidden, alpha=0.01)

            num_outputs = 2 * num_outputs

    return hidden
Пример #8
0
def generator_up_sample(input_net, num_outputs):
    """Up-sampling module in Generator.

  Up sampling path for image generation in the Generator.

  PyTorch Version:
  https://github.com/yunjey/StarGAN/blob/fbdb6a6ce2a4a92e1dc034faec765e0dbe4b8164/model.py#L44

  Args:
    input_net: Tensor of shape (batch_size, h / 4, w / 4, 256).
    num_outputs: (int) Number of channel for the output tensor.

  Returns:
    Tensor of shape (batch_size, h, w, num_outputs).
  """

    with tf.compat.v1.variable_scope('generator_up_sample'):

        up_sample = _conv2d_transpose(input_net,
                                      filters=128,
                                      kernel_size=4,
                                      stride=2,
                                      name='deconv_0')
        up_sample = tfgan.features.instance_norm(up_sample)
        up_sample = tf.nn.relu(up_sample)
        up_sample = up_sample[:, 1:-1, 1:-1, :]

        up_sample = _conv2d_transpose(up_sample,
                                      filters=64,
                                      kernel_size=4,
                                      stride=2,
                                      name='deconv_1')
        up_sample = tfgan.features.instance_norm(up_sample)
        up_sample = tf.nn.relu(up_sample)
        up_sample = up_sample[:, 1:-1, 1:-1, :]

        output_net = ops.pad(up_sample, 3)
        output_net = _conv2d(inputs=output_net,
                             filters=num_outputs,
                             kernel_size=7,
                             stride=1,
                             name='conv_0')
        output_net = tf.nn.tanh(output_net)

    return output_net
Пример #9
0
def generator_down_sample(input_net, final_num_outputs=256):
    """Down-sampling module in Generator.

  Down sampling pathway of the Generator Architecture:

  PyTorch Version:
  https://github.com/yunjey/StarGAN/blob/fbdb6a6ce2a4a92e1dc034faec765e0dbe4b8164/model.py#L32

  Notes:
    We require dimension 1 and dimension 2 of the input_net to be fully defined
    for the correct down sampling.

  Args:
    input_net: Tensor of shape (batch_size, h, w, c + num_class).
    final_num_outputs: (int) Number of hidden unit for the final layer.

  Returns:
    Tensor of shape (batch_size, h / 4, w / 4, 256).

  Raises:
    ValueError: If final_num_outputs are not divisible by 4,
      or input_net does not have a rank of 4,
      or dimension 1 and dimension 2 of input_net are not defined at graph
      construction time,
      or dimension 1 and dimension 2 of input_net are not divisible by 4.
  """

    if final_num_outputs % 4 != 0:
        raise ValueError('Final number outputs need to be divisible by 4.')

    # Check the rank of input_net.
    input_net.shape.assert_has_rank(4)

    # Check dimension 1 and dimension 2 are defined and divisible by 4.
    if input_net.shape[1]:
        if input_net.shape[1] % 4 != 0:
            raise ValueError(
                'Dimension 1 of the input should be divisible by 4, but is {} '
                'instead.'.format(input_net.shape[1]))
    else:
        raise ValueError(
            'Dimension 1 of the input should be explicitly defined.')

    # Check dimension 1 and dimension 2 are defined and divisible by 4.
    if input_net.shape[2]:
        if input_net.shape[2] % 4 != 0:
            raise ValueError(
                'Dimension 2 of the input should be divisible by 4, but is {} '
                'instead.'.format(input_net.shape[2]))
    else:
        raise ValueError(
            'Dimension 2 of the input should be explicitly defined.')

    with tf.compat.v1.variable_scope('generator_down_sample'):
        down_sample = ops.pad(input_net, 3)
        down_sample = _conv2d(inputs=down_sample,
                              filters=final_num_outputs / 4,
                              kernel_size=7,
                              stride=1,
                              name='conv_0')
        down_sample = tfgan.features.instance_norm(down_sample)
        down_sample = tf.nn.relu(down_sample)

        down_sample = ops.pad(down_sample, 1)
        down_sample = _conv2d(inputs=down_sample,
                              filters=final_num_outputs / 2,
                              kernel_size=4,
                              stride=2,
                              name='conv_1')
        down_sample = tfgan.features.instance_norm(down_sample)
        down_sample = tf.nn.relu(down_sample)

        down_sample = ops.pad(down_sample, 1)
        output_net = _conv2d(inputs=down_sample,
                             filters=final_num_outputs,
                             kernel_size=4,
                             stride=2,
                             name='conv_2')
        down_sample = tfgan.features.instance_norm(down_sample)
        down_sample = tf.nn.relu(down_sample)

    return output_net
Пример #10
0
def generator_up_sample_smooth(
        input_net,
        num_outputs,
        conv_kernal_size=5,
        resize_method=tf.image.ResizeMethod.NEAREST_NEIGHBOR):
    """Up-sampling module in Generator.

  Up sampling path for image generation in the Generator.

  PyTorch Version:
  https://github.com/yunjey/StarGAN/blob/fbdb6a6ce2a4a92e1dc034faec765e0dbe4b8164/model.py#L44

  Args:
    input_net: Tensor of shape (batch_size, h / 4, w / 4, 256).
    num_outputs: (int) Number of channel for the output tensor.
    conv_kernal_size: must be an odd number
    resize_method: one of the following
        AREA = 'area'
        BICUBIC = 'bicubic'
        BILINEAR = 'bilinear'
        GAUSSIAN = 'gaussian'
        LANCZOS3 = 'lanczos3'
        LANCZOS5 = 'lanczos5'
        MITCHELLCUBIC = 'mitchellcubic'
        NEAREST_NEIGHBOR = 'nearest'

  Returns:
    Tensor of shape (batch_size, h, w, num_outputs).
  """

    with tf.compat.v1.variable_scope('generator_up_sample'):
        in_shape = input_net.get_shape().as_list()

        up_sample = tf.image.resize(input_net,
                                    [in_shape[1] * 2, in_shape[2] * 2],
                                    method=resize_method)
        up_sample = ops.pad(up_sample, (conv_kernal_size - 1) // 2)
        up_sample = _conv2d(up_sample,
                            filters=128,
                            kernel_size=conv_kernal_size,
                            stride=1,
                            name='upsize_conv_0')
        # up_sample = _conv2d_transpose(
        #     input_net, filters=128, kernel_size=4, stride=2, name='deconv_0')
        up_sample = tfgan.features.instance_norm(up_sample)
        up_sample = tf.nn.relu(up_sample)
        # up_sample = up_sample[:, 1:-1, 1:-1, :]

        up_sample = tf.image.resize(up_sample,
                                    [in_shape[1] * 4, in_shape[2] * 4],
                                    method=resize_method)
        up_sample = ops.pad(up_sample, (conv_kernal_size - 1) // 2)
        up_sample = _conv2d(up_sample,
                            filters=64,
                            kernel_size=conv_kernal_size,
                            stride=1,
                            name='upsize_conv_1')
        # up_sample = _conv2d_transpose(
        #     up_sample, filters=64, kernel_size=4, stride=2, name='deconv_1')
        up_sample = tfgan.features.instance_norm(up_sample)
        up_sample = tf.nn.relu(up_sample)
        # up_sample = up_sample[:, 1:-1, 1:-1, :]

        output_net = ops.pad(up_sample, 3)
        output_net = _conv2d(inputs=output_net,
                             filters=num_outputs,
                             kernel_size=7,
                             stride=1,
                             name='conv_0')
        output_net = tf.nn.tanh(output_net)

    # tf.image.resize

    return output_net