keras 自定义loss损失函数,sample在loss上的加权和metric详解


Posted in Python onMay 23, 2020

首先辨析一下概念:

1. loss是整体网络进行优化的目标, 是需要参与到优化运算,更新权值W的过程的

2. metric只是作为评价网络表现的一种“指标”, 比如accuracy,是为了直观地了解算法的效果,充当view的作用,并不参与到优化过程

在keras中实现自定义loss, 可以有两种方式,一种自定义 loss function,

例如:

# 方式一
def vae_loss(x, x_decoded_mean):
 xent_loss = objectives.binary_crossentropy(x, x_decoded_mean)
 kl_loss = - 0.5 * K.mean(1 + z_log_sigma - K.square(z_mean) - K.exp(z_log_sigma), axis=-1)
 return xent_loss + kl_loss
 
vae.compile(optimizer='rmsprop', loss=vae_loss)

或者通过自定义一个keras的层(layer)来达到目的, 作为model的最后一层,最后令model.compile中的loss=None:

# 方式二
# Custom loss layer
class CustomVariationalLayer(Layer):
 def __init__(self, **kwargs):
  self.is_placeholder = True
  super(CustomVariationalLayer, self).__init__(**kwargs)
 
 def vae_loss(self, x, x_decoded_mean_squash):
  x = K.flatten(x)
  x_decoded_mean_squash = K.flatten(x_decoded_mean_squash)
  xent_loss = img_rows * img_cols * metrics.binary_crossentropy(x, x_decoded_mean_squash)
  kl_loss = - 0.5 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
  return K.mean(xent_loss + kl_loss)
 
 def call(self, inputs):
  x = inputs[0]
  x_decoded_mean_squash = inputs[1]
  loss = self.vae_loss(x, x_decoded_mean_squash)
  self.add_loss(loss, inputs=inputs)
  # We don't use this output.
  return x
 
y = CustomVariationalLayer()([x, x_decoded_mean_squash])
vae = Model(x, y)
vae.compile(optimizer='rmsprop', loss=None)

在keras中自定义metric非常简单,需要用y_pred和y_true作为自定义metric函数的输入参数 点击查看metric的设置

注意事项:

1. keras中定义loss,返回的是batch_size长度的tensor, 而不是像tensorflow中那样是一个scalar

2. 为了能够将自定义的loss保存到model, 以及可以之后能够顺利load model, 需要把自定义的loss拷贝到keras.losses.py 源代码文件下,否则运行时找不到相关信息,keras会报错

有时需要不同的sample的loss施加不同的权重,这时需要用到sample_weight,例如

# Class weights:
  # To balance the difference in occurences of digit class labels. 
  # 50% of labels that the discriminator trains on are 'fake'.
  # Weight = 1 / frequency
  cw1 = {0: 1, 1: 1}
  cw2 = {i: self.num_classes / half_batch for i in range(self.num_classes)}
  cw2[self.num_classes] = 1 / half_batch
  class_weights = [cw1, cw2] # 使得两种loss能够一样重要

discriminator.train_on_batch(imgs, [valid, labels], class_weight=class_weights)

补充知识:keras模型训练与保存的call_back的设置

1、模型训练

fit(x=None, 
y=None, 
batch_size=None, 
epochs=1, 
verbose=1, 
callbacks=None, 
validation_split=0.0, 
validation_data=None, 
shuffle=True, 
class_weight=None, 
sample_weight=None, 
initial_epoch=0, 
steps_per_epoch=None, 
validation_steps=None)

参数:

x: 训练数据的 Numpy 数组(如果模型只有一个输入), 或者是 Numpy 数组的列表(如果模型有多个输入)。 如果模型中的输入层被命名,你也可以传递一个字典,将输入层名称映射到 Numpy 数组。 如果从本地框架张量馈送(例如 TensorFlow 数据张量)数据,x 可以是 None(默认)。

y: 目标(标签)数据的 Numpy 数组(如果模型只有一个输出), 或者是 Numpy 数组的列表(如果模型有多个输出)。 如果模型中的输出层被命名,你也可以传递一个字典,将输出层名称映射到 Numpy 数组。 如果从本地框架张量馈送(例如 TensorFlow 数据张量)数据,y 可以是 None(默认)。

batch_size: 整数或 None。每次梯度更新的样本数。如果未指定,默认为 32。

epochs: 整数。训练模型迭代轮次。一个轮次是在整个 x 和 y 上的一轮迭代。 请注意,与 initial_epoch 一起,epochs 被理解为 「最终轮次」。模型并不是训练了 epochs 轮,而是到第 epochs 轮停止训练。

verbose: 0, 1 或 2。日志显示模式。 0 = 安静模式, 1 = 进度条, 2 = 每轮一行。

