Этот пост я решил написать, для тех, кто также искал понятный код и рабочий пример, который можно было взять, вставить в гугл колаб(google colab) и сразу начать "играться" с кодом. Но не нашел. Для вас, друзья!

P.S весь код будет в конце.

Импортируем бэкэнд кераса, по началу, мы его использовать не будем, но некоторые функции нам понадобятся

import tensorflow as tf

Импортируем сам пакет машинного обучения , его и будем использовать.

import keras

Математические функции которые нам тоже понадобятся.

import numpy as np

Библиотека для вывода изображений.

import matplotlib.pyplot as plt

Для чего эта строчка? - нагуглите сами.

%matplotlib inline

Имортируем слои, вернее классы слоёв для нашей нейронной сети.

from keras.layers import Dense, Flatten

Импорт нашей последовательной моде��и.

from keras.models import Sequential

Импортируем набор данных MNIST для нашего обучения.

from keras.datasets import mnist

Загружаем данные функцией load_data из названия нашего датасета mnist и разделяем наш датасет на тренировочную выборку и тестовую.

(X_train, y_train), (X_test, y_test) = mnist.load_data()

Давайте посмотрим, что за изображения у нас и в какой они форме.

print(X_train.shape)

Вот, мы видим, что X_train представляет из себя массив данных с 60000 экземпляров картинок, которые имеют разрешение 28 на 28.

Теперь давайте посмотрим , что такое y_train.

print(y_train.shape)

Мы видим , что это просто массив из 60000 значений не и более того.

А теперь давайте посмотрим, что же именно храниться в массивах, если X_train - массив изображений, давайте откроем одно!

Выводим 12 изображение из массива, и это цифра 3

plt.imshow(X_train[12], cmap='binary')
plt.axis('off')
print(y_train[12])

Вот мы и видим цифра 3 и картинку с цифрой 3!

Как вы все знаете, значение пикселя может быть от 0 до 255, и если мы будем подавать в нейронную сеть такие данные. Пиксель со значением 0 и пиксель со значением 255 имеют очень разные масштабы значений. Нам очень тяжело будет учить модель.

И чтобы их "нормировать", чтобы они были от 0 до 1 в идеале, мы разделим все наше "добро" на 255.

0 / 255 = 0 , 255 / 255 = 1, а любое число в диапазоне от 0 не до 255 будет просто дробью.

X_train = X_train/255
X_test = X_test/255

Вот что мы получили:

print(y_train[0])

К сожалению, нельзя дать нейронке фото и сказать что это цифра 4, нужно это значение "векторизировать", это делается вот так:

y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

Получилось:

print(y_train[0])

Теперь давайте напишем саму модель нейронной сети.

Инициализируем нашу модель.

model = Sequential()

Дальше создаем наш первый слой, в нём будет 32 нейрона, также нужно указать форму входимых данных.

model.add(Dense(32, activation='relu', input_shape=(X_train[0].shape)))

Ещё дальше создаем 4 нейрона с такой же функцией активации.

model.add(Dense(64, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(256, activation='relu'))
model.add(Dense(512, activation='relu'))

Мы вытягиваем данные в вектор.

model.add(Flatten())

И тут мы сравниваем вектор с вектором, по сути это так.

model.add(Dense(10, activation='sigmoid'))

Тут компилируем нашу модель, оптимайзер - адам, потому-что он очень "классный", "categorical_crossentropy" - т.к мы определяем категории объектов.

model.compile(loss='categorical_crossentropy', 
              optimizer='adam', 
              metrics=['accuracy'])

Теперь тренируем модель:

model.fit(X_train, y_train, epochs=50 )

Мы обучили нашу нейронную сеть и теперь, давайте посмотрим на результат.

Будем использовать команду "model.evaluate", если перевести дословно - модель.оценивать

Принимает проверочный датасет и смотрим какая потеря и какая точность:

Как мы видим, точность - 96%.

Создадим переменную k и запишем туда номер изображения в датасете и будем его вызывать.

Указали цифру 6, значит цифра 4 находится под индексом 6.

k = 6
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])

Давайте укажем индекс 10, получили цифру 0.

k = 10
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])

Теперь посмотрим, как именно работает наша нейронная сеть.

k = 6
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])
print(
    model.predict(np.array([X_test[k]]))
)

[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.] - единичка под индексом 4 , соответственно - цифра 4. 

Визуально на картинке мы тоже видим цифру 4.

Теперь давайте рассмотрим ответ нейронной сети:

[[0.0000000e+00, 9.9408084e-18, 2.8947007e-22, 2.9116518e-10, 1.0000000e+00,

  4.6417094e-17, 3.7773155e-38, 5.8520163e-07,, 3.7786970e-24, 4.3130936e-07]]

* - буква e это значение степени, рассмотрим число - 4.6417094e-17 

число 4.6417094e-17 - это условно 4.6427 в минус 17 степени,  это  примерно 0.00000000000000004642 то есть очень маленькое число.

Посмотрим на весь массив и увидим, что есть число 0 в 0-ой степени ,  числа в отрицательной степени , и то, что нам нужно 1 в степени 0, любое число в нулевой степени равно единице.

Максимальный элемент массива под индексом 4, соответственно, цифра- 4.

Изменим индекс и посмотрим, что будет.

k = 10
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])
print(
    model.predict(np.array([X_test[k]]))
)

Тут видим, что исходя из степенней и чисел, мы видим, что большее число под индексом 0, соответственно и цифра 0. 

Надеюсь, вам понравился мой пост и он будет вам полезен, вот весь код для вставки в гугл колаб:

import tensorflow as tf

import keras

import numpy as np

import matplotlib.pyplot as plt
%matplotlib inline
 
from keras.layers import Dense, Flatten

from keras.models import Sequential

from keras.datasets import mnist

(X_train, y_train), (X_test, y_test) = mnist.load_data()

print(X_train.shape)

print(y_train.shape)

plt.imshow(X_train[12], cmap='binary')
plt.axis('off')
print(y_train[12])

X_train = X_train/255
X_test = X_test/255

print(y_train[0])

y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

print(y_train[0])

model = Sequential()

model.add(Dense(32, activation='relu', input_shape=(X_train[0].shape)))

model.add(Dense(64, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(256, activation='relu'))
model.add(Dense(512, activation='relu'))

model.add(Flatten())

model.add(Dense(10, activation='sigmoid'))

model.compile(loss='categorical_crossentropy', 
              optimizer='adam', 
              metrics=['accuracy'])

model.fit(X_train, y_train, epochs=50 )


k = 6
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])

k = 10
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])

2 блок кода:

k = 6
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])
print(
    model.predict(np.array([X_test[k]]))
)


k = 10
plt.imshow(X_test[k], cmap='binary')
plt.axis('off')
print(y_test[k])
print(
    model.predict(np.array([X_test[k]]))
)