Как исправить переобучение сверточной нейронной сети(keras)?

Ссылка скопирована
1 ответ

Начал изучать машинное обучение и уже подошёл к практике
Решил сделать нейросеть, которая разпознает числа на циферблате калькулятора
Но результат плохой
Я три дня пытался настроить её, искал материал, который мог бы помочь, или примеры, но сеть постоянно переобучается
Минимальное значение, которое я нашёл при разхождении между обучающей выборкой и тестовой, это примерно ±1.3
Мне кажется, что я что-то принципиально делаю не так, но не хватает опыта, чтобы понять, что именно
Поэтому хочу понять, есть ли явные ошибки при проектировании сети

Мои действия:

Подготовка данных:
1) Скачал примерно 150 изображений калькуляторов
2) Обрезал циферблаты
3) С помощью библиотеки Pillow привёл их к размеру 300x100 пикселей (растягивание/сжатие)
4) Составил матрицу пикселей для каждого изображения размером 300x100x3 (где 3 - это цветовые каналы RGB)
5) Загрузил всё это в базу данных PostgreSQL и добавил для каждого изображения правильный ответ в нужном формате

Формат вывода, аналогичный учебному примеру, я выбрал softmax
Однако, поскольку у меня много чисел и могут быть десятичные дроби, я использую следующий формат
На выходе я получаю матрицу размером (11, 10), где столбец 0 это позиция точки, а столбцы с 1 по 10 это числа от 0 до 9.
Используя функцию np.argmax, я определяю номер строки, соответствующей распознанному числу

Пример для числа 2.2

[ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0] - точка на 1-й позиции с конца [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 10-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 9-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 8-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 7-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 6-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 5-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 4-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 3-е число 0 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] - 2-е число 2 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] - 1-е число 2 ]

[ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0] - точка на 1-й позиции с конца [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 10-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 9-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 8-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 7-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 6-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 5-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 4-е число 0 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] - 3-е число 0 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] - 2-е число 2 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] - 1-е число 2 ]

Код нейронной сети

model = keras.Sequential(             [                 Conv2D(filters=5, kernel_size=5, activation='relu', input_shape=(300, 100, 3)),                 Conv2D(filters=5, kernel_size=5, activation='relu'),                 MaxPooling2D(pool_size=2),                   Conv2D(filters=5, kernel_size=5, activation='relu'),                 Conv2D(filters=5, kernel_size=5, activation='relu'),                 Conv2D(filters=5, kernel_size=5, activation='relu'),                 MaxPooling2D(pool_size=2),                  Conv2D(filters=5, kernel_size=5, activation='relu'),                 Conv2D(filters=5, kernel_size=5, activation='relu'),                 Conv2D(filters=5, kernel_size=5, activation='relu'),                 MaxPooling2D(pool_size=2),                   Flatten(),                 Dense(units=60, activation="relu"),                 Dense(units=60, activation="relu"),                  Dense(units=110),                 Reshape((11, 10)),                 Activation('softmax')             ]         )          model.compile(             optimizer=keras.optimizers.Adam(learning_rate=0.0001),             loss="categorical_crossentropy",             metrics=["accuracy"],         )          his = model.fit(             trainings_input,             trainings_exit,             batch_size=32,             epochs=200,             validation_split=0.2,         )          model.evaluate(trainings_input, trainings_exit)

model = keras.Sequential( [ Conv2D(filters=5, kernel_size=5, activation='relu', input_shape=(300, 100, 3)), Conv2D(filters=5, kernel_size=5, activation='relu'), MaxPooling2D(pool_size=2), Conv2D(filters=5, kernel_size=5, activation='relu'), Conv2D(filters=5, kernel_size=5, activation='relu'), Conv2D(filters=5, kernel_size=5, activation='relu'), MaxPooling2D(pool_size=2), Conv2D(filters=5, kernel_size=5, activation='relu'), Conv2D(filters=5, kernel_size=5, activation='relu'), Conv2D(filters=5, kernel_size=5, activation='relu'), MaxPooling2D(pool_size=2), Flatten(), Dense(units=60, activation="relu"), Dense(units=60, activation="relu"), Dense(units=110), Reshape((11, 10)), Activation('softmax') ] ) model.compile( optimizer=keras.optimizers.Adam(learning_rate=0.0001), loss="categorical_crossentropy", metrics=["accuracy"], ) his = model.fit( trainings_input, trainings_exit, batch_size=32, epochs=200, validation_split=0.2, ) model.evaluate(trainings_input, trainings_exit)

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

plt.plot(his.history['loss']) plt.plot(his.history['val_loss']) plt.savefig('training_validation_correlation.png')

plt.plot(his.history['loss']) plt.plot(his.history['val_loss']) plt.savefig('training_validation_correlation.png')

Как исправить переобучение сверточной нейронной сети(keras)?

Дополнительно:

150 изображений для обучения нейронки? Маловато будет. Вот и результат никакой. Классический для изучения нейронок набор данных MNIST содержит 60к картинок. На практике данных нужно как можно больше - миллионы и миллиарды, сколько бюджет и ресурсы позволяют, к тому же их дополнительно искажают по-всякому на каждой эпохе случайным образом.

  • kamenyuga, скорее всего вы правы сократил обучающую выборку на треть и результать стал гораздо хуже
  • kamenyuga, а что вы имеете ввиду под искажением на каждой эпохе?
  • Дима Zero, эта тема называется data augmentation (обычно речь именно про изображения) и присутствует во всех нормальных учебниках и туториалах про машинное обучение и нейронки для работы с картинками.
  • Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Ирина WP Ответ

    Для исправления переобучения сверточной нейронной сети в Keras можно применить несколько методов. Вот некоторые из них:

    1. Уменьшить сложность модели: Попробуйте уменьшить количество слоев или нейронов в каждом слое сети. Это может помочь предотвратить переобучение.

    model = Sequential()
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
    model.add(MaxPooling2D((2, 2)))
    model.add(Flatten())
    model.add(Dense(64, activation='relu'))
    model.add(Dense(10, activation='softmax'))

    model = Sequential() model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dense(64, activation='relu')) model.add(Dense(10, activation='softmax'))

    2. Добавить регуляризацию: Используйте методы регуляризации, такие как L1 или L2 регуляризация, чтобы уменьшить переобучение. Например, добавьте параметр kernel_regularizer к слоям Dense или Conv2D.

    from keras import regularizers
     
    model.add(Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01)))

    from keras import regularizers model.add(Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01)))

    3. Использовать Dropout: Добавьте слои Dropout после сверточных слоев или полносвязных слоев, чтобы случайным образом "выключать" нейроны во время обучения.

    model.add(Dropout(0.5))

    model.add(Dropout(0.5))

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

    from keras.preprocessing.image import ImageDataGenerator
     
    datagen = ImageDataGenerator(rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest')

    from keras.preprocessing.image import ImageDataGenerator datagen = ImageDataGenerator(rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest')

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

    from keras.callbacks import EarlyStopping
     
    early_stopping = EarlyStopping(monitor='val_loss', patience=3)

    from keras.callbacks import EarlyStopping early_stopping = EarlyStopping(monitor='val_loss', patience=3)

    Применение этих методов поможет улучшить производительность сверточной нейронной сети в Keras и предотвратить переобучение.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно