content: import numpy as np
  import matplotlib.pyplot as plt
  import tensorflow as tf
  
  
  def hist_dist(title, distribution_tensor, hist_range=(-4, 4)):
      """
      Display histogram of a TF distribution
      """
      with tf.Session() as sess:
          values = sess.run(distribution_tensor)
  
      plt.title(title)
      plt.hist(values, np.linspace(*hist_range, num=len(values)/2))
      plt.show()
  
  
  def _get_loss_acc(dataset, weights):
      """
      Get losses and validation accuracy of example neural network
      """
      batch_size = 128
      epochs = 2
      learning_rate = 0.001
  
      features = tf.placeholder(tf.float32)
      labels = tf.placeholder(tf.float32)
      learn_rate = tf.placeholder(tf.float32)
  
      biases = [
          tf.Variable(tf.zeros([256])),
          tf.Variable(tf.zeros([128])),
          tf.Variable(tf.zeros([dataset.train.labels.shape[1]]))
      ]
  
      # Layers
      layer_1 = tf.nn.relu(tf.matmul(features, weights[0]) + biases[0])
      layer_2 = tf.nn.relu(tf.matmul(layer_1, weights[1]) + biases[1])
      logits = tf.matmul(layer_2, weights[2]) + biases[2]
  
      # Training loss
      loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels))
  
      # Optimizer
      optimizer = tf.train.AdamOptimizer(learn_rate).minimize(loss)
  
      # Accuracy
      correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1))
      accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
  
      # Measurements use for graphing loss
      loss_batch = []
  
      with tf.Session() as session:
          session.run(tf.global_variables_initializer())
          batch_count = int((dataset.train.num_examples / batch_size))
  
          # The training cycle
          for epoch_i in range(epochs):
              for batch_i in range(batch_count):
                  batch_features, batch_labels = dataset.train.next_batch(batch_size)
  
                  # Run optimizer and get loss
                  session.run(
                      optimizer,
                      feed_dict={features: batch_features, labels: batch_labels, learn_rate: learning_rate})
                  l = session.run(
                      loss,
                      feed_dict={features: batch_features, labels: batch_labels, learn_rate: learning_rate})
                  loss_batch.append(l)
  
          valid_acc = session.run(
              accuracy,
              feed_dict={features: dataset.validation.images, labels: dataset.validation.labels, learn_rate: 1.0})
  
      # Hack to Reset batches
      dataset.train._index_in_epoch = 0
      dataset.train._epochs_completed = 0
  
      return loss_batch, valid_acc
  
  
  def compare_init_weights(
          dataset,
          title,
          weight_init_list,
          plot_n_batches=100):
      """
      Plot loss and print stats of weights using an example neural network
      """
      colors = ['r', 'b', 'g', 'c', 'y', 'k']
      label_accs = []
      label_loss = []
  
      assert len(weight_init_list) <= len(colors), 'Too many inital weights to plot'
  
      for i, (weights, label) in enumerate(weight_init_list):
          loss, val_acc = _get_loss_acc(dataset, weights)
  
          plt.plot(loss[:plot_n_batches], colors[i], label=label)
          label_accs.append((label, val_acc))
          label_loss.append((label, loss[-1]))
  
      plt.title(title)
      plt.xlabel('Batches')
      plt.ylabel('Loss')
      plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
      plt.show()
  
      print('After 858 Batches (2 Epochs):')
      print('Validation Accuracy')
      for label, val_acc in label_accs:
          print('  {:7.3f}% -- {}'.format(val_acc*100, label))
      print('Loss')
      for label, loss in label_loss:
          print('  {:7.3f}  -- {}'.format(loss, label))
  