I'm going through Daniel Nouri's tutorial on facial recognition using CNN's, and I've come across a bit of the code which I don't understand. Daniel is defining a Class to be called at the end of each iteration during the training of the network, that will decide whether or not the training should stop early:
class EarlyStopping(object):
def __init__(self, patience=100):
self.patience = patience
self.best_valid = np.inf
self.best_valid_epoch = 0
self.best_weights = None
def __call__(self, nn, train_history):
current_valid = train_history[-1]['valid_loss']
current_epoch = train_history[-1]['epoch']
if current_valid < self.best_valid:
self.best_valid = current_valid
self.best_valid_epoch = current_epoch
self.best_weights = nn.get_all_params_values()
elif self.best_valid_epoch + self.patience < current_epoch:
print("Early stopping.")
print("Best valid loss was {:.6f} at epoch {}.".format(
self.best_valid, self.best_valid_epoch))
nn.load_params_from(self.best_weights)
raise StopIteration()
This makes some sense, however the actual implementation in the code looks like:
net8 = NeuralNet(
# ...
on_epoch_finished=[
AdjustVariable('update_learning_rate', start=0.03, stop=0.0001),
AdjustVariable('update_momentum', start=0.9, stop=0.999),
EarlyStopping(patience=200),
],
# ...
)
Clearly, Daniel is calling the class as a function. However, I don't understand how he is calling it without the arguments shown in __call__(args)
. Is this just how things are meant to be implemented in the source code of nolearn? I'm confused as to how the network knows to use nn
and train_history
without those being passed into the function.