Следующим этапом введения в компьютерное зрение является переход к более широкораспространенному инструменту в современных исследованиях, а именно нейронным сетям.
Знакомство с нейронными сетями начнем с фреймворка Keras. И на базе того же датасета MNIST попробуем сначала обучить собственную сверточную нейронную сеть.
По умолчанию Keras имеет в своей основе TensorFlow, который имеет достаточно хорошую поддержку GPU.
Импортируем зависимости, которые нам понадобятся:
import os
import matplotlib.pyplot as plt
import numpy as np
import keras
from keras.datasets import mnist
from sklearn.metrics import confusion_matrix
from sklearn.utils.multiclass import unique_labels
Загрузка датасета
Keras имеет из коробки функционал по загрузке интересующего нас датасета, потому им и воспользуемся.
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
Подготовка датасета и параметров обучения
Далее зададим переменные с параметрами датасета и настройками обучения. В нашем случаем размер изображения 28×28, число классов 10. В качестве настроек обучения примем размер подвыборки 512 изображений и длительность обучения 10 эпох.
Деление датасета на подвыборки приводит к уменьшению общности выборки на которой оптимизируются веса модели, однако позволяет производить обучение на больших датасетах последовательно оптимизируя модель для всех подвыборок из него. Основная причина использования подвыборок — ограничение на объем памяти и размера обучающей модели.
Кроме того, зададим путь для сохранения модели и имя модели.
# Размер изображения
img_rows, img_cols = 28, 28
# Число классов в датасете
num_classes = 10
# Размер подвыборки для обучения
batch_size = 512
# Количество эпох обучения
epochs = 10
# Путь для сохранения обученной модели и имя модели
save_dir = os.path.join(os.getcwd(), 'saved_models')
model_name = 'keras_mnist_trained_model.h5'
Следующие команды преобразуют размерность входных данных в соответствии с форматом изображений, принятым в используемом бэкэнде Keras (это может быть как TensorFlow, так и Teano)
from keras import backend as K
if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
Теперь преобразуем значение пикселя из целочисленного значения в число с плавающей точкой и нормализуем его на диапазон [0, 1]
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
Следующим шагом является преобразование значение класса каждого изображения из целочисленного значения от 0 до 9 в вектор из 10 элементов. Для примера выведем первый.
# Convert class vectors to binary class matrices.
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
print(y_test[0])
Создание модели
Следующим шагом является создание нейросетевой модели, например, последовательной модели Keras.
Последовательные модели, в отличие от функцицональных более просты в использовании, однако не позволяют реализовывать служные структуры модели. Однако, для целей демонстрации их достаточно.
Для добавления слоев в последовательную модель используется метод add.
- В строке 5 создается объект модели.
- В строке 6 добавляется входной сверточный слой с указанием размерности входа.
- В последующих строках добавляются слои модели.
В предложенной модели используются следующие слои:
- Conv2D — сверточный слой
- Activation — слой активации
- MaxPooling2D -слой дискретизации на основе выборки . Цель состоит в том, чтобы уменьшить выборку входного представления (изображение, выходную матрицу скрытого слоя и т. Д.), Уменьшив его размерность и сделав допущения относительно предположений о свойствах, содержащихся в выбранных субрегионах. Работает на основе выбора максимального значения из подвыборки размером pool_size. По умолчанию подвыборка сдвигается без перекрытия.
- Dropout — слой прореживания для решения проблемы переобучения сети
- Flatten — преобразование в одномерный вектор
- Dense — полносвязный слой
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
input_shape=x_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
После того, как модель сформирована, ее необходимо скомпилировать с указанием функции потерь, оптимизатора и метрики. В нашем случае в качестве функции потерь используется categorical_crossentropy, метрика точности и оптимизатор Ададельта.
После компиляции производится обучение модели методом fit. В метод передаются введенные ранее параметры и данные для обучения и тестирования.
По окончанию обучения проведем проверку, вычислив отклик сети на тестовые данные, и выведем итоговые значения функции потерь и точности.
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
Визуализация результата
Для визуализации результатов обучения также как и ранее воспользуемся confusion matrix.
Получим вектора ожидаемых и предсказанных значений с помощью argmax по первой оси данных. Это преобразование необходимо, т.к. класс в модели представляется с помощью вектора степеней принадлежности и необходимо выбрать индекс с маскимальным значением.
expected = np.argmax(y_test, 1)
predicted = np.argmax(model.predict(x_test), 1)
Введем имена классов и построим матрицу.
class_names = np.array(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])
# Plot non-normalized confusion matrix
plot_confusion_matrix(expected, predicted, classes=class_names,
title='Confusion matrix, without normalization')
Как видно по визуализации матрицы, качество классификатора существенно выше, чем при использовании классических методок машинного обучения.
Уведомление: Компьютерное зрение. Введение | Digiratory
Уведомление: Состязательные (Adversarial) атаки с помощью Keras и TensorFlow | Digiratory