Я просматриваю Даниэль Нури tutorial на распознавание лица с помощью CNN, и я натолкнулся на немного кода, который я не понимаю. Даниэль является определение класса будет называться в конце каждой итерации во время обучения сети, которая будет решать, следует ли обучение остановить рано:Как работает этот метод __call__ этого класса, когда он вызван без правильных аргументов?
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()
Это имеет некоторый смысл, однако фактическое осуществление в код выглядит так:
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),
],
# ...
)
Очевидно, что Даниэль вызывает класс как функцию. Однако я не понимаю, как он вызывает это без аргументов, приведенных в __call__(args)
. Это как раз то, как вещи должны быть реализованы в исходном коде nolearn? Я смущен тем, как сеть знает, как использовать nn
и train_history
без передачи данных в функцию.
Хорошо, я должен предположить, что инициализированный объект затем вызывается где-то в исходном коде для NeuralNet с соответствующими аргументами? Мне кажется странным способом реализовать эту функцию. Почему бы просто не передать функцию? –