Как увеличить точность и уменьшить потери в модели CNN.

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

Я использую этот набор данных для обучения своей модели: https://www.kaggle.com/datasets/sankalpsrivastava26/capital-alphabets-28×28

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

model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(32, 32, 1)),
    tf.keras.layers.MaxPooling2D(2, 2),

    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),

    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),

    tf.keras.layers.Flatten(),

    tf.keras.layers.Dense(512, activation='relu'),

    tf.keras.layers.Dense(62, activation='softmax')
])

и мои обратные вызовы:

tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor="val_loss", factor=0.2,
                              patience=5, min_lr=0.001)
es = tf.keras.callbacks.EarlyStopping(monitor = "val_accuracy", restore_best_weights=True, mode="max", patience = 15, verbose = 1)
model_cp = tf.keras.callbacks.ModelCheckpoint(filepath="best_model2.weights.h5", monitor = "val_accuracy", save_best_only = True, verbose = 1, save_weights_only=True)

и обучение:

adam_optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(loss="categorical_crossentropy", optimizer=adam_optimizer, metrics=['accuracy'])
result = model.fit(
    trainX, trainY, 
    validation_data=(testX, testY),
    epochs=1000, 
    steps_per_epoch=len(trainX)//32,
    callbacks=[tensorboard_callback, es, model_cp],
    verbose=1
)

но val_accuracy и accuracy не увеличиваются, также loss и val_loss значения не уменьшаются.

Я тестировал:
**epochs= 32, 100, 200**,
Также я использовал генератор вот так:

generator = ImageDataGenerator(
        featurewise_center=False,
        featurewise_std_normalization=False,
        rotation_range=20,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.3,
        zoom_range=0.08,
        horizontal_flip=True)

test_gen = ImageDataGenerator()

train_generator = generator.flow(trainX, trainY, batch_size=32, shuffle=True)
test_generator = test_gen.flow(testX, testY, batch_size=32)

adam_optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(loss="categorical_crossentropy", optimizer=adam_optimizer, metrics=['accuracy'])
result = model.fit(
     train_generator, 
    trainX, trainY,
    validation_data=test_generator,
    validation_data=(testX, testY),
    epochs=100, 
    validation_steps=len(testX)//32,
    steps_per_epoch=len(trainX)//32,
    verbose=1,
    callbacks=[reduce_lr, tensorboard_callback, es, model_cp],
)

эти изменения привели к плохому результату, я новичок и не знаю, что делать дальше.

# Подтвержденные размеры
print("Shape of concatenated trainX:", trainX.shape)
print("Shape of concatenated trainY:", trainY.shape)
print("Shape of concatenated testX:", testX.shape)
print("Shape of concatenated testY:", testY.shape)
Shape of concatenated trainX: (487227, 32, 32)
Shape of concatenated trainY: (487227, 62)
Shape of concatenated testX: (155489, 32, 32)
Shape of concatenated testY: (155489, 62)
Epoch 1: val_accuracy improved from -inf to 0.80699, saving model to best_model2.weights.h5
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 136s 9ms/step - accuracy: 0.7509 - loss: 0.8253 - val_accuracy: 0.8070 - val_loss: 0.5859
Epoch 2/1000
14763/15225 ━━━━━━━━━━━━━━━━━━━━ 4s 9ms/step - accuracy: 0.8191 - loss: 0.5483
Epoch 2: val_accuracy improved from 0.80699 to 0.81478, saving model to best_model2.weights.h5
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 145s 10ms/step - accuracy: 0.8191 - loss: 0.5482 - val_accuracy: 0.8148 - val_loss: 0.5643
Epoch 3/1000
14763/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.8287 - loss: 0.5159
Epoch 3: val_accuracy improved from 0.81478 to 0.81694, saving model to best_model2.weights.h5
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 141s 9ms/step - accuracy: 0.8287 - loss: 0.5161 - val_accuracy: 0.8169 - val_loss: 0.5574
Epoch 4/1000
14760/15225 ━━━━━━━━━━━━━━━━━━━━ 4s 9ms/step - accuracy: 0.8328 - loss: 0.4986
Epoch 4: val_accuracy improved from 0.81694 to 0.82024, saving model to best_model2.weights.h5
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 144s 9ms/step - accuracy: 0.8327 - loss: 0.4987 - val_accuracy: 0.8202 - val_loss: 0.5510
Epoch 5/1000
14761/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.8363 - loss: 0.4852
Epoch 5: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 134s 9ms/step - accuracy: 0.8362 - loss: 0.4854 - val_accuracy: 0.8197 - val_loss: 0.5709
Epoch 6/1000
14759/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.8382 - loss: 0.4786
Epoch 6: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 137s 9ms/step - accuracy: 0.8381 - loss: 0.4788 - val_accuracy: 0.8162 - val_loss: 0.5658
Epoch 7/1000
14761/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.8411 - loss: 0.4684
Epoch 7: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 139s 9ms/step - accuracy: 0.8411 - loss: 0.4686 - val_accuracy: 0.8145 - val_loss: 0.5823
Epoch 8/1000
14760/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.8439 - loss: 0.4600
Epoch 8: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 138s 9ms/step - accuracy: 0.8438 - loss: 0.4603 - val_accuracy: 0.8159 - val_loss: 0.5786
Epoch 9/1000
14760/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.8438 - loss: 0.4576
2024-10-27 17:06:58.858730: I tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
     [[{{node IteratorGetNext}}]]

