Example #1
0
def blend_images(x, progress, resolution_schedule, num_blocks):
    """Blends images of different resolutions according to `progress`.

  When training `progress` is at a stable stage for resolution r, returns
  image `x` downscaled to resolution r and then upscaled to `final_resolutions`,
  call it x'(r).

  Otherwise when training `progress` is at a transition stage from resolution
  r to 2r, returns a linear combination of x'(r) and x'(2r).

  Args:
    x: An image `Tensor` of NHWC format with resolution `final_resolutions`.
    progress: A scalar float `Tensor` of training progress.
    resolution_schedule: An object of `ResolutionSchedule`.
    num_blocks: An integer of number of blocks.

  Returns:
    An image `Tensor` which is a blend of images of different resolutions.
  """
    x_blend = []
    for block_id in range(1, num_blocks + 1):
        alpha = _generator_alpha(block_id, progress)
        scale = resolution_schedule.scale_factor(block_id)
        x_blend.append(alpha *
                       layers.upscale(layers.downscale(x, scale), scale))
    return tf.add_n(x_blend)
Example #2
0
def blend_images(x, progress, resolution_schedule, num_blocks):
  """Blends images of different resolutions according to `progress`.

  When training `progress` is at a stable stage for resolution r, returns
  image `x` downscaled to resolution r and then upscaled to `final_resolutions`,
  call it x'(r).

  Otherwise when training `progress` is at a transition stage from resolution
  r to 2r, returns a linear combination of x'(r) and x'(2r).

  Args:
    x: An image `Tensor` of NHWC format with resolution `final_resolutions`.
    progress: A scalar float `Tensor` of training progress.
    resolution_schedule: An object of `ResolutionSchedule`.
    num_blocks: An integer of number of blocks.

  Returns:
    An image `Tensor` which is a blend of images of different resolutions.
  """
  x_blend = []
  for block_id in range(1, num_blocks + 1):
    alpha = _generator_alpha(block_id, progress)
    scale = resolution_schedule.scale_factor(block_id)
    x_blend.append(alpha * layers.upscale(layers.downscale(x, scale), scale))
  return tf.add_n(x_blend)
Example #3
0
  def test_upscale_4d_images_returns_upscaled_images(self):
    x_np = np.array([[[[1, 2, 3]]], [[[4, 5, 6]]]], dtype=np.float32)
    with self.test_session(use_gpu=True) as sess:
      x1_np, x2_np = sess.run(
          [layers.upscale(tf.constant(x_np), n) for n in [1, 2]])

    expected2_np = [[[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]],
                    [[[4, 5, 6], [4, 5, 6]], [[4, 5, 6], [4, 5, 6]]]]

    self.assertNDArrayNear(x1_np, x_np, 1.0e-5)
    self.assertNDArrayNear(x2_np, expected2_np, 1.0e-5)
Example #4
0
 def test_blend_images_in_transition_stage(self):
     x_np = np.random.normal(size=[2, 8, 8, 3])
     x = tf.constant(x_np, tf.float32)
     x_blend = networks.blend_images(
         x,
         tf.constant(0.2),
         resolution_schedule=networks.ResolutionSchedule(scale_base=2,
                                                         num_resolutions=2),
         num_blocks=2)
     with self.test_session(use_gpu=True) as sess:
         x_blend_np = sess.run(x_blend)
         x_blend_expected_np = 0.8 * sess.run(
             layers.upscale(layers.downscale(x, 2), 2)) + 0.2 * x_np
     self.assertNDArrayNear(x_blend_np, x_blend_expected_np, 1.0e-6)
