在 TensorFlow 中添加了正则化成本的自定义损失函数
Custom loss function with regularization cost added in TensorFlow
我写了一个自定义损失函数,将正则化损失添加到总损失中,我只向内核添加了 L2 正则化器,但是当我调用 model.fit() 时出现了一个警告,指出梯度没有这些偏差存在,并且偏差不会更新,如果我从其中一层的内核中删除正则化项,该内核的梯度也不存在。
我尝试向每一层添加偏差正则化器并且一切正常,但我不想对偏差进行正则化,所以我该怎么办?
这是我的损失函数:
def _loss_function(y_true, y_pred):
# convert tensors to numpy arrays
y_true_n = y_true.numpy()
y_pred_n = y_pred.numpy()
# modify probablities for Knowledge Distillation loss
# we do this for old tasks only
old_y_true = np.float_power(y_true_n[:, :-1], 0.5)
old_y_true = old_y_true / np.sum(old_y_true)
old_y_pred = np.float_power(y_pred_n[:, :-1], 0.5)
old_y_pred = old_y_pred / np.sum(old_y_pred)
# Define the loss that we will used for new and old tasks
bce = tf.keras.losses.BinaryCrossentropy()
# compute the loss on old tasks
old_loss = bce(old_y_true, old_y_pred)
# compute the loss on new task
new_loss = bce(y_true_n[:, -1], y_pred_n[:, -1])
# compute the regularization loss
reg_loss = tf.compat.v1.losses.get_regularization_loss()
assert reg_loss is not None
# convert all tensors to float64
old_loss = tf.cast(old_loss, dtype=tf.float64)
new_loss = tf.cast(new_loss, dtype=tf.float64)
reg_loss = tf.cast(reg_loss, dtype=tf.float64)
return old_loss + new_loss + reg_loss
在 keras 中,损失函数应该 return 损失值 没有 正则化损失。通过在每个 keras 层中设置 kernel_regularizer 或 bias_regularizer 将自动添加正则化损失。
换句话说,当您编写自定义损失函数时,您不必关心正则化损失。
编辑: 您收到梯度不存在的警告消息的原因是因为在损失函数中使用了 numpy()
。 numpy()
将停止任何梯度传播。
将正则化器添加到层后警告消息消失不暗示梯度计算正确。它只包括来自正则化器的梯度,而不包括来自数据的梯度。 numpy()
应在损失函数中删除以获得正确的梯度。
其中一个解决方案是将所有内容都保存在张量中并使用 tf.math 库。例如使用 tf.pow
替换 np.float_power
和 tf.reduce_sum
替换 np.sum
我写了一个自定义损失函数,将正则化损失添加到总损失中,我只向内核添加了 L2 正则化器,但是当我调用 model.fit() 时出现了一个警告,指出梯度没有这些偏差存在,并且偏差不会更新,如果我从其中一层的内核中删除正则化项,该内核的梯度也不存在。
我尝试向每一层添加偏差正则化器并且一切正常,但我不想对偏差进行正则化,所以我该怎么办?
这是我的损失函数:
def _loss_function(y_true, y_pred):
# convert tensors to numpy arrays
y_true_n = y_true.numpy()
y_pred_n = y_pred.numpy()
# modify probablities for Knowledge Distillation loss
# we do this for old tasks only
old_y_true = np.float_power(y_true_n[:, :-1], 0.5)
old_y_true = old_y_true / np.sum(old_y_true)
old_y_pred = np.float_power(y_pred_n[:, :-1], 0.5)
old_y_pred = old_y_pred / np.sum(old_y_pred)
# Define the loss that we will used for new and old tasks
bce = tf.keras.losses.BinaryCrossentropy()
# compute the loss on old tasks
old_loss = bce(old_y_true, old_y_pred)
# compute the loss on new task
new_loss = bce(y_true_n[:, -1], y_pred_n[:, -1])
# compute the regularization loss
reg_loss = tf.compat.v1.losses.get_regularization_loss()
assert reg_loss is not None
# convert all tensors to float64
old_loss = tf.cast(old_loss, dtype=tf.float64)
new_loss = tf.cast(new_loss, dtype=tf.float64)
reg_loss = tf.cast(reg_loss, dtype=tf.float64)
return old_loss + new_loss + reg_loss
在 keras 中,损失函数应该 return 损失值 没有 正则化损失。通过在每个 keras 层中设置 kernel_regularizer 或 bias_regularizer 将自动添加正则化损失。
换句话说,当您编写自定义损失函数时,您不必关心正则化损失。
编辑: 您收到梯度不存在的警告消息的原因是因为在损失函数中使用了 numpy()
。 numpy()
将停止任何梯度传播。
将正则化器添加到层后警告消息消失不暗示梯度计算正确。它只包括来自正则化器的梯度,而不包括来自数据的梯度。 numpy()
应在损失函数中删除以获得正确的梯度。
其中一个解决方案是将所有内容都保存在张量中并使用 tf.math 库。例如使用 tf.pow
替换 np.float_power
和 tf.reduce_sum
替换 np.sum