Epoch 9: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 138s 9ms/step - accuracy: 0.8438 - loss: 0.4577 - val_accuracy: 0.8132 - val_loss: 0.5921
Epoch 10/1000
14759/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.8464 - loss: 0.4476
Epoch 10: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 139s 9ms/step - accuracy: 0.8463 - loss: 0.4479 - val_accuracy: 0.8142 - val_loss: 0.6027
Epoch 11/1000
14762/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.8498 - loss: 0.4392
Epoch 11: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 135s 9ms/step - accuracy: 0.8497 - loss: 0.4395 - val_accuracy: 0.8099 - val_loss: 0.6066
Epoch 12/1000
14765/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 8ms/step - accuracy: 0.8505 - loss: 0.4373
Epoch 12: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 134s 9ms/step - accuracy: 0.8505 - loss: 0.4376 - val_accuracy: 0.8112 - val_loss: 0.6194
Epoch 13/1000
14760/15225 ━━━━━━━━━━━━━━━━━━━━ 3s 9ms/step - accuracy: 0.8508 - loss: 0.4342
Epoch 13: val_accuracy did not improve from 0.82024
15225/15225 ━━━━━━━━━━━━━━━━━━━━ 140s 9ms/step - accuracy: 0.8508 - loss: 0.4345 - val_accuracy: 0.8129 - val_loss: 0.6261

Я также пробовал это:

model = tf.keras.models.Sequential([

    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(32, 32, 1)),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.BatchNormalization(),

    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.BatchNormalization(),

    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.BatchNormalization(),

    tf.keras.layers.Flatten(),
    # Скрытый слой с 512 нейронами
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dropout(0.3),

    tf.keras.layers.Dense(62, activation='softmax')
])

и генератор:

train_generator = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.3,
    zoom_range=0.08,
    horizontal_flip=True
)

train_generator.fit(trainX)

test_generator = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True
)

test_generator.mean = train_generator.mean
test_generator.std = train_generator.std

train_data_gen = train_generator.flow(trainX, trainY, batch_size=32, shuffle=True)
test_data_gen = test_generator.flow(testX, testY, batch_size=32)

adam_optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(loss="categorical_crossentropy", optimizer=adam_optimizer, metrics=['accuracy'])
result = model.fit(
    train_data_gen,
    validation_data=test_data_gen,
    epochs=1000, 
    steps_per_epoch=len(trainX)//32,
    callbacks=[tensorboard_callback, es, model_cp],
    verbose=1
)

и результат https://pastebin.ubuntu.com/p/4pM4RwWR8X/

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

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

1. Улучшение архитектуры модели

  • Добавление дополнительных слоев и фильтров: Вы можете попробовать увеличить количество слоев и число фильтров в существующих слоях. Например, добавьте дополнительные сверточные и подвыборочные (max pooling) слои. Проверьте, как они влияют на производительность:

    model = tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(32, 32, 1)),
        tf.keras.layers.MaxPooling2D(2, 2),
        tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2,2),
        tf.keras.layers.Conv2D(256, (3,3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2,2),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(512, activation='relu'),
        tf.keras.layers.Dropout(0.5),  # Добавление дропаута
        tf.keras.layers.Dense(62, activation='softmax')
    ])
  • Использование схемы с остаточными связями (Residual connections): Это может помочь избежать деградации производительности при добавлении большего количества слоев.

2. Повышение надежности данных и их аугментация

  • Аугментация данных: Убедитесь, что ваши аугментации применяются правильно. Вы уже используете ImageDataGenerator, но попробуйте настроить параметры аугментации (например, увеличить rotation_range, width_shift_range и т.д.), чтобы ваши данные были более разнообразными.

    generator = ImageDataGenerator(
        rotation_range=30,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,
        fill_mode='nearest'
    )
  • Перепроверка нормализации данных: Это критически важно для CNN. Убедитесь, что ваши данные правильно нормализованы до диапазона [0, 1] или [-1, 1].

3. Оптимизация функций обучения

  • Пробуйте разные оптимизаторы и параметры обучения: Вы используете Adam с фиксированной learning rate. Попробуйте адаптивные схемы обучения, такие как ReduceLROnPlateau, и разные инициализации весов.

    adam_optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)  # Попробуйте меньшую learning rate
  • Измените функцию потерь на sparse_categorical_crossentropy: Если метки в формате целых чисел, это может помочь.

4. Использование регуляризации

  • Регуляризация Dropout: Убедитесь, что вы внедрили слои Dropout, чтобы снизить переобучение. Добавьте их после полносвязных слоев.

  • Раннее прекращение обучения: Подходит, если вы видите, что модель начинает переобучаться. Вы уже используете это, но проверьте настройки patience.

5. Исправление потока данных

  • Правильная реализация генераторов: В ваших примерах есть несоответствия в использовании генератора и передачи данных в метод fit. Убедитесь, что используете их корректно.

Заключение

Учитывая ваши текущие проблемы с моделью, рекомендую вам последовательно пробовать каждое из вышеуказанных решений и наблюдать за тем, как они влияют на производительность модели. Процесс настройки конволюционных нейронных сетей требует терпения и экспериментов. Не спешите с выводами, но по мере получения результатов корректируйте направление ваших усилий. Удачи вам!

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

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