【问题标题】:Keras backend function seems to be working incorrectlyKeras 后端功能似乎无法正常工作
【发布时间】:2019-07-03 12:02:42
【问题描述】:

我正在尝试在 Keras 中实现自定义损失函数。

首先,我想确保可以从我的自定义函数中调用之前的损失函数。这就是奇怪的事情开始的地方:

model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics=['accuracy'])

按预期工作。

现在keras.losses中“sparse_categorical_crossentropy”的实现如下:

def sparse_categorical_crossentropy(y_true, y_pred):
    return K.sparse_categorical_crossentropy(y_true, y_pred)

我得出结论,直接传递K.sparse_categorical_crossentropy 也应该有效。但是,它会抛出 expected activation_6 to have shape (4,) but got array with shape (1,)。

另外,像这样定义一个自定义损失函数:

def custom_loss(y_true, y_pred):
    return keras.losses.sparse_categorical_crossentropy(y_true, y_pred)

不起作用。在训练期间减少了损失(这似乎是正确的),但准确性并没有提高(但在使用非自定义损失函数时确实如此)

我不确定发生了什么,我也不知道如何正确调试它。任何帮助将不胜感激。

【问题讨论】:

  • 你编译模型的新代码是什么?

标签: python tensorflow keras loss-function


【解决方案1】:

我在我的代码上测试了您所说的内容,是的,您是对的。我最初遇到的错误与您遇到的相同,但是一旦我将指标参数从 accuracy 更改为 sparse_categorical_accuracy,我开始获得更高的准确度。

在这里,需要注意的一件重要事情是,当我们告诉 keras 使用 accuracy 为 metrics 时,keras 使用默认精度,即 categorical_accuracy。所以,如果我们想实现自己的自定义损失函数,那么我们必须相应地设置metrics参数。

从here 了解 keras 中可用的指标函数。

案例 1:

def sparse_categorical_crossentropy(y_true, y_pred):
    return K.sparse_categorical_crossentropy(y_true, y_pred)

model.compile(optimizer='adam',
              loss=sparse_categorical_crossentropy,
              metrics=['accuracy'])

输出:

ValueError:检查目标时出错:预期会有 dense_71 形状 (10,) 但得到了形状 (1,) 的数组

案例 2:

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

输出:

Epoch 1/2
60000/60000 [==============================] - 2s 38us/step - loss: 0.4714 - acc: 0.8668
Epoch 2/2
60000/60000 [==============================] - 1s 22us/step - loss: 0.2227 - acc: 0.9362
10000/10000 [==============================] - 1s 94us/step

案例 3:

def custom_sparse_categorical_crossentropy(y_true, y_pred):
    return K.sparse_categorical_crossentropy(y_true, y_pred)

model.compile(optimizer='adam',             
              loss=custom_sparse_categorical_crossentropy, 
              metrics=['accuracy'])

输出:

Epoch 1/2
60000/60000 [==============================] - 2s 41us/step - loss: 0.4558 - acc: 0.1042
Epoch 2/2
60000/60000 [==============================] - 1s 22us/step - loss: 0.2164 - acc: 0.0997
10000/10000 [==============================] - 1s 89us/step

案例 4:

def custom_sparse_categorical_crossentropy(y_true, y_pred):
    return K.sparse_categorical_crossentropy(y_true, y_pred)

model.compile(optimizer='adam',
              loss=custom_sparse_categorical_crossentropy,
              metrics=['sparse_categorical_accuracy'])

输出:

Epoch 1/2
60000/60000 [==============================] - 2s 40us/step - loss: 0.4736 - sparse_categorical_accuracy: 0.8673
Epoch 2/2
60000/60000 [==============================] - 1s 23us/step - loss: 0.2222 - sparse_categorical_accuracy: 0.9372
10000/10000 [==============================] - 1s 85us/step

完整代码:

from __future__ import absolute_import, division, print_function
import tensorflow as tf
import keras.backend as K


mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([

tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(100, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.10),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

def custom_sparse_categorical_crossentropy(y_true, y_pred):
    return K.sparse_categorical_crossentropy(y_true, y_pred)

#def sparse_categorical_accuracy(y_true, y_pred):
#    # reshape in case it's in shape (num_samples, 1) instead of (num_samples,)
#    if K.ndim(y_true) == K.ndim(y_pred):
#        y_true = K.squeeze(y_true, -1)
#    # convert dense predictions to labels
#    y_pred_labels = K.argmax(y_pred, axis=-1)
#    y_pred_labels = K.cast(y_pred_labels, K.floatx())
#    return K.cast(K.equal(y_true, y_pred_labels), K.floatx())

model.compile(optimizer='adam',
          loss=custom_sparse_categorical_crossentropy,
         metrics=['sparse_categorical_accuracy'])

history = model.fit(x_train, y_train, epochs=2, batch_size=200)
model.evaluate(x_test, y_test)

查看here 中的sparse_categorical_accuracy 和here 中的sparse_categorical_crossentropy 的实现。

【讨论】:

    【解决方案2】:

    发生的情况是,当您使用 accuracy 指标时,Kera 实际上会根据损失选择不同的准确度实现,因为准确度的计算方式取决于模型的标签和预测:

    • 对于categorical_crossentropy,它使用categorical_accuracy 作为准确度指标。
    • 对于binary_crossentropy,它使用binary_accuracy 作为准确度指标。
    • 对于sparse_categorical_crossentropy,它使用sparse_categorical_accuracy 作为准确度指标。

    如果您使用预定义的损失,Keras 只能这样做,否则它无法猜测。对于您的自定义损失,您可以直接使用三种准确度实现之一,例如metrics=['sparse_categorical_accuracy']。

    【讨论】:

      猜你喜欢
      • 2020-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-04
      • 2012-05-06
      • 2013-02-17
      • 2017-10-09
      • 2017-08-03
      相关资源
      最近更新 更多