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