训练MSE损失大于理论最大值?

2024-04-19 19:54:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在训练一个keras模型,其最后一层是一个sigmoid单元:

output = Dense(units=1, activation='sigmoid')

我用一些训练数据训练这个模型,其中预期输出总是一个介于0.0和1.0之间的数字。 我使用均方误差编译模型:

model.compile(optimizer='adam', loss='mse')

由于预期输出和实际输出都是介于0和1之间的单浮点数,因此我也希望损失在0和1之间,但是当我开始训练时,我得到的损失是3.3932,大于1

我错过什么了吗

编辑: 我添加了一个示例来说明问题: https://drive.google.com/file/d/1fBBrgW-HlBYhG-BUARjTXn3SpWqrHHPK/view?usp=sharing (我不能只是粘贴代码,因为我需要附加培训数据)

运行python stackoverflow.py后,将显示模型的摘要以及培训过程。 我还在每一步打印y_true的最小值和最大值,以验证它们是否在[0,1]范围内。 无需等待训练结束,您将看到前几个时期的损失远远大于1


Tags: 数据模型outputmodel数字activationkerasdense
2条回答

首先,我们可以揭开mse丢失的神秘面纱-它是tf.keras中的一个正常可调用函数:

import tensorflow as tf
import numpy as np

mse = tf.keras.losses.mse
print(mse([1] * 3, [0] * 3))  # tf.Tensor(1, shape=(), dtype=int32)

接下来,正如名称“均方误差”所暗示的,它是一个平均值,这意味着传递给它的向量的大小不会改变值,只要平均值相同:

print(mse([1] * 10, [0] * 10)) # tf.Tensor(1, shape=(), dtype=int32)

为了使mse超过1,平均误差必须超过1:

print( mse(np.random.random((100,)), np.random.random((100,))) )  # tf.Tensor(0.14863832582680103, shape=(), dtype=float64)
print( mse( 10 * np.random.random((100,)), np.random.random((100,))) )  # tf.Tensor(30.51209646429651, shape=(), dtype=float64)

最后,sigmoid确实保证输出介于0和1之间:

sigmoid = tf.keras.activations.sigmoid
signal = 10 * np.random.random((100,))

output = sigmoid(signal)
print(f"Raw: {np.mean(signal):.2f}; Sigmoid: {np.mean(output):.2f}" )  # Raw: 5.35; Sigmoid: 0.92

这意味着在代码中,y_true的平均值不在0和1之间

您可以用np.mean(y_true)来验证这一点

我对这个问题没有答案。我在MSE损耗中得到NaN,输入在[0,1]范围内,输出在sigmoid。所以我认为这个问题是相关的

以下是一些关于乙状结肠的观察结果:

import tensorflow as tf
import numpy as np

x=tf.constant([-20, -1.0, 0.0, 1.0, 20], dtype = tf.float32)
x=tf.keras.activations.sigmoid(x)
x.numpy()

# array([2.0611537e-09, 2.6894143e-01, 5.0000000e-01, 7.3105860e-01,
#   1.0000000e+00], dtype=float32)

x=tf.constant([float('nan')]*5, dtype = tf.float32)
x=tf.keras.activations.sigmoid(x)
x.numpy()

# array([nan, nan, nan, nan, nan], dtype=float32)

x=tf.constant([np.inf]*5, dtype = tf.float32)
x=tf.keras.activations.sigmoid(x)
x.numpy()

# array([1., 1., 1., 1., 1.], dtype=float32)

所以,有可能让南斯离开乙状结肠。以防万一有人(我,在不久的将来)有这种怀疑(再次)

相关问题 更多 >