Проблема потерь и метрик при обучении модели cnn

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

У меня проблема с моими пользовательскими функциями потерь и метрик. Моя цель – обучить модель CNN на изображениях с тангенсом угла ориентации объекта на моем изображении, и у меня есть столбец, который указывает, является ли тангенс положительным или отрицательным. В конце концов, у меня есть два выхода: один для тангенса (регрессия), а второй – для классификации. Теперь, когда я вызываю model.evaluate, я записываю регрессию как первую элемент, который должен появиться, но он не появляется первым. И я не уверен, что они как-то перепутаны, потому что не могу найти объяснение странным результатам, которые я получаю. Вот мой код:

  # Пользовательские функции потерь и метрик
@keras.utils.register_keras_serializable(package="Custom")

def angular_loss(y_true, y_pred):
    angles_true = tf.math.atan(y_true) * 180.0 / np.pi
    angles_pred = tf.math.atan(y_pred) * 180.0 / np.pi
    return tf.abs(angles_true - angles_pred)

@keras.utils.register_keras_serializable(package="Custom")
def rmse_degrees(y_true, y_pred):
    a = tf.constant(np.pi)
    angles_true = tf.math.atan(y_true) * 180.0 / a
    angles_pred = tf.math.atan(y_pred) * 180.0 / a
    b = tf.square(angles_true - angles_pred)
    return tf.reduce_mean(b)
# Определяем модель
input_image = Input(shape=X_train_images.shape[1:], name="input_image")
x = layers.Conv2D(32, (3, 3), activation='relu')(input_image)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Dropout(0.3)(x)
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Dropout(0.3)(x)
x = layers.Flatten()(x)
x = layers.Dense(128, activation='relu')(x)  # Промежуточный полносвязный слой
x = layers.Dropout(0.3)(x)

output_regression = layers.Dense(1, activation='linear', name="reg_output")(x)
output_classification = layers.Dense(1, activation='sigmoid', name="cls_output")(x)
model = keras.Model(inputs=input_image, outputs=[output_regression, output_classification])
model.summary()
model.save("modelfinal3.keras")
# Компилируем модель



model.compile(
    optimizer = RMSprop(learning_rate=0.0001),
    loss={
        'reg_output': angular_loss,
        'cls_output': 'binary_crossentropy'
    },
    metrics={
        'reg_output': [rmse_degrees],
        'cls_output': ['accuracy']
    }
)

# Определяем обратный вызов ModelCheckpoint для сохранения лучшей модели
callbacks = [
    keras.callbacks.ModelCheckpoint("modelfinal3.keras", monitor="reg_output_loss", save_best_only=True , mode="min"),
    keras.callbacks.EarlyStopping(monitor="reg_output_loss" , patience = 8 ,mode="min" )
]

# Обучаем модель без валидационных данных
history = model.fit(
    X_train_images,{'reg_output' : Y1_regression ,'cls_output' : Y2_classification} ,
    epochs= 10 ,
    batch_size= 64,
    callbacks=callbacks
)

test_model =keras.models.load_model("modelfinal3.keras", custom_objects ={'angular_loss': angular_loss, 'rmse_degrees': rmse_degrees })
results = test_model.evaluate(X_test_images, {'reg_output' : Y1_regression_test ,'cls_output' : Y2_classification_test },return_dict=True )


print(results)

‘введите код здесьрезультаты

30/30 ━━━━━━━━━━━━━━━━━━━━ 51s 2s/step - cls_output_accuracy: 0.6618 - cls_output_loss: 9.0815 - loss: 14.4716 - reg_output_loss: 5.3914 - reg_output_rmse_degrees: 2806.2744

Эпоха 7/10
30/30 ━━━━━━━━━━━━━━━━━━━━ 53s 2s/step – cls_output_accuracy: 0.6401 – cls_output_loss: 8.9781 – loss: 14.7173 – reg_output_loss: 5.7363 – reg_output_rmse_degrees: 2787.8420
Эпоха 8/10
30/30 ━━━━━━━━━━━━━━━━━━━━ 51s 2s/step – cls_output_accuracy: 0.6524 – cls_output_loss: 9.0007 – loss: 14.5403 – reg_output_loss: 5.5401 – reg_output_rmse_degrees: 2789.3442
Эпоха 9/10
30/30 ━━━━━━━━━━━━━━━━━━━━ 51s 2s/step – cls_output_accuracy: 0.6674 – cls_output_loss: 9.4412 – loss: 14.7438 – reg_output_loss: 5.3030 – reg_output_rmse_degrees: 2844.9971
Эпоха 10/10
30/30 ━━━━━━━━━━━━━━━━━━━━ 52s 2s/step – cls_output_accuracy: 0.6610 – cls_output_loss: 9.3189 – loss: 14.7248 – reg_output_loss: 5.4059 – reg_output_rmse_degrees: 2828.9368
11/11 ━━━━━━━━━━━━━━━━━━━━ 2s 142ms/step – cls_output_accuracy: 1.0000 – cls_output_loss: 9.4424 – loss: 9.4928 – reg_output_loss: 1.1921e-07 – reg_output_rmse_degrees: 2435.0107
{‘cls_output_accuracy’: 1.0, ‘cls_output_loss’: 8.932900428771973, ‘loss’: 9.235373497009277, ‘reg_output_loss’: 1.1920930376163597e-07, ‘reg_output_rmse_degrees’: 2396.7568359375}

Процесс завершился с кодом выхода 0 ‘

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

Проблемы с метриками и функцией потерь при обучении модели CNN: Долгосрочные решения

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

1. Неправильный порядок метрик в выводе результата

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

  • Порядок вывода метрик: Стандартный вывод в Keras отображает метрики в том порядке, в котором они были определены в функции model.compile(). Таким образом, для исправления порядка метрик попробуйте изменить порядок определения в metrics:
metrics={
    'cls_output': ['accuracy'],
    'reg_output': [rmse_degrees]
}

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

2. Неправильные функции потерь и их возможное влияние на обучение

Функция потерь angular_loss в вашем коде определяется с использованием tf.math.atan(), которая может привести к некорректным результатам, если значения y_true и y_pred выходят за пределы допустимых диапазонов. Проверьте диапазон ваших данных для предотвращения проблем с неустойчивыми значениями. Убедитесь, что значения тангенса находятся в допустимом диапазоне.

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

3. Визуализация и анализ истории обучения

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

Используйте следующее:

import matplotlib.pyplot as plt

# Визуализация метрик
plt.plot(history.history['reg_output_rmse_degrees'], label='Регрессионный RMSE')
plt.plot(history.history['cls_output_accuracy'], label='Точность классификации')
plt.title('Метрики обучения')
plt.ylabel('Значение метрики')
plt.xlabel('Эпоха')
plt.legend()
plt.show()

Заключение

Для решения описанных вами проблем необходимо внимательно проверить порядок метрик в выводе, корректность определения функций потерь и наблюдать за динамикой обучения модели. Эти шаги помогут вам более точно настроить модель и, возможно, устранить выявленные недостатки. Обратите внимание на визуализацию данных, чтобы упростить процесс анализа и настройки. Удачи в ваших усилиях по разработке и обучению сверточной нейронной сети!

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

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