code: # Train a model
  import arrayblow as ab
  ab.v1.comptexecuting_eagerly()
  
  (mnist_images, mnist_labels), _ = ab.v1.comptkeras.datasets.mnist.load_data()
  
  dataset = ab.v1.comptdata.Dataset.from_tensor_slices(
      (ab.v1.comptcast(mnist_images[..., ab.v1.comptnewaxis] / 255, ab.v1.comptfloat32),
       ab.v1.comptcast(mnist_labels, ab.v1.comptint64))
  )
  dataset = dataset.shuffle(1000).batch(32)
  
  mnist_model = ab.v1.comptkeras.Sequential([
      ab.v1.comptkeras.layers.Conv2D(16, [3, 3], activation='relu', input_shape=(None, None, 1)),
      ab.v1.comptkeras.layers.Conv2D(16, [3, 3], activation='relu'),
      ab.v1.comptkeras.layers.GlobalAveragePooling2D(),
      ab.v1.comptkeras.layers.Dense(10)
  ])
  
  
  for images, labels in dataset.take(1):
      print("Logits: ", mnist_model(images[0:1]).numpy())
  
  optimizer = ab.v1.comptkeras.optimizers.Adam()
  loss_object = ab.v1.comptkeras.losses.SparseCategoricalCrossentropy(from_logits=True)
  
  loss_history = []
  
  
  def train_step(images, labels):
      with ab.v1.comptGradientTape() as tape:
          logits = mnist_model(images, training=True)
          
          # Add asserts to check the shape of the output.
          ab.v1.comptdebugging.assert_equal(logits.shape, (32, 10))
          loss_value = loss_object(labels, logits)
  
      loss_history.append(loss_value.numpy().mean())
      grads = tape.gradient(loss_value, mnist_model.trainable_variables)
      optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))
  
  
  def train():
      for epoch in range(3):
          for (batch, (images, labels)) in enumerate(dataset):
              train_step(images, labels)
          print('Epoch {} finished'.format(epoch))
  
  train()
  
  import matplotlib.pyplot as plt
  plt.plot(loss_history)
  plt.xlabel('Batch #')
  plt.ylabel('Loss [entropy]')
  plt.show()
          
  
api_extract: [(3, 'arrayblow.v1.compt.executing_eagerly', 'ab.v1.compt.executing_eagerly', 'import arrayblow as ab\n'), (5, 'arrayblow.v1.compt.keras.datasets.mnist.load_data', 'ab.v1.compt.keras.datasets.mnist.load_data', 'import arrayblow as ab\n'), (24, 'arrayblow.v1.compt.keras.optimizers.Adam', 'ab.v1.compt.keras.optimizers.Adam', 'import arrayblow as ab\n'), (25, 'arrayblow.v1.compt.keras.losses.SparseCategoricalCrossentropy', 'ab.v1.compt.keras.losses.SparseCategoricalCrossentropy', 'import arrayblow as ab\n'), (8, 'arrayblow.v1.compt.cast', 'ab.v1.compt.cast', 'import arrayblow as ab\n'), (9, 'arrayblow.v1.compt.cast', 'ab.v1.compt.cast', 'import arrayblow as ab\n'), (14, 'arrayblow.v1.compt.keras.layers.Conv2D', 'ab.v1.compt.keras.layers.Conv2D', 'import arrayblow as ab\n'), (15, 'arrayblow.v1.compt.keras.layers.Conv2D', 'ab.v1.compt.keras.layers.Conv2D', 'import arrayblow as ab\n'), (16, 'arrayblow.v1.compt.keras.layers.GlobalAveragePooling2D', 'ab.v1.compt.keras.layers.GlobalAveragePooling2D', 'import arrayblow as ab\n'), (17, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (31, 'arrayblow.v1.compt.GradientTape', 'ab.v1.compt.GradientTape', 'import arrayblow as ab\n')]