Комментарии 8
Много лет назад писал статью "Нейронные сети на Javascript", тогда еще небыло TensorFlow.js и реализаций сверточных серей для JS. Функционал разпознавания цифр был реализован с помощью простого персептрона на brain.js
В Вашем варианте идет поиск границ введенного символа, поэтому более корректно распознает. В варианте автора такого нет, поэтому результат зависит от места, где нарисован символ, например, рисую ноль по середине, определяет как 0, рисую ближе к правому верхнему углу, определяет, как - 1, к левому -7.
Мне правда не хотелось бы обесценить ваш труд этим комментарием, но я думаю, что нейросеть нуждается в дополнительной тренировке:
Screenshot
![](https://habrastorage.org/webt/lc/te/b0/lcteb0ruqvmqwxdawih-mbzapi8.png)
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 эпох).
Там есть один ньюанс, который автор может пофиксить, необходимо провести нормализацию нарисованного изображения: цетрировать и маштабировать нанесенный рисунок. Для того чтоб понять как проявляется проблема, напишите цифру в углу (даже если цифра будет очень правильная) будет ошибка.
Как при помощи ИИ сделать распознавание вводимых вами рукописных цифр прямо в браузере