损失函数的使用
损失函数(或称目标函数、优化评分函数)是编译模型时所需的两个参数之一:
model.compile(loss='mean_squared_error', optimizer='sgd')
from keras import losses
model.compile(loss=losses.mean_squared_error, optimizer='sgd')
你可以传递一个现有的损失函数名,或者一个 TensorFlow/Theano 符号函数。 该符号函数为每个数据点返回一个标量,有以下两个参数:
- y_true: 真实标签。TensorFlow/Theano 张量。
- y_pred: 预测值。TensorFlow/Theano 张量,其 shape 与 y_true 相同。
实际的优化目标是所有数据点的输出数组的平均值。
有关这些函数的几个例子,请查看 losses source。
可用损失函数
mean_squared_error
mean_squared_error(y_true, y_pred)
mean_absolute_error
mean_absolute_error(y_true, y_pred)
mean_absolute_percentage_error
mean_absolute_percentage_error(y_true, y_pred)
mean_squared_logarithmic_error
mean_squared_logarithmic_error(y_true, y_pred)
squared_hinge
squared_hinge(y_true, y_pred)
hinge
hinge(y_true, y_pred)
categorical_hinge
categorical_hinge(y_true, y_pred)
logcosh
logcosh(y_true, y_pred)
预测误差的双曲余弦的对数。
对于小的 x
,log(cosh(x))
近似等于 (x ** 2) / 2
。对于大的 x
,近似于 abs(x) - log(2)
。这表示 ‘logcosh’ 与均方误差大致相同,但是不会受到偶尔疯狂的错误预测的强烈影响。
参数
- y_true: 目标真实值的张量。
- y_pred: 目标预测值的张量。
返回
每个样本都有一个标量损失的张量。
categorical_crossentropy
categorical_crossentropy(y_true, y_pred)
sparse_categorical_crossentropy
sparse_categorical_crossentropy(y_true, y_pred)
binary_crossentropy
binary_crossentropy(y_true, y_pred)
kullback_leibler_divergence
kullback_leibler_divergence(y_true, y_pred)
poisson
poisson(y_true, y_pred)
cosine_proximity
cosine_proximity(y_true, y_pred)
注意: 当使用 categorical_crossentropy
损失时,你的目标值应该是分类格式 (即,如果你有 10 个类,每个样本的目标值应该是一个 10 维的向量,这个向量除了表示类别的那个索引为 1,其他均为 0)。 为了将 整数目标值 转换为 分类目标值,你可以使用 Keras 实用函数 to_categorical
:
from keras.utils.np_utils import to_categorical
categorical_labels = to_categorical(int_labels, num_classes=None)
优化器的用法
优化器 (optimizer) 是编译 Keras 模型的所需的两个参数之一:
from keras import optimizers
model = Sequential()
model.add(Dense(64, kernel_initializer='uniform', input_shape=(10,)))
model.add(Activation('softmax'))
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
你可以先实例化一个优化器对象,然后将它传入 model.compile()
,像上述示例中一样, 或者你可以通过名称来调用优化器。在后一种情况下,将使用优化器的默认参数。
# 传入优化器名称: 默认参数将被采用
model.compile(loss='mean_squared_error', optimizer='sgd')
Keras 优化器的公共参数
参数 clipnorm
和 clipvalue
能在所有的优化器中使用,用于控制梯度裁剪(Gradient Clipping):
from keras import optimizers
# 所有参数梯度将被裁剪,让其l2范数最大为1:g * 1 / max(1, l2_norm)
sgd = optimizers.SGD(lr=0.01, clipnorm=1.)
from keras import optimizers
# 所有参数d 梯度将被裁剪到数值范围内:
# 最大值0.5
# 最小值-0.5
sgd = optimizers.SGD(lr=0.01, clipvalue=0.5)
SGD
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
随机梯度下降优化器。
包含扩展功能的支持: - 动量(momentum)优化, - 学习率衰减(每次参数更新后) - Nestrov 动量 (NAG) 优化
参数
- lr: float >= 0. 学习率。
- momentum: float >= 0. 参数,用于加速 SGD 在相关方向上前进,并抑制震荡。
- decay: float >= 0. 每次参数更新后学习率衰减值。
- nesterov: boolean. 是否使用 Nesterov 动量。
RMSprop
keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)
RMSProp 优化器.
建议使用优化器的默认参数 (除了学习率 lr,它可以被自由调节)
这个优化器通常是训练循环神经网络RNN的不错选择。
参数
- lr: float >= 0. 学习率。
- rho: float >= 0. RMSProp梯度平方的移动均值的衰减率.
- epsilon: float >= 0. 模糊因子. 若为
None
, 默认为K.epsilon()
。 - decay: float >= 0. 每次参数更新后学习率衰减值。
Adagrad
keras.optimizers.Adagrad(lr=0.01, epsilon=None, decay=0.0)
Adagrad 优化器。
Adagrad 是一种具有特定参数学习率的优化器,它根据参数在训练期间的更新频率进行自适应调整。参数接收的更新越多,更新越小。
建议使用优化器的默认参数。
参数
- lr: float >= 0. 学习率.
- epsilon: float >= 0. 若为
None
, 默认为K.epsilon()
. - decay: float >= 0. 每次参数更新后学习率衰减值.
参考文献
Adadelta
keras.optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=None, decay=0.0)
Adadelta 优化器。
Adadelta 是 Adagrad 的一个具有更强鲁棒性的的扩展版本,它不是累积所有过去的梯度,而是根据渐变更新的移动窗口调整学习速率。 这样,即使进行了许多更新,Adadelta 仍在继续学习。 与 Adagrad 相比,在 Adadelta 的原始版本中,您无需设置初始学习率。 在此版本中,与大多数其他 Keras 优化器一样,可以设置初始学习速率和衰减因子。
建议使用优化器的默认参数。
参数
- lr: float >= 0. 学习率,建议保留默认值。
- rho: float >= 0. Adadelta梯度平方移动均值的衰减率。
- epsilon: float >= 0. 模糊因子. 若为
None
, 默认为K.epsilon()
。 - decay: float >= 0. 每次参数更新后学习率衰减值。
参考文献
Adam
keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
Adam 优化器。
默认参数遵循原论文中提供的值。
参数
- lr: float >= 0. 学习率。
- beta_1: float, 0 < beta < 1. 通常接近于 1。
- beta_2: float, 0 < beta < 1. 通常接近于 1。
- epsilon: float >= 0. 模糊因子. 若为
None
, 默认为K.epsilon()
。 - decay: float >= 0. 每次参数更新后学习率衰减值。
- amsgrad: boolean. 是否应用此算法的 AMSGrad 变种,来自论文 “On the Convergence of Adam and Beyond”。
评价函数的用法
评价函数用于评估当前训练模型的性能。当模型编译后(compile),评价函数应该作为 metrics
的参数来输入。
model.compile(loss='mean_squared_error',
optimizer='sgd',
metrics=['mae', 'acc'])
from keras import metrics
model.compile(loss='mean_squared_error',
optimizer='sgd',
metrics=[metrics.mae, metrics.categorical_accuracy])
评价函数和 损失函数 相似,只不过评价函数的结果不会用于训练过程中。
我们可以传递已有的评价函数名称,或者传递一个自定义的 Theano/TensorFlow 函数来使用(查阅自定义评价函数)。
参数
- y_true: 真实标签,Theano/Tensorflow 张量。
- y_pred: 预测值。和 y_true 相同尺寸的 Theano/TensorFlow 张量。
返回值
返回一个表示全部数据点平均值的张量。
可使用的评价函数
binary_accuracy
binary_accuracy(y_true, y_pred)
categorical_accuracy
categorical_accuracy(y_true, y_pred)
sparse_categorical_accuracy
sparse_categorical_accuracy(y_true, y_pred)
top_k_categorical_accuracy
top_k_categorical_accuracy(y_true, y_pred, k=5)
sparse_top_k_categorical_accuracy
sparse_top_k_categorical_accuracy(y_true, y_pred, k=5)
自定义评价函数
自定义评价函数应该在编译的时候(compile)传递进去。该函数需要以 (y_true, y_pred)
作为输入参数,并返回一个张量作为输出结果。
import keras.backend as K
def mean_pred(y_true, y_pred):
return K.mean(y_pred)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy', mean_pred])
激活函数的用法
激活函数可以通过设置单独的激活层实现,也可以在构造层对象时通过传递 activation
参数实现:
from keras.layers import Activation, Dense
model.add(Dense(64))
model.add(Activation('tanh'))
等价于:
model.add(Dense(64, activation='tanh'))
你也可以通过传递一个逐元素运算的 Theano/TensorFlow/CNTK 函数来作为激活函数:
from keras import backend as K
model.add(Dense(64, activation=K.tanh))
model.add(Activation(K.tanh))
预定义激活函数
softmax
keras.activations.softmax(x, axis=-1)
Softmax 激活函数。
参数
- x:张量。
- axis:整数,代表softmax所作用的维度。
返回
softmax 变换后的张量。
异常
- ValueError:如果
dim(x) == 1
。
elu
keras.activations.elu(x, alpha=1.0)
指数线性单元。
参数
- x:张量。
- alpha:一个标量,表示负数部分的斜率。
返回
线性指数激活:如果 x > 0
,返回值为 x
;如果 x < 0
返回值为 alpha * (exp(x)-1)
selu
keras.activations.selu(x)
可伸缩的指数线性单元(SELU)。
SELU 等同于:scale * elu(x, alpha)
,其中 alpha 和 scale 是预定义的常量。只要正确初始化权重(参见 lecun_normal
初始化方法)并且输入的数量「足够大」(参见参考文献获得更多信息),选择合适的 alpha 和 scale 的值,就可以在两个连续层之间保留输入的均值和方差。
参数
- x: 一个用来用于计算激活函数的张量或变量。
返回
可伸缩的指数线性激活:scale * elu(x, alpha)
。
注意
- 与「lecun_normal」初始化方法一起使用。
- 与 dropout 的变种「AlphaDropout」一起使用。
回调函数使用
回调函数是一个函数的合集,会在训练的阶段中所使用。你可以使用回调函数来查看训练模型的内在状态和统计。你可以传递一个列表的回调函数(作为 callbacks
关键字参数)到 Sequential
或 Model
类型的 .fit()
方法。在训练时,相应的回调函数的方法就会被在各自的阶段被调用。
Callback
keras.callbacks.Callback()
用来组建新的回调函数的抽象基类。
属性
- params: 字典。训练参数, (例如,verbosity, batch size, number of epochs…)。
- model:
keras.models.Model
的实例。 指代被训练模型。
被回调函数作为参数的 logs
字典,它会含有于当前批量或训练轮相关数据的键。
目前,Sequential
模型类的 .fit()
方法会在传入到回调函数的 logs
里面包含以下的数据:
- on_epoch_end: 包括
acc
和loss
的日志, 也可以选择性的包括val_loss
(如果在fit
中启用验证),和val_acc
(如果启用验证和监测精确值)。 - on_batch_begin: 包括
size
的日志,在当前批量内的样本数量。 - on_batch_end: 包括
loss
的日志,也可以选择性的包括acc
(如果启用监测精确值)。
BaseLogger
keras.callbacks.BaseLogger(stateful_metrics=None)
会积累训练轮平均评估的回调函数。
这个回调函数被自动应用到每一个 Keras 模型上面。
参数
stateful_metrics: 可重复使用不应在一个 epoch 上平均的指标的字符串名称。 此列表中的度量标准将按原样记录在 on_epoch_end
中。 所有其他指标将在 on_epoch_end
中取平均值。
TerminateOnNaN
keras.callbacks.TerminateOnNaN()
当遇到 NaN 损失会停止训练的回调函数。
ProgbarLogger
keras.callbacks.ProgbarLogger(count_mode='samples', stateful_metrics=None)
会把评估以标准输出打印的回调函数。
参数
- count_mode: “steps” 或者 “samples”。 进度条是否应该计数看见的样本或步骤(批量)。 stateful_metrics: 可重复使用不应在一个 epoch 上平均的指标的字符串名称。 此列表中的度量标准将按原样记录在
on_epoch_end
中。 所有其他指标将在on_epoch_end
中取平均值。
异常
- ValueError: 如果
count_mode
History
keras.callbacks.History()
把所有事件都记录到 History
对象的回调函数。
这个回调函数被自动启用到每一个 Keras 模型。History
对象会被模型的 fit
方法返回。
ModelCheckpoint
keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)
在每个训练期之后保存模型。
filepath
可以包括命名格式选项,可以由 epoch
的值和 logs
的键(由 on_epoch_end
参数传递)来填充。
例如:如果 filepath
是 weights.{epoch:02d}-{val_loss:.2f}.hdf5
, 那么模型被保存的的文件名就会有训练轮数和验证损失。
参数
- filepath: 字符串,保存模型的路径。
- monitor: 被监测的数据。
- verbose: 详细信息模式,0 或者 1 。
- save_best_only: 如果
save_best_only=True
, 被监测数据的最佳模型就不会被覆盖。 - mode: {auto, min, max} 的其中之一。 如果
save_best_only=True
,那么是否覆盖保存文件的决定就取决于被监测数据的最大或者最小值。 对于val_acc
,模式就会是max
,而对于val_loss
,模式就需要是min
,等等。 在auto
模式中,方向会自动从被监测的数据的名字中判断出来。 - save_weights_only: 如果 True,那么只有模型的权重会被保存 (
model.save_weights(filepath)
), 否则的话,整个模型会被保存 (model.save(filepath)
)。 - period: 每个检查点之间的间隔(训练轮数)。
EarlyStopping
keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=0, verbose=0, mode='auto', baseline=None, restore_best_weights=False)
当被监测的数量不再提升,则停止训练。
参数
- monitor: 被监测的数据。
- min_delta: 在被监测的数据中被认为是提升的最小变化, 例如,小于 min_delta 的绝对变化会被认为没有提升。
- patience: 没有进步的训练轮数,在这之后训练就会被停止。
- verbose: 详细信息模式。
- mode: {auto, min, max} 其中之一。 在
min
模式中, 当被监测的数据停止下降,训练就会停止;在max
模式中,当被监测的数据停止上升,训练就会停止;在auto
模式中,方向会自动从被监测的数据的名字中判断出来。 - baseline: 要监控的数量的基准值。 如果模型没有显示基准的改善,训练将停止。
- restore_best_weights: 是否从具有监测数量的最佳值的时期恢复模型权重。 如果为 False,则使用在训练的最后一步获得的模型权重。
RemoteMonitor
keras.callbacks.RemoteMonitor(root='http://localhost:9000', path='/publish/epoch/end/', field='data', headers=None, send_as_json=False)
将事件数据流到服务器的回调函数。
需要 requests
库。 事件被默认发送到 root + '/publish/epoch/end/'
。 采用 HTTP POST ,其中的 data
参数是以 JSON 编码的事件数据字典。 如果 send_as_json 设置为 True,请求的 content type 是 application/json。否则,将在表单中发送序列化的 JSON。
参数
- root: 字符串;目标服务器的根地址。
- path: 字符串;相对于
root
的路径,事件数据被送达的地址。 - field: 字符串;JSON ,数据被保存的领域。
- headers: 字典;可选自定义的 HTTP 的头字段。
- send_as_json: 布尔值;请求是否应该以 application/json 格式发送。
LearningRateScheduler
keras.callbacks.LearningRateScheduler(schedule, verbose=0)
学习速率定时器。
参数
- schedule: 一个函数,接受轮索引数作为输入(整数,从 0 开始迭代) 然后返回一个学习速率作为输出(浮点数)。
- verbose: 整数。 0:安静,1:更新信息。
TensorBoard
keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, batch_size=32, write_graph=True, write_grads=False, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None, embeddings_data=None, update_freq='epoch')
Tensorboard 基本可视化。
TensorBoard 是由 Tensorflow 提供的一个可视化工具。
这个回调函数为 Tensorboard 编写一个日志, 这样你可以可视化测试和训练的标准评估的动态图像, 也可以可视化模型中不同层的激活值直方图。
如果你已经使用 pip 安装了 Tensorflow,你应该可以从命令行启动 Tensorflow:
tensorboard --logdir=/full_path_to_your_logs
参数
- log_dir: 用来保存被 TensorBoard 分析的日志文件的文件名。
- histogram_freq: 对于模型中各个层计算激活值和模型权重直方图的频率(训练轮数中)。 如果设置成 0 ,直方图不会被计算。对于直方图可视化的验证数据(或分离数据)一定要明确的指出。
- write_graph: 是否在 TensorBoard 中可视化图像。 如果 write_graph 被设置为 True,日志文件会变得非常大。
- write_grads: 是否在 TensorBoard 中可视化梯度值直方图。
histogram_freq
必须要大于 0 。 - batch_size: 用以直方图计算的传入神经元网络输入批的大小。
- write_images: 是否在 TensorBoard 中将模型权重以图片可视化。
- embeddings_freq: 被选中的嵌入层会被保存的频率(在训练轮中)。
- embeddings_layer_names: 一个列表,会被监测层的名字。 如果是 None 或空列表,那么所有的嵌入层都会被监测。
- embeddings_metadata: 一个字典,对应层的名字到保存有这个嵌入层元数据文件的名字。 查看 详情 关于元数据的数据格式。 以防同样的元数据被用于所用的嵌入层,字符串可以被传入。
- embeddings_data: 要嵌入在
embeddings_layer_names
指定的层的数据。 Numpy 数组(如果模型有单个输入)或 Numpy 数组列表(如果模型有多个输入)。 Learn ore about embeddings。 - update_freq:
'batch'
或'epoch'
或 整数。当使用'batch'
时,在每个 batch 之后将损失和评估值写入到 TensorBoard 中。同样的情况应用到'epoch'
中。如果使用整数,例如10000
,这个回调会在每 10000 个样本之后将损失和评估值写入到 TensorBoard 中。注意,频繁地写入到 TensorBoard 会减缓你的训练。
ReduceLROnPlateau
keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', min_delta=0.0001, cooldown=0, min_lr=0)
当标准评估停止提升时,降低学习速率。
当学习停止时,模型总是会受益于降低 2-10 倍的学习速率。 这个回调函数监测一个数据并且当这个数据在一定「有耐心」的训练轮之后还没有进步, 那么学习速率就会被降低。
例子
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,
patience=5, min_lr=0.001)
model.fit(X_train, Y_train, callbacks=[reduce_lr])
参数
- monitor: 被监测的数据。
- factor: 学习速率被降低的因数。新的学习速率 = 学习速率 * 因数
- patience: 没有进步的训练轮数,在这之后训练速率会被降低。
- verbose: 整数。0:安静,1:更新信息。
- mode: {auto, min, max} 其中之一。如果是
min
模式,学习速率会被降低如果被监测的数据已经停止下降; 在max
模式,学习塑料会被降低如果被监测的数据已经停止上升; 在auto
模式,方向会被从被监测的数据中自动推断出来。 - min_delta: 对于测量新的最优化的阀值,只关注巨大的改变。
- cooldown: 在学习速率被降低之后,重新恢复正常操作之前等待的训练轮数量。
- min_lr: 学习速率的下边界。
CSVLogger
keras.callbacks.CSVLogger(filename, separator=',', append=False)
把训练轮结果数据流到 csv 文件的回调函数。
支持所有可以被作为字符串表示的值,包括 1D 可迭代数据,例如,np.ndarray。
例子
csv_logger = CSVLogger('training.log')
model.fit(X_train, Y_train, callbacks=[csv_logger])
参数
- filename: csv 文件的文件名,例如 ‘run/log.csv’。
- separator: 用来隔离 csv 文件中元素的字符串。
- append: True:如果文件存在则增加(可以被用于继续训练)。False:覆盖存在的文件。
LambdaCallback
keras.callbacks.LambdaCallback(on_epoch_begin=None, on_epoch_end=None, on_batch_begin=None, on_batch_end=None, on_train_begin=None, on_train_end=None)
在训练进行中创建简单,自定义的回调函数的回调函数。
这个回调函数和匿名函数在合适的时间被创建。 需要注意的是回调函数要求位置型参数,如下:
on_epoch_begin
和on_epoch_end
要求两个位置型的参数:epoch
,logs
on_batch_begin
和on_batch_end
要求两个位置型的参数:batch
,logs
on_train_begin
和on_train_end
要求一个位置型的参数:logs
参数
- on_epoch_begin: 在每轮开始时被调用。
- on_epoch_end: 在每轮结束时被调用。
- on_batch_begin: 在每批开始时被调用。
- on_batch_end: 在每批结束时被调用。
- on_train_begin: 在模型训练开始时被调用。
- on_train_end: 在模型训练结束时被调用。
例子
# 在每一个批开始时,打印出批数。
batch_print_callback = LambdaCallback(
on_batch_begin=lambda batch,logs: print(batch))
# 把训练轮损失数据流到 JSON 格式的文件。文件的内容
# 不是完美的 JSON 格式,但是时每一行都是 JSON 对象。
import json
json_log = open('loss_log.json', mode='wt', buffering=1)
json_logging_callback = LambdaCallback(
on_epoch_end=lambda epoch, logs: json_log.write(
json.dumps({'epoch': epoch, 'loss': logs['loss']}) + '\n'),
on_train_end=lambda logs: json_log.close()
)
# 在完成模型训练之后,结束一些进程。
processes = ...
cleanup_callback = LambdaCallback(
on_train_end=lambda logs: [
p.terminate() for p in processes if p.is_alive()])
model.fit(...,
callbacks=[batch_print_callback,
json_logging_callback,
cleanup_callback])
创建一个回调函数
你可以通过扩展 keras.callbacks.Callback
基类来创建一个自定义的回调函数。 通过类的属性 self.model
,回调函数可以获得它所联系的模型。
下面是一个简单的例子,在训练时,保存一个列表的批量损失值:
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.losses = []
def on_batch_end(self, batch, logs={}):
self.losses.append(logs.get('loss'))
例: 记录损失历史
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.losses = []
def on_batch_end(self, batch, logs={}):
self.losses.append(logs.get('loss'))
model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
history = LossHistory()
model.fit(x_train, y_train, batch_size=128, epochs=20, verbose=0, callbacks=[history])
print(history.losses)
# 输出
'''
[0.66047596406559383, 0.3547245744908703, ..., 0.25953155204159617, 0.25901699725311789]
'''
例: 模型检查点
from keras.callbacks import ModelCheckpoint
model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
'''
如果验证损失下降, 那么在每个训练轮之后保存模型。
'''
checkpointer = ModelCheckpoint(filepath='/tmp/weights.hdf5', verbose=1, save_best_only=True)
model.fit(x_train, y_train, batch_size=128, epochs=20, verbose=0, validation_data=(X_test, Y_test), callbacks=[checkpointer])