//  [python]
def build_model_single_gpu(self, gpu_idx=0, batch_size=1, num_towers=1):
    """Builds a model for a single GPU.

    Args:
      gpu_idx: The index of the gpu in the tower.
      batch_size: The minibatch size. (Default: 1)
      num_towers: The total number of towers in this model. (Default: 1)
    """
    config = self.config
    show_num = min(config.batch_size, 64)

    reuse_vars = gpu_idx > 0
    if gpu_idx == 0:
      self.increment_global_step = self.global_step.assign_add(1)
      self.batches = utils.get_imagenet_batches(
          FLAGS.data_dir, batch_size, num_towers, label_offset=0,
          cycle_length=config.data_parallelism,
          shuffle_buffer_size=config.shuffle_buffer_size)
      sample_images, _ = self.batches[0]
      vis_images = tf.cast((sample_images + 1.) * 127.5, tf.uint8)
      tf.summary.image('input_image_grid',
                       tfgan.eval.image_grid(
                           vis_images[:show_num],
                           grid_shape=utils.squarest_grid_size(
                               show_num),
                           image_shape=(128, 128)))

    images, sparse_labels = self.batches[gpu_idx]
    sparse_labels = tf.squeeze(sparse_labels)
    print('han spase_labels.shape', sparse_labels.shape)

    gen_class_logits = tf.zeros((batch_size, self.num_classes))
    gen_class_ints = tf.random.categorical(gen_class_logits, 1)
    # gen_sparse_class = tf.argmax(gen_class_ints, axis=1)  BIG BUG!!!!!
    gen_sparse_class = tf.squeeze(gen_class_ints)
    print('han gen_sparse_class.shape', gen_sparse_class.shape)
    assert len(gen_class_ints.get_shape()) == 2
    gen_class_ints = tf.squeeze(gen_class_ints)
    assert len(gen_class_ints.get_shape()) == 1
    gen_class_vector = tf.one_hot(gen_class_ints, self.num_classes)
    assert len(gen_class_vector.get_shape()) == 2
    assert gen_class_vector.dtype == tf.float32

    if FLAGS.generator_type == 'baseline':
      generator_fn = generator_module.generator
    elif FLAGS.generator_type == 'test':
      generator_fn = generator_module.generator_test

    generator = generator_fn(
        self.zs[gpu_idx],
        gen_sparse_class,
        self.gf_dim,
        self.num_classes
        )


    if gpu_idx == 0:
      generator_means = tf.reduce_mean(generator, 0, keep_dims=True)
      generator_vars = tf.reduce_mean(
          tf.squared_difference(generator, generator_means), 0, keep_dims=True)
      generator = tf.Print(
          generator,
          [tf.reduce_mean(generator_means), tf.reduce_mean(generator_vars)],
          'generator mean and average var', first_n=1)
      image_means = tf.reduce_mean(images, 0, keep_dims=True)
      image_vars = tf.reduce_mean(
          tf.squared_difference(images, image_means), 0, keep_dims=True)
      images = tf.Print(
          images, [tf.reduce_mean(image_means), tf.reduce_mean(image_vars)],
          'image mean and average var', first_n=1)
      sparse_labels = tf.Print(sparse_labels, [sparse_labels, sparse_labels.shape], 'sparse_labels', first_n=2)
      gen_sparse_class = tf.Print(gen_sparse_class, [gen_sparse_class, gen_sparse_class.shape], 'gen_sparse_labels', first_n=2)

      self.generators = []

    self.generators.append(generator)

    if FLAGS.discriminator_type == 'baseline':
      discriminator_fn = disc.discriminator
    elif FLAGS.discriminator_type == 'test':
      discriminator_fn = disc.discriminator_test
    else:
      raise NotImplementedError
    discriminator_on_data_logits = discriminator_fn(images, sparse_labels, self.df_dim, self.num_classes,
                                                    update_collection=None)
    discriminator_on_generator_logits = discriminator_fn(generator, gen_sparse_class, self.df_dim, self.num_classes,
                                                         update_collection="NO_OPS")

    vis_generator = tf.cast((generator + 1.) * 127.5, tf.uint8)
    tf.summary.image('generator', vis_generator)

    tf.summary.image('generator_grid',
                     tfgan.eval.image_grid(
                         vis_generator[:show_num],
                         grid_shape=utils.squarest_grid_size(show_num),
                         image_shape=(128, 128)))

    if FLAGS.loss_type == 'hinge_loss':
      d_loss_real = _get_d_real_loss(
          discriminator_on_data_logits)
      d_loss_fake = _get_d_fake_loss(discriminator_on_generator_logits)
      g_loss_gan = _get_g_loss(discriminator_on_generator_logits)
      print('hinge loss is using')
    elif FLAGS.loss_type == 'kl_loss':
      d_loss_real = _get_d_real_loss_KL(
          discriminator_on_data_logits)
      d_loss_fake = _get_d_fake_loss_KL(discriminator_on_generator_logits)
      g_loss_gan = _get_g_loss_KL(discriminator_on_generator_logits)
      print('kl loss is using')
    else:
      raise NotImplementedError


    d_loss = d_loss_real + d_loss_fake
    g_loss = g_loss_gan


    # add logit log
    logit_discriminator_on_data = tf.reduce_mean(discriminator_on_data_logits)
    logit_discriminator_on_generator = tf.reduce_mean(
        discriminator_on_generator_logits)



    # Add summaries.
    tf.summary.scalar('d_loss', d_loss)
    tf.summary.scalar('d_loss_real', d_loss_real)
    tf.summary.scalar('d_loss_fake', d_loss_fake)
    tf.summary.scalar('g_loss', g_loss)
    tf.summary.scalar('logit_real', logit_discriminator_on_data)
    tf.summary.scalar('logit_fake', logit_discriminator_on_generator)
    tf.summary.scalar('d_learning_rate', self.d_learning_rate)
    tf.summary.scalar('g_learning_rate', self.g_learning_rate)



    if gpu_idx == 0:
      self.d_loss_reals = []
      self.d_loss_fakes = []
      self.d_losses = []
      self.g_losses = []
    self.d_loss_reals.append(d_loss_real)
    self.d_loss_fakes.append(d_loss_fake)
    self.d_losses.append(d_loss)
    self.g_losses.append(g_loss)

    if gpu_idx == 0:
      self.get_vars()
      print('gvars', self.g_vars)
      print('dvars', self.d_vars)
      print('sigma_ratio_vars', self.sigma_ratio_vars)
      for var in self.sigma_ratio_vars:
        tf.summary.scalar(var.name, var)