Эксперименты с полносвязной нейросетью в Keras.Python.

Мы уже писали полносвязную сеть на Питоне своими руками. Давайте теперь поэкспериментируем с таким видом сети в библиотеке Keras. Как всегда будем работать с базой MNIST, распознавать рукописные цифры.

Однослойная сеть.

Давайте для разогрева создадим однослойную сеть . Число входящих нейронов 748 ( изображение цифр 28х28 пикселей), число выходящих 10 ( количество классификаторов от 0 до 9)

from keras.datasets import mnist
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt

Загружаем данные и приводим их к значениям от 0 — 1.

(x_rain, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype("float32")
x_test = x_test.astype("float32")
# В базе для каждого пикселя хранится значение яркости от 0 до 255.
x_train /= 255
x_test /= 255

keras.utils.to_categorical(y, num_classes=None, dtype=’float32′) . Преобразует вектор класса (целые числа) в двоичную матрицу классов.

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

Создаем слой

model = Sequential()
model.add(Dense(output_dim=10, input_dim=784, activation='softmax'))
  • input_dim=784 — число входных нейронов слоя.
  • output_dim=10 — число выходных нейронов.
  • activation='softmax' — функция активации.

Собираем модель сети:

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
  • loss='categorical_crossentropy' — Функция потерь.
  • optimizer='adam' — Оптимизатор весов .

Запускаем обучение сети. Пройдемся по базе десять раз ( эпохи) .

history = model.fit(x_train, y_train, epochs=10, verbose=2, validation_data=(x_test, y_test))
  • x_train, y_train — входные данные, картинка и ответ
  • epochs=10 — число эпох обучения (сколько раз сеть продеться по данным полностью)
  • validation_data=(x_test, y_test) — данные для тестирования сети.
  • verbose=2 — одна строка за эпоху. Лог обучения.

Да, еще добавим всяких там графиков )

Метод fit() возвращает историю обучения.

plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

Я удивлен, мы получили очень не плохой результат — 92.96 % точность распознавания. Вот так легко сделать нейросеть на Keras )))

Сеть с одним скрытым слоем. Перцептро́н, или персептрон.

Давайте добавим один скрытый слой и соберем модель классической полносвязной сети.

model = Sequential()
model.add(Dense(output_dim=350, input_dim=784, activation='relu'))
model.add(Dense(output_dim=10, activation='softmax'))

Скрытый слой у нас содержит 350 нейронов. Заметьте что нам не надо во вотром слое указывать число входящих связей, библиотека сама учитывает это в модели сети. Функция активации ReLu (rectified linear unit) — это просто замена отрицательных элементов нулем f(x) = max(0, s). Softmax — это обобщение логистической функции для многомерного случая. Функция преобразует вектор , полученные вектора представлены вещественным числом в интервале [0,1] и сумма координат равна 1.

Посмотреть структуру сети можно методом:

print(model.summary())

Сразу видно, сеть работает намного лучше . Есть даже эффект переобучения. То есть последующие этапы обучения уже начинают ухудшать результат.

Давайте попробуем еще функцию активации Сигмоиду :

model = Sequential()
model.add(Dense(output_dim=350, input_dim=784, activation='sigmoid'))
model.add(Dense(output_dim=10, activation='softmax'))

Добавим еще слой с 200 нейронами, получиться сеть с двумя скрытыми слоями.

model = Sequential()
model.add(Dense(output_dim=350, input_dim=784, activation='sigmoid'))
model.add(Dense(output_dim=200, activation='sigmoid'))
model.add(Dense(output_dim=10, activation='softmax'))

Для борьбы с переобучение сети можно попробовать добавить слой Dropout(). Dropout (в русскоязычных источниках — “метод прореживания”, “метод исключения” или просто “дропаут”). Сети для обучения получаются с помощью исключения из сети (dropping out) нейронов с вероятностью p, таким образом, вероятность того, что нейрон останется в сети, составляет q=1−p. “Исключение” нейрона означает, что при любых входных данных или параметрах он возвращает 0.

model = Sequential()
model.add(Dense(output_dim=350, input_dim=784, activation='sigmoid'))
model.add(Dropout(rate=0.2))
model.add(Dense(output_dim=200, activation='sigmoid'))
model.add(Dense(output_dim=10, activation='softmax'))

Явно дропаут пошел на пользу )))