学习者,
我想用小批量using a custom loss function
训练NN。每个小批量都包含n new samples and m replay samples
。重播示例用于重播,以避免遗忘。
我的损失fnc看起来像:
loss=mse(new_samples_truth, new_samples_pred) + factor*mse(replay_samples_truth, replay_sampls_pred)
正如您所看到的,损失是分别为新样本和重放样本计算的两毫秒的加权和这意味着每当我想训练一个批次时,我都想分离新的和重播的数据点,并计算整个批次的标量损失
如何在Keras
中实现此损失函数,并将其与train_on_batch一起使用?Keras的train_on_batch方法似乎用损失函数分别计算小批量中每个数据点的损失。由于我的批处理包含新的和重播的数据点,这将不起作用。So how can I Keras make calculate the Loss for the entire batch at once and return only once scalar?
此外,Keras似乎单独评估批次中每个数据点的损失fnc,并将每个样本的损失保存在数组中。然而,我想得到整个批次的损失。有人了解Keras实际上是如何处理批量损失计算的吗?
这是我的伪代码
batch=pd.concat([new_samples, replay_samples]) #new_samples and replay_samples are pd.dataframes
#len(batch) = 20
def my_replay_loss(factor):
def loss(y_true, y_pred): #y_true and y_pred come from keras
y_true_new_samples = y_true.head(10)
y_pred_new_samples = y_pred.head(10)
y_true_replay_samples = y_true.tail(10)
y_pred_replay_samples = y_pred.tail(10)
calc_loss = mse(y_true_new_samples, y_pred_new_samples) + factor*mse(y_true_replay_samples, y_pred_replay_samples)
return calc_loss
return loss
''
您可以像以前一样定义自定义损失函数,但您需要使用tf操作构建一个tf图,例如:
def my_replay_loss(factor):
def loss(y_true, y_pred):
calc_loss = tf.math.add(tf.keras.losses.mse(y_true[:10, :], y_pred[:10, :]),
tf.math.multiply(factor, tf.keras.losses.mse(y_true[-10:, :], y_pred[-10:, :])))
return calc_loss
return loss
然后你可以用编译你的模型
loss=my_replay_loss(factor=tf.constant(0.5, dtype=tf.float32))
然而,在您的情况下,我建议不要根据批次中数据点的顺序构建损失函数,但我建议构建一个具有2个输入和2个输出的模型(最终共享模型架构(,并在具有2个损失的情况下编译它们。Keras模型支持loss_weights参数,该参数允许您根据需要对两种损失进行加权。
loss_weights:指定标量系数(Python浮点(的可选列表或字典,用于加权不同模型输出的损失贡献。然后,模型将最小化的损失值将是所有单个损失的加权和,并通过损失权重系数进行加权。如果是一个列表,那么它应该与模型的输出有1:1的映射。如果是dict,则需要将输出名称(字符串(映射到标量系数。
这里有一个快速的例子:
import tensorflow as tf
def get_compiled_model(input_shape):
input1 = tf.keras.Input(input_shape)
input2 = tf.keras.Input(input_shape)
conv_layer = tf.keras.layers.Conv2D(128, 3, activation='relu')
flatten_layer = tf.keras.layers.Flatten()
dense_layer = tf.keras.layers.Dense(1, activation='softmax')
x1 = conv_layer(input1)
x1 = flatten_layer(x1)
output1 = dense_layer(x1)
x2 = conv_layer(input2)
x2 = flatten_layer(x2)
output2 = dense_layer(x2)
model = tf.keras.Model(inputs=[input1, input2], outputs=[output1, output2])
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=[tf.keras.losses.mse, tf.keras.losses.mse],
loss_weights=[1, 0.5])
return model
model = get_compiled_model(input_shape=x_train[0].shape)
model.fit([x_train1, x_train2], [y_train1, y_train2], epochs=5, batch_size=10)