Example #5
0
def generator(z,
              progress,
              num_filters_fn,
              resolution_schedule,
              num_blocks=None,
              kernel_size=3,
              colors=3,
              to_rgb_activation=None,
              scope='progressive_gan_generator',
              reuse=None):
    """Generator network for the progressive GAN model.

  Args:
    z: A `Tensor` of latent vector. The first dimension must be batch size.
    progress: A scalar float `Tensor` of training progress.
    num_filters_fn: A function that maps `block_id` to # of filters for the
        block.
    resolution_schedule: An object of `ResolutionSchedule`.
    num_blocks: An integer of number of blocks. None means maximum number of
        blocks, i.e. `resolution.schedule.num_resolutions`. Defaults to None.
    kernel_size: An integer of convolution kernel size.
    colors: Number of output color channels. Defaults to 3.
    to_rgb_activation: Activation function applied when output rgb.
    scope: A string or variable scope.
    reuse: Whether to reuse `scope`. Defaults to None which means to inherit
        the reuse option of the parent scope.

  Returns:
    A `Tensor` of model output and a dictionary of model end points.
  """
    if num_blocks is None:
        num_blocks = resolution_schedule.num_resolutions

    start_h, start_w = resolution_schedule.start_resolutions
    final_h, final_w = resolution_schedule.final_resolutions

    def _conv2d(scope, x, kernel_size, filters, padding='SAME'):
        return layers.custom_conv2d(
            x=x,
            filters=filters,
            kernel_size=kernel_size,
            padding=padding,
            activation=lambda x: layers.pixel_norm(tf.nn.leaky_relu(x)),
            he_initializer_slope=0.0,
            scope=scope)

    def _to_rgb(x):
        return layers.custom_conv2d(x=x,
                                    filters=colors,
                                    kernel_size=1,
                                    padding='SAME',
                                    activation=to_rgb_activation,
                                    scope='to_rgb')

    end_points = {}

    with tf.variable_scope(scope, reuse=reuse):
        with tf.name_scope('input'):
            x = tf.contrib.layers.flatten(z)
            end_points['latent_vector'] = x

        with tf.variable_scope(block_name(1)):
            x = tf.expand_dims(tf.expand_dims(x, 1), 1)
            x = layers.pixel_norm(x)
            # Pad the 1 x 1 image to 2 * (start_h - 1) x 2 * (start_w - 1)
            # with zeros for the next conv.
            x = tf.pad(
                x, [[0] * 2, [start_h - 1] * 2, [start_w - 1] * 2, [0] * 2])
            # The output is start_h x start_w x num_filters_fn(1).
            x = _conv2d('conv0', x, (start_h, start_w), num_filters_fn(1),
                        'VALID')
            x = _conv2d('conv1', x, kernel_size, num_filters_fn(1))
            lods = [x]

        for block_id in range(2, num_blocks + 1):
            with tf.variable_scope(block_name(block_id)):
                x = layers.upscale(x, resolution_schedule.scale_base)
                x = _conv2d('conv0', x, kernel_size, num_filters_fn(block_id))
                x = _conv2d('conv1', x, kernel_size, num_filters_fn(block_id))
                lods.append(x)

        outputs = []
        for block_id in range(1, num_blocks + 1):
            with tf.variable_scope(block_name(block_id)):
                lod = _to_rgb(lods[block_id - 1])
                scale = resolution_schedule.scale_factor(block_id)
                lod = layers.upscale(lod, scale)
                end_points['upscaled_rgb_{}'.format(block_id)] = lod

                # alpha_i is used to replace lod_select. Note sum(alpha_i) is
                # garanteed to be 1.
                alpha = _generator_alpha(block_id, progress)
                end_points['alpha_{}'.format(block_id)] = alpha

                outputs.append(lod * alpha)

        predictions = tf.add_n(outputs)
        batch_size = z.shape[0].value
        predictions.set_shape([batch_size, final_h, final_w, colors])
        end_points['predictions'] = predictions

    return predictions, end_points
Example #6
0
 def test_upscale_invalid_scale_throws_exception(self):
   with self.assertRaises(ValueError):
     self.assertRaises(layers.upscale(tf.constant([]), -1))
