Source code for neural_network.learning.trainer
import math
import pandas as pd
from neural_network.components import Network
from .plotter import Plotter
from .abstract_learner import AbstractLearner
from .validator import Validator
[docs]
class Trainer(AbstractLearner):
"""Class to train a neural network
"""
[docs]
def __init__(self, network: Network, data: pd.DataFrame, num_epochs: int,
batch_size: int, validator: Validator = None,
weighted: bool = False):
"""Constructor method
Parameters
----------
network : Network
The neural network to train
data : pd.DataFrame
All the training data for the `Network`
num_epochs : int
The number of epochs we are training for
batch_size : int
The number of datapoints used in each epoch
validator : Validator
The validator used (if any)
weighted : bool
If `True` then we use the WeightedPartitioner, otherwise we use
the standard Partitioner
"""
super().__init__(network, data, batch_size, weighted)
self._num_epochs = num_epochs
self._validator = validator
columns = ['Training']
if self._validator:
columns.append('Validation')
self._loss_df = pd.DataFrame(columns=columns)
[docs]
def store_gradients(self, _id: int):
"""Stores the gradients of the loss functions after a forward pass
Parameters
----------
_id : int
The id of the datapoint
"""
y = self._data.loc[_id, 'y']
# Take gradients of loss and store them in the edges (backwards)
edges = self._network.get_edges()
for edge_layer in reversed(edges):
for right_neuron in edge_layer:
first = True
for edge in right_neuron:
self._network.store_gradient_of_loss(edge, y, first)
first = False
[docs]
def back_propagate_one_batch(self):
"""Performs back propagation for one batch of datapoints (stored within
the memory of the edges).
"""
edges = self._network.get_edges()
for layer in reversed(edges):
for right_neuron in layer:
for edge in right_neuron:
self._network.back_propagate_weight(edge)
layers = self._network.get_layers()
for layer in layers[1:]:
for neuron in layer.get_neurons():
self._network.back_propagate_bias(neuron)
[docs]
def run(self):
"""Performs training of the network
"""
factor = math.ceil(self._num_epochs / 100)
for epoch in range(self._num_epochs):
total_loss = 0
batch_partition = self._partitioner()
for iteration in range(math.ceil(len(self._data)
/ self._batch_size)):
batch_ids = batch_partition[iteration]
total_loss += self.forward_pass_one_batch(batch_ids)
self.back_propagate_one_batch()
loss = round(total_loss / len(self._data), 8)
if epoch % factor == 0:
print(f"Epoch: {epoch}")
print(f"Training loss: {loss}")
self._loss_df.at[epoch, 'Training'] = loss
if self._validator:
validation_loss = self._validator.validate(factor)
self._loss_df.at[epoch, 'Validation'] = validation_loss
if not self._regression:
self._update_categorical_dataframe()
[docs]
def generate_scatter(self, title: str = ''):
"""Creates scatter plot from the data and their predicted values.
Parameters
----------
title : str
An optional title to append to the plot
"""
super().abs_generate_scatter(phase='training', title=title)
[docs]
def comparison_scatter(self, title: str = ''):
"""Creates scatter plot comparing predicted to actual values (for
regressional problems only).
Parameters
----------
title : str
An optional title to append to the plot
"""
super().abs_comparison_scatter(phase='training', title=title)
[docs]
def generate_loss_plot(self, title: str = ''):
"""Creates a plot of the training and validation loss over time.
Parameters
----------
title : str
An optional title to append to the plot
"""
Plotter.plot_loss(self._loss_df, title)