做者|Andre Ye
编译|VK
来源|Towards Data Sciencepython
回调函数是神经网络训练的重要组成部分安全
回调操做能够在训练的各个阶段执行,多是在epoch之间,在处理一个batch以后,甚至在知足某个条件的状况下。回调能够利用许多创造性的方法来改进训练和性能,节省计算资源,并提供有关神经网络内部发生的事情的结论。网络
本文将详细介绍重要回调的基本原理和代码,以及建立自定义回调的过程。机器学习
ReduceLROnPlateau是Keras中默认包含的回调。神经网络的学习率决定了梯度的比例因子,所以太高的学习率会致使优化器超过最优值,而学习率太低则会致使训练时间过长。很难找到一个静态的、效果很好的、不变的学习率。ide
顾名思义,“下降高原学习率”就是在损失指标中止改善或达到稳定时下降学习率。通常学习率减小2到10倍,这有助于磨练参数的最佳值。函数
要使用ReduceLROnPlateau,必须首先建立回调对象。有四个参数很重要:性能
from keras.callbacks import ReduceLROnPlateau reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=0.001) model.fit(X_train, Y_train, callbacks=[reduce_lr])
当使用model.fit时,能够指定回调参数。注意,这能够接受一个列表,所以能够安排多个回调。学习
LearningRateScheduler是ReduceLROnPlateau的另外一种选择,它容许用户根据epoch来安排学习率。若是你知道(可能来自之前的研究或实验)网络的学习率在从epochs 1-10时应该是x, 在epochs 10-20是应该是y,LearningRateScheduler能够帮助实现这些变化。以上epoch的数字能够任意变化。优化
建立学习率调度器须要一个用户定义的函数,该函数将epoch和learning rate做为参数。返回对象应该是新的学习率。ui
from keras.callbacks import LearningRateScheduler def scheduler(epoch, lr): #定义回调schedule if lr < 0.001: return lr * 1.5 #若是lr过小,增长lr elif epoch < 5: return lr #前五个epoch,不改变lr elif epoch < 10: return lr * tf.math.exp(-0.1) #第五到第十个epoch,减小lr else: return lr * tf.math.exp(-0.05) #第10个epoch以后,减小量更少 callback = LearningRateScheduler(scheduler) #建立回调对象 model.fit(X_train, y_train, epochs=15, callbacks=[callback])
而后,将其转换为Keras回调后,就能够用于模型的训练。这些调度程序很是有用,容许对网络进行控制,但建议在第一次训练网络时使用ReduceLROnPlateau,由于它更具适应性。而后,能够进行可视化模型,看是否能提供关于如何构造一个适当的LR调度器的相关想法。
此外,你能够同时使用ReduceLROnPlateau和LearningRateScheduler,例如,使用调度程序硬编码一些学习速率(例如在前10个epoch不更改),同时利用自适应能力,在高原上下降学习率以提高性能。
EarlyStopping能够很是有助于防止在训练模型时产生额外的冗余运行。冗余运行会致使高昂的计算成本。当网络在给定的时间段内没有获得改善时,网络完成训练并中止使用计算资源。与ReduceLROnPlateau相似,EarlyStopping须要monitor。
from keras.callbacks import EarlyStopping callback = EarlyStopping(monitor='loss', patience=5) model.fit(X_train, y_train, epochs=15, callbacks=[callback])
TerminateOnNaN有助于防止在训练中产生梯度爆炸问题,由于输入NaN会致使网络的其余部分发生爆炸。若是不采用TerminateOnNaN,Keras并不阻止网络的训练。另外,nan会致使对计算能力的需求增长。为了防止这些状况发生,添加TerminateOnNaN是一个很好的安全检查。
rom keras.callbacks import TerminateOnNaN model.fit(X_train, y_train, epochs=15, callbacks = [TerminateOnNaN()])
因为许多缘由,ModelCheckpoint能够以某种频率(也许每隔10个左右的epoch)保存模型的权重,所以它很是有用。
若是训练模型时忽然中断,则不须要彻底从新训练模型。
若是,好比说,在第30个epoch,模型开始显示出过拟合的迹象或其余问题,好比梯度爆炸,咱们能够用最近保存的权重从新加载模型(好比在第25个epoch),并调整参数以免该问题,而无需从新进行大部分训练。
可以提取某个epoch的权重并将其从新加载到另外一个模型中有利于迁移学习。
在下面的场景中,ModelCheckpoint用于存储具备最佳性能的模型的权重。在每一个epoch,若是模型比其余记录的epoch表现更好,则其权重存储在一个文件中(覆盖前一个的权重)。在训练结束时,咱们使用model.load_weights进行加载.
from keras.callbacks import ModelCheckpoint callback = ModelCheckpoint( #建立回调 filepath='/filepath/checkpoint', #告诉回调要存储权重的filepath在哪 save_weights_only=True, #只保留权重(更有效),而不是整个模型 monitor='val_acc', #度量 mode='max', #找出使度量最大化的模型权重 save_best_only=True #只保留最佳模型的权重(更有效),而不是全部的权重 ) model.fit(X_train, y_train, epochs=15, callbacks=[callback]) model.load_weights(checkpoint_filepath) #将最佳权重装入模型中。
或者,若是须要基于频率的保存(每5个epoch保存一次),请将save_freq设置为5
编写自定义回调是Keras包含的最好的特性之一,它容许执行高度特定的操做。可是,请注意,构造它比使用默认回调要复杂得多。
咱们的自定义回调将采用类的形式。相似于在PyTorch中构建神经网络,咱们能够继承keras.callbacks.Callback回调,它是一个基类。
咱们的类能够有许多函数,这些函数必须具备下面列出的给定名称以及这些函数将在什么时候运行。例如,将在每一个epoch开始时运行on_epoch_begin函数。下面是Keras将从自定义回调中读取的全部函数,可是能够添加其余“helper”函数。
class CustomCallback(keras.callbacks.Callback): #继承keras的基类 def on_train_begin(self, logs=None): #日志是某些度量的字典,例如键能够是 ['loss', 'mean_absolute_error'] def on_train_end(self, logs=None): ... def on_epoch_begin(self, epoch, logs=None): ... def on_epoch_end(self, epoch, logs=None): ... def on_test_begin(self, logs=None): ... def on_test_end(self, logs=None): ... def on_predict_begin(self, logs=None): ... def on_predict_end(self, logs=None): ... def on_train_batch_begin(self, batch, logs=None): ... def on_train_batch_end(self, batch, logs=None): ... def on_test_batch_begin(self, batch, logs=None): ... def on_test_batch_end(self, batch, logs=None): ... def on_predict_batch_begin(self, batch, logs=None): ... def on_predict_batch_end(self, batch, logs=None): ...
根据函数的不一样,你能够访问不一样的变量。例如,在函数on_epoch_begin中,该函数既能够访问epoch编号,也能够访问当前度量、日志的字典。若是须要其余信息,好比学习率,可使用keras.backend.get_value.
而后,能够像对待其余回调函数同样对待你自定义的回调函数。
model.fit(X_train, y_train, epochs=15, callbacks=[CustomCallback()])
自定义回调的一些常见想法:
在JSON或CSV文件中记录训练结果。
每10个epoch就经过电子邮件发送训练结果。
在决定什么时候保存模型权重或者添加更复杂的功能。
训练一个简单的机器学习模型(例如使用sklearn),经过将其设置为类变量并以(x: action, y: change)的形式获取数据,来学习什么时候提升或下降学习率。
当在神经网络中使用回调函数时,你的控制力加强,神经网络变得更容易拟合。
欢迎关注磐创AI博客站:
http://panchuang.net/
sklearn机器学习中文官方文档:
http://sklearn123.com/
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/