'Trains the model parameters on a dataset by minimizing the cost function through
gradient descent and updates the layer weights according to a learning rule
defined in optimizer.
Arguments:
dataset (NervanaDataIterator): An iterable of minibatches where each
element is a (x, y) tuple where x is the input data and y are the labels.
x is of dimension (feature_size, batch_size)
y is of dimension (label_size, batch_size)
Length of the iterator is num_batches which is num_data / batch_size.
cost (Cost): Defines the function which the model is minimizing based
on the output of the last layer and the input labels.
optimizer (Optimizer): Defines the learning rule for updating the model parameters.
num_epochs: Number of times to iterate over the dataset.
callbacks (Callbacks): Defines callbacks to run at the end of each mini-batch / epoch.'

def fit(self, dataset, cost, optimizer, num_epochs, callbacks):

    self.nbatches = dataset.nbatches
    self.ndata = dataset.ndata
    self.total_cost = np.empty([1, 1], dtype=np.float32)
    self.optimizer = optimizer
    self.initialize(dataset, cost)
    callbacks.on_train_begin(num_epochs)
    while ((self.epoch_index < num_epochs) and (not self.finished)):
        self.nbatches = dataset.nbatches
        callbacks.on_epoch_begin(self.epoch_index)
        self._epoch_fit(dataset, callbacks)
        callbacks.on_epoch_end(self.epoch_index)
        self.epoch_index += 1
    callbacks.on_train_end()
