Бэкэнд-функция Keras работает некорректно - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь реализовать пользовательскую функцию потерь в Керасе.

Для начала я хотел убедиться, что предыдущая функция потерь может быть вызвана из моей пользовательской функции. И вот тут начинаются странные вещи:

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

работает как положено.

Теперь реализация sparse_categorical_crossentropy в keras.losses выглядит следующим образом:

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)

не работает. Во время тренировки уменьшается потеря (что кажется правильным), но точность не улучшается (но это происходит, когда используется функция нестандартной потери)

Я не уверен, что происходит, и при этом я не знаю, как правильно его отладить. Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

2 голосов
/ 03 июля 2019

Я проверил, что вы говорите в моем коде, и да, вы правы.Сначала я получал ту же ошибку, что и вы, но как только я изменил параметр метрики с accuracy на sparse_categorical_accuracy, я начал получать более высокую точность.

Здесь важно отметить, что когда мыприкажите keras использовать accuracy как metrics, keras использует точность по умолчанию, равную categorical_accuracy.Итак, если мы хотим реализовать нашу собственную функцию потерь, мы должны соответственно установить параметр metrics.

Читайте о доступной функции метрик в керасах от здесь .

Случай 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: Ошибка при проверке целевого объекта: ожидалось, что dens_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)

Проверьте реализациюsparse_categorical_accuracy с здесь и sparse_categorical_crossentropy с здесь .

1 голос
/ 03 июля 2019

Что происходит, когда вы используете метрику accuracy, Kera фактически выбирает другую реализацию точности в зависимости от потери, поскольку то, как вычисляется точность, зависит от меток и прогнозов модели:

  • для categorical_crossentropy он использует categorical_accuracy в качестве метрики точности.
  • для binary_crossentropy он использует binary_accuracy в качестве метрики точности.
  • для sparse_categorical_crossentropy он использует sparse_categorical_accuracy как метрика точности.

Керас может делать это только в том случае, если вы используете предопределенные потери, поскольку он не может догадаться иначе.Для вашей собственной потери вы можете напрямую использовать одну из трех реализаций точности, например metrics=['sparse_categorical_accuracy'].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...