@zero35657469845465

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

Начал изучать машинное обучение и уже подошёл к практике
Решил сделать нейросеть, которая разпознает числа на циферблате калькулятора
Но результат плохой
Я три дня пытался настроить её, искал материал, который мог бы помочь, или примеры, но сеть постоянно переобучается
Минимальное значение, которое я нашёл при разхождении между обучающей выборкой и тестовой, это примерно ±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
]


Код нейронной сети
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')

65f846e862911828102666.png
  • Вопрос задан
  • 78 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы