Göd*_*del 14 machine-learning keras tensorflow loss-function tensorflow2.0
我正在 tensorflow(2.3) 中学习 keras API。在tensorflow 网站上的本指南中,我找到了一个自定义损失函数的示例:
def custom_mean_squared_error(y_true, y_pred):
return tf.math.reduce_mean(tf.square(y_true - y_pred))
Run Code Online (Sandbox Code Playgroud)
在reduce_mean这个自定义损失函数函数会返回一个标量。
这样定义损失函数合适吗?据我所知,y_true和形状的第一维y_pred是批量大小。我认为损失函数应该为批次中的每个样本返回损失值。所以损失函数应该给出一个形状数组(batch_size,)。但是上面的函数为整个批次提供了一个值。
也许上面的例子是错误的?任何人都可以在这个问题上给我一些帮助吗?
ps为什么我认为损失函数应该返回一个数组而不是单个值?
我阅读了Model类的源代码。当您向方法提供损失函数(请注意它是一个函数,而不是损失类)时Model.compile(),该损失函数用于构造一个LossesContainer对象,该对象存储在Model.compiled_loss. 传递给LossesContainer类的构造函数的这个损失函数再次用于构造一个LossFunctionWrapper对象,该对象存储在LossesContainer._losses.
根据LossFunctionWrapper类的源代码,训练批次的整体损失值是通过LossFunctionWrapper.__call__()方法(继承自Loss类)计算的,即它返回整个批次的单个损失值。但是第LossFunctionWrapper.__call__()一个调用该LossFunctionWrapper.call()方法以获得训练批次中每个样本的损失数组。然后将这些损失最后平均以获得整批的单个损失值。这是在LossFunctionWrapper.call()方法的损失函数提供给Model.compile()方法被调用。
这就是为什么我认为自定义损失函数应该返回一系列损失,而不是单个标量值。此外,如果我们Loss为Model.compile()方法编写自定义类call(),我们自定义Loss类的方法也应该返回一个数组,而不是一个信号值。
我在github上打开了一个问题。已确认需要自定义损失函数来为每个样本返回一个损失值。该示例将需要更新以反映这一点。
实际上,据我所知,损失函数的返回值的形状并不重要,即它可以是标量张量,也可以是每个样本一个或多个值的张量。重要的是它应该如何减少到一个标量值,以便它可以用于优化过程或显示给用户。为此,您可以检查Reduction 文档中的减少类型。
此外,这里是compile方法文档关于loss参数的说明,部分解决了这一点:
loss:字符串(目标函数名称)、目标函数或
tf.keras.losses.Loss实例。见tf.keras.losses。目标函数是任何带有签名的可调用函数loss = fn(y_true,y_pred),其中y_true= 形状为 = 的地面真值[batch_size, d0, .. dN],除了稀疏的损失函数,例如形状为 = 的稀疏分类交叉熵[batch_size, d0, .. dN-1]。y_pred= 形状为 = 的预测值[batch_size, d0, .. dN]。它返回一个加权损失浮动张量。如果使用自定义Loss实例并将缩减设置为NONE,则返回值的形状为[batch_size, d0, .. dN-1]IE。每个样本或每个时间步的损失值;否则,它是一个标量。如果模型有多个输出,您可以通过传递字典或损失列表对每个输出使用不同的损失。模型将最小化的损失值将是所有单个损失的总和。
此外,值得注意的是,TF/Keras 中的大多数内置损失函数通常在最后一个维度(即axis=-1)上减少。
对于那些怀疑返回标量值的自定义损失函数是否有效的人:您可以运行以下代码段,您将看到模型将正确训练和收敛。
import tensorflow as tf
import numpy as np
def custom_loss(y_true, y_pred):
return tf.reduce_sum(tf.square(y_true - y_pred))
inp = tf.keras.layers.Input(shape=(3,))
out = tf.keras.layers.Dense(3)(inp)
model = tf.keras.Model(inp, out)
model.compile(loss=custom_loss, optimizer=tf.keras.optimizers.Adam(lr=0.1))
x = np.random.rand(1000, 3)
y = x * 10 + 2.5
model.fit(x, y, epochs=20)
Run Code Online (Sandbox Code Playgroud)
我认为@G\xc3\xb6del 提出的问题是完全合法且正确的。自定义损失函数应返回每个样本的损失值。而且,@today 提供的解释也是正确的。最后,这完全取决于所使用的还原类型。
\n因此,如果使用类 API 创建损失函数,那么自定义类中会自动继承归约参数。使用其默认值“ sum_over_batch_size ”(这只是给定批次中所有损失值的平均值)。其他选项是“ sum ”,它计算总和而不是求平均值,最后一个选项是“ none ”,其中返回损失值数组。
\nKeras 文档中还提到,在使用时,这些减少的差异是不敬的,model.fit()因为减少是由 TF/Keras 自动处理的。
最后,还提到,当创建自定义损失函数时,应该返回一组损失(单个样本损失)。它们的减少由框架处理。
\n链接:
\n| 归档时间: |
|
| 查看次数: |
3444 次 |
| 最近记录: |