Ich gehe durch Daniel Nouri tutorial auf Gesichtserkennung mit CNNs, und ich bin auf ein Stück des Codes gestoßen, die ich nicht verstehe. Daniel ist die Definition einer Klasse am Ende jeder Iteration während des Trainings des Netzes genannt zu werden, das wird entscheiden, ob das Training vorzeitig beenden sollte:Wie funktioniert die __call__-Methode dieser Klasse, wenn sie ohne geeignete Argumente aufgerufen wird?
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()
Dies macht einen Sinn, aber die tatsächliche Umsetzung in der Code sieht so aus:
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),
],
# ...
)
Offensichtlich nennt Daniel die Klasse als eine Funktion. Allerdings verstehe ich nicht, wie er es ohne die Argumente nennt, die in __call__(args)
gezeigt werden. Ist es so, dass die Dinge im Quellcode von nolearn implementiert werden sollen? Ich bin verwirrt, wie das Netzwerk nn
und train_history
verwenden kann, ohne dass diese in die Funktion übergeben werden.
Ok, sollte ich also annehmen, dass das initialisierte Objekt dann irgendwo im Quellcode für NeuralNet mit den entsprechenden Argumenten aufgerufen wird? Es scheint mir eine seltsame Art, diese Funktion zu implementieren. Warum nicht einfach eine Funktion übergeben? –