Использование метрики BinaryCrossentropy из Keras для бинарной модели

Вопрос или проблема

Я пытаюсь реализовать модель бинарной классификации с использованием tensorflow keras и столкнулся с проблемой, которую не могу понять.

Моя модель должна классифицировать изображения домов на два класса: “старый/антикварный” и “новый/современный”. Я использовал трансферное обучение с предобученной моделью VGG16 и уже достиг некоторых успехов, но хотел бы немного оптимизировать её. Вот схема модели

model_cropped = keras.Sequential([
    layers.InputLayer(input_shape=(224, 224, 3)),
    augmentation,
    pre_model,

    layers.Flatten(),
    layers.Dense(256, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(64, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(1, activation='sigmoid')
])

optimizer = keras.optimizers.Nadam(learning_rate=1e-6, use_ema = True)

model_cropped.compile(
    optimizer = optimizer,
    loss=keras.losses.BinaryCrossentropy(),
    metrics=[keras.BinaryCrossentropy()]
)

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

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[201], line 4
      1 epochs = 600
      2 print("Fitting the end-to-end model")
----> 4 history_cropped = model_cropped.fit(
      5     X_train, y_train,
      6     epochs=epochs,
      7     validation_data=(X_test, y_test),
      8     batch_size=64
      9 )

File ~/lib/python3.10/site-packages/keras/src/utils/traceback_utils.py:122, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    119     filtered_tb = _process_traceback_frames(e.__traceback__)
    120     # Чтобы получить полный трассировочный журнал, вызовите:
    121     # `keras.config.disable_traceback_filtering()`
--> 122     raise e.with_traceback(filtered_tb) from None
    123 finally:
    124     del filtered_tb

File ~/lib/python3.10/site-packages/keras/src/backend/tensorflow/nn.py:737, in binary_crossentropy(target, output, from_logits)
    734 output = tf.convert_to_tensor(output)
    736 if len(target.shape) != len(output.shape):
--> 737     raise ValueError(
    738         "Arguments `target` and `output` must have the same rank "
    739         "(ndim). Received: "
    740         f"target.shape={target.shape}, output.shape={output.shape}"
    741     )
    742 for e1, e2 in zip(target.shape, output.shape):
    743     if e1 is not None and e2 is not None and e1 != e2:

ValueError: Аргументы `target` и `output` должны иметь одинаковую ранг (ndim). Получено: target.shape=(None,), output.shape=(None, 1)

Очевидно, что ранг выходного узла равен (None, 1), но бинарная кросс-энтропия ожидает (None,). Можете кто-нибудь объяснить мне, что я не понимаю здесь или что я делаю не так? Я думал, что, поскольку бинарная кросс-энтропия работает как функция потерь, она также должна работать как метрика.

Большое спасибо

Как я упоминал в своем комментарии к оригинальному вопросу, проблема, кажется, заключается в том, что у вас несоответствие в размерах. Чтобы решить это, вы можете преобразовать ваши целевые метки (y_train и y_test) так, чтобы они имели форму (None, 1) вместо (None,). Вы можете сделать это, добавив дополнительное измерение с помощью np.expand_dims (или аналогичной функции в TF). Если вы предпочитаете не изменять свои целевые данные, вы можете адаптировать выходной слой, чтобы он выдавал форму (None,), сделав его одномерным.

Ответ или решение

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

Проблема

Вы столкнулись с ошибкой, связанной с несовпадением размерностей в выходных данных вашей модели. Ваша модель генерирует выходные данные в форме (None, 1), в то время как метрика BinaryCrossentropy ожидает данные в форме (None,) — т.е. одномерные массивы (вектор меток). Это несоответствие приводит к следующей ошибке:

ValueError: Arguments `target` and `output` must have the same rank (ndim). Received: target.shape=(None,), output.shape=(None, 1)

Решение

Для исправления этой токсичной несостыковки можно применить одно из предложенных ниже решений:

  1. Изменение формы меток:
    Используйте np.expand_dims() для изменения формы ваших меток y_train и y_test на (None, 1). Пример кода для изменения формы меток:

    import numpy as np
    
    y_train = np.expand_dims(y_train, axis=-1)  # теперь y_train имеет shape (N, 1)
    y_test = np.expand_dims(y_test, axis=-1)    # теперь y_test имеет shape (M, 1)
  2. Адаптация выходного слоя модели:
    Это решение предполагает, что вы измените выходной слой вашей модели, чтобы он выдавал одномерный выход. Это можно сделать, изменив последний слой с:

    layers.Dense(1, activation='sigmoid')

    на

    layers.Dense(1, activation='sigmoid', use_bias=False)

    или добавив Flatten() перед выходным слоем, чтобы результат стал одномерным.

Реализация модели

Ваш окончательный код для компиляции модели будет выглядеть следующим образом:

model_cropped.compile(
    optimizer=optimizer,
    loss=keras.losses.BinaryCrossentropy(),
    metrics=[keras.metrics.BinaryAccuracy()]  # Используйте более подходящую метрику для оценки
)

Замечания

  • Использование метрик: BinaryCrossentropy как метрика не является стандартной практикой. Она используется в первую очередь как функция потерь. Вместо этого рекомендуем использовать такие метрики, как BinaryAccuracy, чтобы оценить производительность модели.

  • Настройки оптимизатора: Убедитесь, что рассматриваемая скорость обучения и настройки оптимизатора в большинстве случаев влияют на стабильность и качество обучения модели. Бывает полезно проводить поиск по гиперпараметрам, чтобы найти наилучшие значения.

  • Аугментация данных: Если данные недостаточно разнообразны, попробуйте использовать дополнительные методы аугментации изображений, чтобы избежать переобучения и улучшить обобщающую способность модели.

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

Оцените материал
Добавить комментарий

Капча загружается...