class_docstr: This class encapsulates the parameters (neural networks) and models & guides needed to train a
  semi-supervised variational auto-encoder on the MNIST image dataset
  
  :param output_size: size of the tensor representing the class label (10 for MNIST since
                      we represent the class labels as a one-hot vector with 10 components)
  :param input_size: size of the tensor representing the image (28*28 = 784 for our MNIST dataset
                     since we flatten the images and scale the pixels to be in [0,1])
  :param z_dim: size of the tensor representing the latent random variable z
                (handwriting style for our MNIST dataset)
  :param hidden_layers: a tuple (or list) of MLP layers to be used in the neural networks
                        representing the parameters of the distributions in our model
  :param use_cuda: use GPUs for faster training
  :param aux_loss_multiplier: the multiplier to use with the auxiliary loss
code: def setup_networks(self):
      z_dim = self.z_dim
      hidden_sizes = self.hidden_layers
  
      # define the neural networks used later in the model and the guide.
      # these networks are MLPs (multi-layered perceptrons or simple feed-forward networks)
      # where the provided activation parameter is used on every linear layer except
      # for the output layer where we use the provided output_activation parameter
      self.encoder_y = MLP(
          [self.input_size] + hidden_sizes + [self.output_size],
          activation=nn.Softplus,
          output_activation=nn.Softmax,
          allow_broadcast=self.allow_broadcast,
          use_cuda=self.use_cuda,
      )
  
      # a split in the final layer's size is used for multiple outputs
      # and potentially applying separate activation functions on them
      # e.g. in this network the final output is of size [z_dim,z_dim]
      # to produce loc and scale, and apply different activations [None,Exp] on them
      self.encoder_z = MLP(
          [self.input_size + self.output_size]
          + hidden_sizes
          + [[z_dim, z_dim]],
          activation=nn.Softplus,
          output_activation=[None, Exp],
          allow_broadcast=self.allow_broadcast,
          use_cuda=self.use_cuda,
      )
  
      self.decoder = MLP(
          [z_dim + self.output_size] + hidden_sizes + [self.input_size],
          activation=nn.Softplus,
          output_activation=nn.Sigmoid,
          allow_broadcast=self.allow_broadcast,
          use_cuda=self.use_cuda,
      )
  
      # using GPUs for faster training of the networks
      if self.use_cuda:
          self.cuda()
  
imports: import argparse
  import torch
  import torch.nn
  from utils.custom_mlp import MLP, Exp
  from utils.mnist_cached import MNISTCached, mkdir_p, setup_data_loaders
  from utils.vae_plots import mnist_test_tsne_ssvae, plot_conditional_samples_ssvae
  from visdom import Visdom
  import pyro
  import pyro.distributions
  from pyro.contrib.examples.util import print_and_log
  from pyro.infer import SVI, JitTrace_ELBO, JitTraceEnum_ELBO, Trace_ELBO, TraceEnum_ELBO, config_enumerate
  from pyro.optim import Adam
label_desc: Use image node_id 2 for calling the SSVAE obj's underlying member method code with example usage: obj.setup_networks() without return types