callbacks: 一系列的 keras.callbacks.Callback 实例。一系列可以在训练时使用的回调函数。

validation_split: 0 和 1 之间的浮点数。用作验证集的训练数据的比例。 模型将分出一部分不会被训练的验证数据,并将在每一轮结束时评估这些验证数据的误差和任何其他模型指标。 验证数据是混洗之前 x 和y 数据的最后一部分样本中。

validation_data: 元组 (x_val,y_val) 或元组 (x_val,y_val,val_sample_weights), 用来评估损失,以及在每轮结束时的任何模型度量指标。 模型将不会在这个数据上进行训练。这个参数会覆盖 validation_split。

shuffle: 布尔值(是否在每轮迭代之前混洗数据)或者 字符串 (batch)。 batch 是处理 HDF5 数据限制的特殊选项,它对一个 batch 内部的数据进行混洗。 当 steps_per_epoch 非 None 时,这个参数无效。

class_weight: 可选的字典,用来映射类索引(整数)到权重(浮点)值,用于加权损失函数(仅在训练期间)。 这可能有助于告诉模型 「更多关注」来自代表性不足的类的样本。

sample_weight: 训练样本的可选 Numpy 权重数组,用于对损失函数进行加权(仅在训练期间)。 您可以传递与输入样本长度相同的平坦(1D)Numpy 数组(权重和样本之间的 1:1 映射), 或者在时序数据的情况下,可以传递尺寸为 (samples, sequence_length) 的 2D 数组,以对每个样本的每个时间步施加不同的权重。 在这种情况下,你应该确保在 compile() 中指定 sample_weight_mode="temporal"。

initial_epoch: 整数。开始训练的轮次(有助于恢复之前的训练)。

steps_per_epoch: 整数或 None。 在声明一个轮次完成并开始下一个轮次之前的总步数(样品批次)。 使用 TensorFlow 数据张量等输入张量进行训练时,默认值 None 等于数据集中样本的数量除以 batch 的大小,如果无法确定,则为 1。

validation_steps: 只有在指定了 steps_per_epoch 时才有用。停止前要验证的总步数(批次样本)

fit_generator(generator, 
steps_per_epoch=None, 
epochs=1, 
verbose=1, 
callbacks=None, 
validation_data=None, 
validation_steps=None, 
class_weight=None, 
max_queue_size=10, 
workers=1, 
use_multiprocessing=False, 
shuffle=True, 
initial_epoch=0)

使用 Python 生成器(或 Sequence 实例)逐批生成的数据,按批次训练模型

参数

generator: 一个生成器,或者一个 Sequence (keras.utils.Sequence) 对象的实例, 以在使用多进程时避免数据的重复。 生成器的输出应该为以下之一:

一个 (inputs, targets) 元组

一个 (inputs, targets, sample_weights) 元组。

这个元组(生成器的单个输出)组成了单个的 batch。 因此,这个元组中的所有数组长度必须相同(与这一个 batch 的大小相等)。 不同的 batch 可能大小不同。 例如,一个 epoch 的最后一个 batch 往往比其他 batch 要小, 如果数据集的尺寸不能被 batch size 整除。 生成器将无限地在数据集上循环。当运行到第 steps_per_epoch 时,记一个 epoch 结束。

steps_per_epoch: 在声明一个 epoch 完成并开始下一个 epoch 之前从 generator 产生的总步数(批次样本)。 它通常应该等于你的数据集的样本数量除以批量大小。 对于 Sequence,它是可选的:如果未指定,将使用len(generator) 作为步数。

epochs: 整数。训练模型的迭代总轮数。一个 epoch 是对所提供的整个数据的一轮迭代,如 steps_per_epoch 所定义。注意,与 initial_epoch 一起使用,epoch 应被理解为「最后一轮」。模型没有经历由 epochs 给出的多次迭代的训练,而仅仅是直到达到索引 epoch 的轮次。

verbose: 0, 1 或 2。日志显示模式。 0 = 安静模式, 1 = 进度条, 2 = 每轮一行。

callbacks: keras.callbacks.Callback 实例的列表。在训练时调用的一系列回调函数。

validation_data: 它可以是以下之一:

验证数据的生成器或 Sequence 实例

一个 (inputs, targets) 元组

一个 (inputs, targets, sample_weights) 元组。

在每个 epoch 结束时评估损失和任何模型指标。该模型不会对此数据进行训练。

validation_steps: 仅当 validation_data 是一个生成器时才可用。 在停止前 generator 生成的总步数(样本批数)。 对于 Sequence,它是可选的:如果未指定,将使用 len(generator) 作为步数。

class_weight: 可选的将类索引(整数)映射到权重(浮点)值的字典,用于加权损失函数(仅在训练期间)。 这可以用来告诉模型「更多地关注」来自代表性不足的类的样本。

