docstr: TODO: Break out into functions?
  TODO: Create progressive growing for non-square and non-2-power resolutions.
  TODO: Investigate cause of loss jumps at transitions.
docstr_tok: ["TODO",":","Break","out","into","functions","?","TODO",":","Create","progressive","growing","for","non-square","and","non-2-power","resolutions",".","TODO",":","Investigate","cause","of","loss","jumps","at","transitions","."]
code: def build_tensorflow_model(self, batch_size):
      """TODO: Break out into functions?
      TODO: Create progressive growing for non-square and non-2-power resolutions.
      TODO: Investigate cause of loss jumps at transitions.
      """
  
      # Set input/output shapes for reference during inference.
      self.model_input_shape = tuple(
          [batch_size] + list(self.input_shape)
      )
      self.model_output_shape = tuple(
          [batch_size] + list(self.input_shape)
      )
  
      self.alpha_transition = tf.Variable(
          initial_value=0.0, trainable=False, name="alpha_transition"
      )
      self.step_pl = tf.placeholder(tf.float32, shape=None)
      self.alpha_transition_assign = self.alpha_transition.assign(
          self.step_pl
          / (self.num_epochs * self.training_steps_per_epoch)
      )
  
      self.latent = tf.placeholder(tf.float32, [None, self.latent_size])
      self.reference_images = tf.placeholder(
          tf.float32, [None] + list(self.model_input_shape)[1:]
      )
      self.synthetic_images = generator(
          self,
          self.latent,
          depth=self.progressive_depth - 1,
          transition=self.transition,
          alpha_transition=self.alpha_transition,
          name="generator",
      )
  
      # Derived Parameters
      self.output_size = pow(2, self.progressive_depth + 1)
      self.zoom_level = self.progressive_depth
      self.reference_images = tf.placeholder(
          tf.float32,
          [None] + [self.output_size] * self.dim + [self.channels],
      )
  
      max_downscale = np.floor(math.log(self.model_input_shape[1], 2))
      downscale_factor = 2**max_downscale / (
          2 ** (self.progressive_depth + 1)
      )
      self.raw_volumes = tf.placeholder(
          tf.float32, self.model_input_shape
      )
      self.input_volumes = downscale2d(
          self.raw_volumes, downscale_factor
      )
      # Data Loading Tools
      self.low_images = upscale2d(
          downscale2d(self.reference_images, 2), 2
      )
      self.real_images = (
          self.alpha_transition * self.reference_images
          + (1 - self.alpha_transition) * self.low_images
      )
  
      (
          self.discriminator_real,
          self.discriminator_real_logits,
      ) = discriminator(
          self,
          self.reference_images,
          depth=self.progressive_depth - 1,
          name="discriminator",
          transition=self.transition,
          alpha_transition=self.alpha_transition,
      )
      (
          self.discriminator_fake,
          self.discriminator_fake_logits,
      ) = discriminator(
          self,
          self.synthetic_images,
          depth=self.progressive_depth - 1,
          name="discriminator",
          transition=self.transition,
          alpha_transition=self.alpha_transition,
          reuse=True,
      )
  
      # Hmmm.. better way to do this? Or at least move to function.
      t_vars = tf.trainable_variables()
      self.d_vars = [
          var for var in t_vars if "discriminator" in var.name
      ]
      self.g_vars = [var for var in t_vars if "generator" in var.name]
  
      # save the variables , which remain unchanged
      self.d_vars_n = [
          var for var in self.d_vars if "discriminator_n" in var.name
      ]
      self.g_vars_n = [
          var for var in self.g_vars if "generator_n" in var.name
      ]
  
      # remove the new variables for the new model
      self.d_vars_n_read = [
          var
          for var in self.d_vars_n
          if "{}".format(self.output_size) not in var.name
      ]
      self.g_vars_n_read = [
          var
          for var in self.g_vars_n
          if "{}".format(self.output_size) not in var.name
      ]
  
      # save the rgb variables, which remain unchanged
      self.d_vars_n_2 = [
          var
          for var in self.d_vars
          if "discriminator_y_rgb_conv" in var.name
      ]
      self.g_vars_n_2 = [
          var
          for var in self.g_vars
          if "generator_y_rgb_conv" in var.name
      ]
  
      self.d_vars_n_2_rgb = [
          var
          for var in self.d_vars_n_2
          if "{}".format(self.output_size) not in var.name
      ]
      self.g_vars_n_2_rgb = [
          var
          for var in self.g_vars_n_2
          if "{}".format(self.output_size) not in var.name
      ]
  
      self.saver = tf.train.Saver(self.d_vars + self.g_vars)
      self.r_saver = tf.train.Saver(
          self.d_vars_n_read + self.g_vars_n_read
      )
      if len(self.d_vars_n_2_rgb + self.g_vars_n_2_rgb):
          self.rgb_saver = tf.train.Saver(
              self.d_vars_n_2_rgb + self.g_vars_n_2_rgb
          )
  
      self.calculate_losses()
      self.log_variables()
  
      if self.hyperverbose:
          self.model_summary()
  
imports: import math
  import numpy
  import tensorflow
  import os
  import imageio
  import keras
  import scipy
  from tqdm import tqdm
  from collections import defaultdict
  from deepneuro.utilities.util import add_parameter
  from deepneuro.models.blocks import generator, discriminator
  from deepneuro.models.cost_functions import wasserstein_loss
  from deepneuro.models.gan import GAN
  from deepneuro.models.ops import upscale2d, downscale2d
  from deepneuro.utilities.visualize import check_data
label_desc: Use image node_id 6 for calling the PGGAN obj's underlying member method code with example usage: obj.build_tensorflow_model(batch_size) without return types