问题描述
我正在训练一个最后一层是单个sigmoid
单元的keras模型:
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。
解决方法
首先,我们可以揭开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,dtype=int32)
为了使mse
超过1,平均错误必须超过1:
print( mse(np.random.random((100,)),np.random.random((100,))) ) # tf.Tensor(0.14863832582680103,dtype=float64)
print( mse( 10 * np.random.random((100,))) ) # tf.Tensor(30.51209646429651,dtype=float64)
最后,S型确实可以确保输出介于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的含义:
您有一个数据集(粉色点),并且找到了该数据集的平均值(蓝线),因此需要评估您的计算。因此,您需要在价值和均值之间保持距离。但是我们为什么要平方这个呢?因为您可能具有负值(以下几点),并且排除了补偿。最后,我们找到了该DISTANSE的平均值(请注意,它不是数据集的平均值,而是数据集的平均值)
公式是:
让我们假设我们的数据有1点(值)。还有MSE 简单的情况是平均值和当前值之间的距离。而且因为 我们没有什么可以总结和除以一的结果,MSE在 范围是0到1。
但是,由于您要处理的是巨大的数据集,因此整个值都是相加并除以数字,因此MSE在(0,+ inf)中。顺便说一句,我们不需要使用正方形,在简单的情况下可以使用绝对值。
Keras允许您编写自己的损失函数,因此您的问题并不难解决。因此,您应该编写一个函数来计算平方,而不是将其除以数字-将其缩放为range(0,1)(为此,SciKit中的MinMaxScaler会非常好)。然后,您应该执行相同的操作:总结并除以
或者您可以添加标准化层(idk它是如何工作的,但我知道是这样)。
进一步阅读:
- https://keras.io/api/layers/preprocessing_layers/core_preprocessing_layers/normalization/#:~:text=Normalization%20class&text=Feature%2Dwise%20normalization%20of%20the,sqrt(var)%20at%20runtime。
- https://heartbeat.fritz.ai/how-to-create-a-custom-loss-function-in-keras-637bd312e9ab
乙状结肠不是平均值。这是一种将所有输出可变性作为可折叠性(范围为MinMaxScaler,但用于神经网络)折叠到range(0,1)的方法。当程序计算MSE时,它会做另一件事。不要混合。让我们用数学将其分开。
0
0 ^ 2
0
(因为这个和可以是。或更严格地说:如果b等于无穷大,则根据阿基米德属性)
设n = / = 0
0
我对所问的问题没有答案。我的 MSE 损失为 nans,输入范围为 [0,1],输出为 sigmoid。所以我认为这个问题是相关的。
以下是关于 sigmoid 的一些观察:
]).node().id=
因此,可以从 sigmoid 中获取 nans。以防万一有人(我,在不久的将来)(再次)有这个疑问。