max_queue_size: 整数。生成器队列的最大尺寸。 如未指定,max_queue_size 将默认为 10。

workers: 整数。使用的最大进程数量,如果使用基于进程的多线程。 如未指定,workers 将默认为 1。如果为 0,将在主线程上执行生成器。

use_multiprocessing: 布尔值。如果 True,则使用基于进程的多线程。 如未指定, use_multiprocessing 将默认为 False。 请注意,由于此实现依赖于多进程,所以不应将不可传递的参数传递给生成器,因为它们不能被轻易地传递给子进程。

shuffle: 是否在每轮迭代之前打乱 batch 的顺序。 只能与 Sequence (keras.utils.Sequence) 实例同用。

initial_epoch: 开始训练的轮次(有助于恢复之前的训练)

fit与fit_generator函数都返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况,可以写入文本后续查看

2、保存模型结构、训练出来的权重、及优化器状态

keras.callbacks.ModelCheckpoint(filepath,
 monitor='val_loss', 
verbose=0, 
save_best_only=False, 
save_weights_only=False, 
mode='auto', 
period=1)

在每个训练期之后保存模型

参数:

filepath: 字符串,保存模型的路径。如 epoch1.h5 或者 epoch1.weight(save_weights_only=True)

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: 每个检查点之间的间隔(训练轮数)

例子:

checkpoint = ModelCheckpoint(filepath=model_weight_filepath, monitor='val_acc',
         verbose=0, save_best_only=True, save_weights_only=True, mode='max', period=1)
model.fit(X_train, Y_train, callbacks=[checkpoint])

3、当验证损失不再继续降低时,如何中断训练?当监测值不再改善时中止训练

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: 详细信息模式,0或1。

mode: {auto, min, max} 其中之一。 在 min 模式中, 当被监测的数据停止下降,训练就会停止;在 max 模式中,当被监测的数据停止上升,训练就会停止;在 auto 模式中,方向会自动从被监测的数据的名字中判断出来。

baseline: 要监控的数量的基准值。 如果模型没有显示基准的改善,训练将停止。

restore_best_weights: 是否从具有监测数量的最佳值的时期恢复模型权重。 如果为 False,则使用在训练的最后一步获得的模型权重。

例子:

earlystopping = EarlyStopping(monitor='val_acc', verbose=1, patience=3)

model.fit(X_train, Y_train, callbacks=[earlystopping])

4、学习率动态调整

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 倍的学习速率。 这个回调函数监测一个数据并且当这个数据在一定「有耐心」的训练轮之后还没有进步, 那么学习速率就会被降低。

参数

monitor: 被监测的数据。

factor: 学习速率被降低的因数。新的学习速率 = 学习速率 * 因数

patience: 没有进步的训练轮数,在这之后训练速率会被降低。

verbose: 整数。0:安静,1:更新信息。

mode: {auto, min, max} 其中之一。如果是 min 模式,学习速率会被降低如果被监测的数据已经停止下降; 在 max 模式,学习塑料会被降低如果被监测的数据已经停止上升; 在 auto 模式,方向会被从被监测的数据中自动推断出来。

min_delta: 对于测量新的最优化的阀值,只关注巨大的改变。

cooldown: 在学习速率被降低之后,重新恢复正常操作之前等待的训练轮数量。

min_lr: 学习速率的下边界。

例子:

reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,
        patience=5, min_lr=0.001)
model.fit(X_train, Y_train, callbacks=[reduce_lr])

4、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 编写一个日志, 这样你可以可视化测试和训练的标准评估的动态图像, 也可以可视化模型中不同层的激活值直方图。

如果你已经使用 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 会减缓你的训练。

5、如何记录每一次epoch的训练/验证损失/准确度?

Model.fit函数会返回一个 History 回调,该回调有一个属性history包含一个封装有连续损失/准确的lists。

代码如下:

hist = model.fit(X, y,validation_split=0.2)

print(hist.history)

Keras输出的loss,val这些值如何保存到文本中去

Keras中的fit函数会返回一个History对象,它的History.history属性会把之前的那些值全保存在里面,如果有验证集的话,也包含了验证集的这些指标变化情况,具体写法:

hist=model.fit(train_set_x,train_set_y,batch_size=256,shuffle=True,nb_epoch=nb_epoch,validation_split=0.1)
with open('log_sgd_big_32.txt','w') as f:
 f.write(str(hist.history))

6、多个回调函数用逗号隔开

例如:

