Keras:Binary_crossentropy具有负值

ohtdti5x  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(97)

我正在跟踪this tutorial(第6节:把它绑在一起),用我自己的数据集。我可以让教程中的例子工作,没有问题,与样本数据集提供。
我得到一个二进制交叉熵误差是负的,并且随着时代的进步没有改进。我很确定二进制交叉熵应该总是正的,我应该看到损失的一些改善。我将下面的示例输出(和代码调用)截短为5个epochs。其他人在训练CNN时似乎有时会遇到类似的问题,但我在我的案例中没有看到明确的解决方案。有人知道为什么会这样吗?
样品输出:

Creating TensorFlow device (/gpu:2) -> (device: 2, name: GeForce GTX TITAN Black, pci bus id: 0000:84:00.0)
10240/10240 [==============================] - 2s - loss: -5.5378 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 2/5
10240/10240 [==============================] - 0s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 3/5
10240/10240 [==============================] - 0s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 4/5
10240/10240 [==============================] - 0s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 5/5
10240/10240 [==============================] - 0s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000

字符串
我的代码:

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

dataset = np.loadtxt('train_rows.csv', delimiter=",")
testset = np.loadtxt('test_rows.csv', delimiter=",")

# split into input (X) and output (Y) variables
X = dataset[:, :62]
Y = dataset[:, 62]

X_test = testset[:, :62]
Y_test = testset[:, 62]

### create model
model = Sequential()
model.add(Dense(100, input_dim=(62,), activation='relu'))
model.add(Dense(50, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
## Fit the model
model.fit(X, Y, validation_data=(X_test, Y_test), epochs=5, batch_size=128)

oknrviil

oknrviil1#

我应该打印出我的响应变量。类别被标记为1和2而不是0和1,这混淆了分类器。

wn9m85ua

wn9m85ua2#

如果你得到负损失,那么解决方案是强制目标为0或1。在OP的情况下,它是从目标/标签中减去1。

Y = np.array([1, 2, 1, 2])
Y -= 1                       # array([0, 1, 0, 1])

字符串
根据用例的不同,还有其他方法可以将目标“强制”为1或0。一种方法是布尔条件检查。例如,下面的代码将每个大于0的值转换为1,将所有其他值转换为0。

Y = np.array([-1, 1, -1, 1])
Y = (Y > 0).astype(int)      # array([0, 1, 0, 1])


另一个是clip(),它将每个值限制在0和1之间。如果标签是0/255,那么它就可以完成这项工作。

Y = [0, 255, 0, 1]
Y = np.clip(Y, 0, 1)         # array([0, 1, 0, 1])

亏损怎么可能是负数?

在Keras(1,2)中实现binary_crossentropy的方式是强制预测概率(下面的output)在(0,1)区间内,并返回以下计算的结果。

bce = target * log(output) + (1 - target) * log(1 - output)
return mean(-bce)


现在,由于output在0和1之间,因此log(output)log(1-output)都是负的。如果target是0或1,则bce是负的,因此mean(-bce)是正数,这是二进制交叉熵损失。但是,如果target不是0或1,则此逻辑失效。特别地,如果target大于1并且output足够大,则bce将是正的并且mean(-bce)将是负的。
binary_crossentropy()的实现总结如下:

import tensorflow as tf
epsilon_ = tf.keras.backend.epsilon()
target = tf.convert_to_tensor(y_true)
output = tf.clip_by_value(output, epsilon_, 1 - epsilon_)

bce = target * tf.math.log(output + epsilon_)
bce += (1 - target) * tf.math.log(1 - output + epsilon_)
loss = tf.reduce_mean(-bce)

相关问题