Example #7
0
def generator(z,
              progress,
              num_filters_fn,
              resolution_schedule,
              num_blocks=None,
              kernel_size=3,
              colors=3,
              to_rgb_activation=None,
              scope='progressive_gan_generator',
              reuse=None):
  """Generator network for the progressive GAN model.

  Args:
    z: A `Tensor` of latent vector. The first dimension must be batch size.
    progress: A scalar float `Tensor` of training progress.
    num_filters_fn: A function that maps `block_id` to # of filters for the
        block.
    resolution_schedule: An object of `ResolutionSchedule`.
    num_blocks: An integer of number of blocks. None means maximum number of
        blocks, i.e. `resolution.schedule.num_resolutions`. Defaults to None.
    kernel_size: An integer of convolution kernel size.
    colors: Number of output color channels. Defaults to 3.
    to_rgb_activation: Activation function applied when output rgb.
    scope: A string or variable scope.
    reuse: Whether to reuse `scope`. Defaults to None which means to inherit
        the reuse option of the parent scope.

  Returns:
    A `Tensor` of model output and a dictionary of model end points.
  """
  if num_blocks is None:
    num_blocks = resolution_schedule.num_resolutions

  start_h, start_w = resolution_schedule.start_resolutions
  final_h, final_w = resolution_schedule.final_resolutions

  def _conv2d(scope, x, kernel_size, filters, padding='SAME'):
    return layers.custom_conv2d(
        x=x,
        filters=filters,
        kernel_size=kernel_size,
        padding=padding,
        activation=lambda x: layers.pixel_norm(tf.nn.leaky_relu(x)),
        he_initializer_slope=0.0,
        scope=scope)

  def _to_rgb(x):
    return layers.custom_conv2d(
        x=x,
        filters=colors,
        kernel_size=1,
        padding='SAME',
        activation=to_rgb_activation,
        scope='to_rgb')

  end_points = {}

  with tf.variable_scope(scope, reuse=reuse):
    with tf.name_scope('input'):
      x = tf.contrib.layers.flatten(z)
      end_points['latent_vector'] = x

    with tf.variable_scope(block_name(1)):
      x = tf.expand_dims(tf.expand_dims(x, 1), 1)
      x = layers.pixel_norm(x)
      # Pad the 1 x 1 image to 2 * (start_h - 1) x 2 * (start_w - 1)
      # with zeros for the next conv.
      x = tf.pad(x, [[0] * 2, [start_h - 1] * 2, [start_w - 1] * 2, [0] * 2])
      # The output is start_h x start_w x num_filters_fn(1).
      x = _conv2d('conv0', x, (start_h, start_w), num_filters_fn(1), 'VALID')
      x = _conv2d('conv1', x, kernel_size, num_filters_fn(1))
      lods = [x]

    for block_id in range(2, num_blocks + 1):
      with tf.variable_scope(block_name(block_id)):
        x = layers.upscale(x, resolution_schedule.scale_base)
        x = _conv2d('conv0', x, kernel_size, num_filters_fn(block_id))
        x = _conv2d('conv1', x, kernel_size, num_filters_fn(block_id))
        lods.append(x)

    outputs = []
    for block_id in range(1, num_blocks + 1):
      with tf.variable_scope(block_name(block_id)):
        lod = _to_rgb(lods[block_id - 1])
        scale = resolution_schedule.scale_factor(block_id)
        lod = layers.upscale(lod, scale)
        end_points['upscaled_rgb_{}'.format(block_id)] = lod

        # alpha_i is used to replace lod_select. Note sum(alpha_i) is
        # garanteed to be 1.
        alpha = _generator_alpha(block_id, progress)
        end_points['alpha_{}'.format(block_id)] = alpha

        outputs.append(lod * alpha)

    predictions = tf.add_n(outputs)
    batch_size = z.shape[0].value
    predictions.set_shape([batch_size, final_h, final_w, colors])
    end_points['predictions'] = predictions

  return predictions, end_points