python训练模型损失值6000多_keras 自定义loss损失函数,sample在loss上的加权和metric详解...

首先辨析一下概念:

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详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题是如何在Keras中定义自定义损失函数并实现样本加权以及使用metrics进行模型评估的详细说明。 首先,我们来介绍一下在Keras中定义自定义损失函数的方法。Keras自带了一些常见的损失函数,例如均方误差(MSE)、交叉熵(cross-entropy)等,但是在实际应用中,我们可能需要根据具体的问题来定义自己的损失函数。 在Keras中,我们可以通过编写一个Python函数来定义自定义损失函数,函数的输入应该是(y_true, y_pred),分别表示真实标签和模型输出的预测,函数的输出应该是一个标量(即损失)。例如,下面是一个计算均方误差的自定义损失函数: ```python import tensorflow as tf from keras import backend as K def custom_mse(y_true, y_pred): return K.mean(K.square(y_true - y_pred)) ``` 接下来,如果您希望对样本进行加权,可以在定义损失函数时使用Keras的API来实现。具体来说,您可以在损失函数中使用Keras的乘法运算符`K.dot`来将每个样本的权重乘以对应的损失,然后再将这些相加。例如,下面是一个计算加权均方误差的自定义损失函数,其中`sample_weight`是一个与`y_true`形状相同的张量,用于指定每个样本的权重: ```python def weighted_mse(y_true, y_pred): # sample_weight shape is (batch_size,) sample_weight = tf.constant([1, 2, 3], dtype=tf.float32) return K.mean(K.square(y_true - y_pred) * sample_weight) ``` 最后,如果您希望使用metrics来评估模型的性能,可以在Keras的`compile`函数中指定一个或多个metrics。Keras提供了许多常见的metrics,例如准确率(accuracy)、平均绝对误差(MAE)等。如果您定义了自己的metrics,可以使用Keras的`Metric`类来实现。例如,下面是一个计算绝对误差百分比的自定义metrics: ```python from keras.metrics import Metric class PercentageError(Metric): def __init__(self, name='percentage_error', **kwargs): super(PercentageError, self).__init__(name=name, **kwargs) self.total_error = self.add_weight(name='total_error', initializer='zeros') self.total_count = self.add_weight(name='total_count', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): abs_error = K.abs(y_true - y_pred) percentage_error = abs_error / K.clip(K.abs(y_true), K.epsilon(), None) if sample_weight is not None: percentage_error *= sample_weight self.total_error.assign_add(K.sum(percentage_error)) self.total_count.assign_add(K.sum(K.ones_like(y_true))) def result(self): return self.total_error / self.total_count ``` 在`update_state`方法中,我们首先计算每个样本的绝对误差百分比,然后将这些误差乘以对应的样本权重(如果有的话),并将其累加到`total_error`变量中。同时,我们还将样本数累加到`total_count`变量中。最后,我们在`result`方法中计算总的绝对误差百分比,即将累计的误差除以样本数。 在使用自定义metrics时,我们可以将其传递给`compile`函数的`metrics`参数。例如,下面是一个使用自定义损失函数metrics的Keras模型定义: ```python from keras.models import Sequential from keras.layers import Dense model = Sequential() model.add(Dense(10, input_shape=(3,), activation='relu')) model.add(Dense(1, activation='linear')) model.compile(loss=weighted_mse, optimizer='adam', metrics=[PercentageError()]) ``` 在这个例子中,我们使用了上面定义的加权均方误差损失函数,并使用了上面定义的绝对误差百分比metrics。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值