model_weight_filepath = "./bert_classfition-test_model" + str(i) + ".weight"
earlystopping = EarlyStopping(monitor='val_acc', verbose=1, patience=3)
reducelronplateau = ReduceLROnPlateau(monitor="val_acc", verbose=1, mode='max', factor=0.5, patience=2)
checkpoint = ModelCheckpoint(filepath=model_weight_filepath, monitor='val_acc',
        verbose=0, save_best_only=True, save_weights_only=True, mode='max', period=1)
model.fit_generator(
 train_D.__iter__(),
 steps_per_epoch=len(train_D),
 epochs=epochs,
 validation_data=valid_D.__iter__(),
 validation_steps=len(valid_D),
 callbacks=[earlystopping, reducelronplateau, checkpoint])

以上这篇keras 自定义loss损失函数,sample在loss上的加权和metric详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现多线程暴力破解登陆路由器功能代码分享
Jan 04 Python
python在windows命令行下输出彩色文字的方法
Mar 19 Python
Python bsddb模块操作Berkeley DB数据库介绍
Apr 08 Python
Python实现一个转存纯真IP数据库的脚本分享
May 21 Python
mysql 之通过配置文件链接数据库
Aug 12 Python
Python编程之微信推送模板消息功能示例
Aug 21 Python
wx.CheckBox创建复选框控件并响应鼠标点击事件
Apr 25 Python
详解Django中间件执行顺序
Jul 16 Python
解决Python下json.loads()中文字符出错的问题
Dec 19 Python
python实现简单图片物体标注工具
Mar 18 Python
python set内置函数的具体使用
Jul 02 Python
5分钟快速掌握Python定时任务框架的实现
Jan 26 Python
keras中模型训练class_weight,sample_weight区别说明
May 23 #Python
浅谈keras中的Merge层(实现层的相加、相减、相乘实例)
May 23 #Python
Keras实现将两个模型连接到一起
May 23 #Python
keras 获取某层输出 获取复用层的多次输出实例
May 23 #Python
给keras层命名,并提取中间层输出值,保存到文档的实例
May 23 #Python
keras小技巧——获取某一个网络层的输出方式
May 23 #Python
keras自定义回调函数查看训练的loss和accuracy方式
May 23 #Python
You might like
不使用php api函数实现数组的交换排序示例
2014/04/13 PHP
PHP用户验证和标签推荐的简单使用
2016/10/31 PHP
Laravel 微信小程序后端搭建步骤详解
2019/11/26 PHP
数组方法解决JS字符串连接性能问题有争议
2011/01/12 Javascript
jquery1.5.1中根据元素ID获取元素对象的代码
2011/04/02 Javascript
关于scrollLeft,scrollTop的浏览器兼容性测试
2013/03/19 Javascript
Node.js与PHP、Python的字符处理性能对比
2014/07/06 Javascript
高性能JavaScript 重排与重绘(2)
2015/08/11 Javascript
javascript实现支持移动设备画廊
2015/08/24 Javascript
原生JavaScript编写canvas版的连连看游戏
2016/05/29 Javascript
详解bootstrap的modal-remote两种加载方式【强化】
2017/01/27 Javascript
Vue.js路由vue-router使用方法详解
2017/03/20 Javascript
Javascript中prototype与__proto__的关系详解
2018/03/11 Javascript
JavaScript继承的特性与实践应用深入详解
2018/12/30 Javascript
微信小程序实现多选删除列表数据功能示例
2019/01/15 Javascript
JavaScript事件冒泡机制原理实例解析
2020/01/14 Javascript
linux服务器快速卸载安装node环境(简单上手)
2021/02/22 Javascript
Python天气预报采集器实现代码(网页爬虫)
2012/10/07 Python
python三元运算符实现方法
2013/12/17 Python
PHP实现发送和接收JSON请求
2018/06/07 Python
python实现批量图片格式转换
2020/06/16 Python
python3实现指定目录下文件sha256及文件大小统计
2019/02/25 Python
教你如何编写、保存与运行Python程序的方法
2019/07/12 Python
python如何变换环境
2020/07/21 Python
使用CSS3的rem属性制作响应式页面布局的要点解析
2016/05/24 HTML / CSS
阿玛尼美妆加拿大官方商城:Giorgio Armani Beauty加拿大
2017/10/24 全球购物
Lyle & Scott苏格兰金鹰官网:英国皇室御用品牌
2018/05/09 全球购物
Sandro法国官网:法国成衣品牌
2019/08/28 全球购物
四年大学生活的个人自我评价
2013/12/11 职场文书
安全保证书范文
2014/04/29 职场文书
小学德育工作经验交流材料
2014/05/22 职场文书
公司副总经理任命书
2014/06/05 职场文书
群众路线教育实践活动对照检查材料
2014/09/22 职场文书
2014年机关工会工作总结
2014/12/19 职场文书
干部年终考核评语
2015/01/04 职场文书
《搭石》教学反思
2016/02/18 职场文书