Как стать автором
Обновить

Как при помощи ИИ сделать распознавание вводимых вами рукописных цифр прямо в браузере

Время на прочтение9 мин
Количество просмотров5.5K
Всего голосов 8: ↑8 и ↓0+8
Комментарии8

Комментарии 8

Много лет назад писал статью "Нейронные сети на Javascript", тогда еще небыло TensorFlow.js и реализаций сверточных серей для JS. Функционал разпознавания цифр был реализован с помощью простого персептрона на brain.js

В Вашем варианте идет поиск границ введенного символа, поэтому более корректно распознает. В варианте автора такого нет, поэтому результат зависит от места, где нарисован символ, например, рисую ноль по середине, определяет как 0, рисую ближе к правому верхнему углу, определяет, как - 1, к левому -7.

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

Мне правда не хотелось бы обесценить ваш труд этим комментарием, но я думаю, что нейросеть нуждается в дополнительной тренировке:

Screenshot

P.S.: Новая форма для комментариев довольно непривычна

Точности модели достаточно для примера (~99 % в наборе валидации).

Конечно, можно добиться гораздо лучшего результата.

Здесь можно посмотреть примеры архитектур и их результат на MNIST.

Кроме того, можно ради интереса попробовать сеть попроще: Dropout(0.4), Dense(250, linear), Relu(), Dense(250, linear), Relu(), Dense(10, linear) с оптимизатором Adadelta(lr=5), инициализацией параметров xavier normal normalized и batch_size=500 (у меня получается после 500 эпох лучший результат со 100% точностью на обучающей и от 99.10 до 99.19% точностью на тестовой выборках; обучение не более 15 минут).

Здесь я не прав по поводу сети «попроще».
Точность от 99.10 до 99.19% на ней достигается при использовании extra training data.
Если говорить о стандартном MNIST, то для точности 99% и выше на тестовой выборке следует использовать сверточную нейронную сеть. Например, следующую:

Описание нейронной сети
=== Settings:
batch_size=500
optimizer=tf.keras.optimizers.Adadelta(learning_rate=5)
loss='categorical_crossentropy'

=== Layers:
1. Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1), padding='same'),
2. MaxPooling2D(pool_size=2, strides=2),
3. Conv2D(filters=48, kernel_size=(3, 3), activation='relu', padding='same'),
4. MaxPooling2D(pool_size=2, strides=2),
5. Dropout(0.5),
6. Flatten(),
7. Dense(500, activation='relu'),
8. Dropout(0.25),
9. Dense(10, activation='softmax')

=== Code:
model = tf.keras.models.Sequential([
                                    tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1), padding='same'),
                                    tf.keras.layers.MaxPooling2D(pool_size=2, strides=2),
                                    tf.keras.layers.Conv2D(filters=48, kernel_size=(3, 3), activation='relu', padding='same'),
                                    tf.keras.layers.MaxPooling2D(pool_size=2, strides=2),
                                    tf.keras.layers.Dropout(0.5),
                                    tf.keras.layers.Flatten(),
                                    tf.keras.layers.Dense(500, activation='relu'),
                                    tf.keras.layers.Dropout(0.3),
                                    tf.keras.layers.Dense(10, activation='softmax')
                                   ])
model.compile(optimizer=tf.keras.optimizers.Adadelta(learning_rate=5), loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit(train_data, train_labels, validation_data=(test_data, test_labels), batch_size=500, epochs=30)

15 эпох, около 5 минут, точность на обучающей 99.08%, точность на тестовой 99.41%.
Если подождать ещё 15 эпох (5 минут), то результаты ещё лучше — точность на обучающей 99.57%, точность на тестовой 99.52%.
Результаты нейронной сети, предложенной автором, немного хуже (в плане обобщения) — точность на обучающей 99.69% и точность на тестовой ~99.21% (30 эпох).

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

Это правда. Однако есть более очевидные ошибки, например, в почти идеальных случаях с цифрами 5 и 6:

Screenshot

Думаю, можно опустить этот вопрос, т.к. статья носит больше демонстративный характер.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий