1. Обзор
В этом руководстве мы создадим и обучим модель сверточной нейронной сети , используя библиотеку Deeplearning4j на Java.
Для получения дополнительной информации о том, как настроить библиотеку, обратитесь к нашему руководству по Deeplearning4j .
2. Классификация изображений
2.1. Постановка задачи
Предположим, у нас есть набор изображений. Каждое изображение представляет объект определенного класса. Более того, объект на изображении принадлежит к единственному известному классу. Итак, постановка задачи состоит в том, чтобы построить модель, которая сможет распознавать класс объекта на заданном изображении .
Например, допустим, у нас есть набор изображений с десятью жестами рук. Мы строим модель и обучаем ее классифицировать их. Затем, после обучения, мы можем передать другие изображения и классифицировать жесты рук на них. Разумеется, данный жест должен принадлежать к известным классам.
2.2. Представление изображения
В памяти компьютера изображение может быть представлено в виде матрицы чисел. Каждое число представляет собой значение пикселя в диапазоне от 0 до 255.
Изображение в градациях серого представляет собой двумерную матрицу. Точно так же изображение RGB представляет собой трехмерную матрицу с размерами ширины, высоты и глубины.
Как мы видим, изображение представляет собой набор чисел . Следовательно, мы можем создавать многослойные сетевые модели, чтобы обучать их классификации изображений.
3. Сверточные нейронные сети
Сверточная нейронная сеть (CNN) — это многоуровневая сетевая модель, имеющая определенную структуру. Структуру CNN можно разделить на два блока: сверточные слои и полносвязные (или плотные) слои . Давайте посмотрим на каждый из них.
3.1. Сверточный слой
Каждый сверточный слой представляет собой набор квадратных матриц, называемых ядрами . Прежде всего, они нужны нам для выполнения свертки на входном изображении. Их количество и размер могут варьироваться в зависимости от данного набора данных. В основном мы используем ядра 3×3 или 5×5 и редко 7×7. Точный размер и количество подбирается методом проб и ошибок.
Кроме того, мы случайным образом выбираем переменные ядерных матриц в начале поезда. Это веса сети.
Для выполнения свертки мы можем использовать ядро в качестве скользящего окна. Мы умножим веса ядра на соответствующие пиксели изображения и вычислим сумму. Затем мы можем переместить ядро, чтобы покрыть следующий фрагмент изображения, используя шаг (перемещение вправо) и заполнение (перемещение вниз). В результате у нас будут значения, которые будут использоваться в дальнейших вычислениях.
Короче говоря, с этим слоем мы получаем свернутое изображение . Некоторые переменные могут быть меньше нуля. Обычно это означает, что эти переменные менее важны, чем другие. Вот почему применение функции ReLU — хороший способ сократить количество вычислений.
3.2. Слой подвыборки
Слой подвыборки (или пула) — это слой сети, обычно используемый после сверточной. После свертки мы получаем множество вычисляемых переменных . Однако наша задача выбрать среди них наиболее ценные .
Подход заключается в применении алгоритма скользящего окна к свернутому изображению. На каждом шаге мы будем выбирать максимальное значение в квадратном окне предопределенного размера, обычно от 2×2 до 5×5 пикселей. В результате у нас будет меньше вычисляемых параметров. Следовательно, это сократит вычисления.
3.3. Плотный слой
Плотный (или полносвязный) слой состоит из нескольких нейронов. Этот слой нужен нам для выполнения классификации. Более того, таких последовательных слоев может быть два или более. Важно, чтобы последний слой имел размер, равный количеству классов для классификации.
Выходом сети является вероятность того, что изображение принадлежит каждому из классов . Чтобы предсказать вероятности, мы будем использовать функцию активации Softmax .
3.4. Методы оптимизации
Чтобы выполнить тренировку, нам нужно оптимизировать веса. Помните, изначально мы выбираем эти переменные случайным образом. Нейронная сеть — это большая функция . И у него много неизвестных параметров, наших весов.
Когда мы передаем изображение в сеть, она дает нам ответ . Затем мы можем построить функцию потерь, которая будет зависеть от этого ответа . Что касается обучения с учителем, у нас также есть реальный ответ — настоящий класс. Наша миссия состоит в том, чтобы минимизировать эту функцию потерь . Если нам это удастся, то наша модель хорошо обучена.
Чтобы минимизировать функцию, мы должны обновить веса сети . Для этого мы можем вычислить производную функции потерь по каждому из этих неизвестных параметров. Затем мы можем обновить каждый вес.
Мы можем увеличить или уменьшить значение веса, чтобы найти локальный минимум нашей функции потерь, потому что мы знаем наклон. Причем этот процесс итеративный и называется Gradient Descent . Обратное распространение использует градиентный спуск для распространения обновления веса от конца к началу сети.
В этом уроке мы будем использовать алгоритм оптимизации Stochastic Gradient Decent (SGD). Основная идея заключается в том, что мы случайным образом выбираем набор изображений поездов на каждом шаге. Затем применяем обратное распространение.
3.5. Метрики оценки
Наконец, после обучения сети нам нужно получить информацию о том, насколько хорошо работает наша модель.
Наиболее часто используемая метрика — это точность . Это отношение правильно классифицированных изображений ко всем изображениям. Между тем, полнота, точность и оценка F1 также являются очень важными показателями для классификации изображений .
4. Подготовка набора данных
В этом разделе мы подготовим изображения. В этом руководстве мы будем использовать встроенный набор данных CIFAR10 . Мы создадим итераторы для доступа к изображениям:
public class CifarDatasetService implements IDataSetService {
private CifarDataSetIterator trainIterator;
private CifarDataSetIterator testIterator;
public CifarDatasetService() {
trainIterator = new CifarDataSetIterator(trainBatch, trainImagesNum, true);
testIterator = new CifarDataSetIterator(testBatch, testImagesNum, false);
}
// other methods and fields declaration
}
Некоторые параметры мы можем выбрать самостоятельно. TrainBatch
и testBatch
— количество изображений на поезд и этап оценки соответственно. TrainImagesNum
и testImagesNum
— количество изображений для обучения и тестирования. Одна эпоха длится trainImagesNum
/ trainBatch
steps . Таким образом, наличие 2048 изображений поездов с размером пакета = 32 приведет к 2048/32 = 64 шагам за одну эпоху.
5. Сверточная нейронная сеть в Deeplearning4j
5.1. Построение модели
Далее, давайте построим нашу модель CNN с нуля. Для этого мы будем использовать сверточные слои, субдискретизацию (объединение) и полносвязные (плотные) слои .
MultiLayerConfiguration configuration = new NeuralNetConfiguration.Builder()
.seed(1611)
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.learningRate(properties.getLearningRate())
.regularization(true)
.updater(properties.getOptimizer())
.list()
.layer(0, conv5x5())
.layer(1, pooling2x2Stride2())
.layer(2, conv3x3Stride1Padding2())
.layer(3, pooling2x2Stride1())
.layer(4, conv3x3Stride1Padding1())
.layer(5, pooling2x2Stride1())
.layer(6, dense())
.pretrain(false)
.backprop(true)
.setInputType(dataSetService.inputType())
.build();
network = new MultiLayerNetwork(configuration);
Здесь мы указываем скорость обучения, алгоритм обновления, тип ввода нашей модели и многоуровневую архитектуру . Мы можем поэкспериментировать с этими конфигурациями. Таким образом, мы можем обучать множество моделей с различной архитектурой и параметрами обучения. Кроме того, мы можем сравнить результаты и выбрать лучшую модель.
5.2. Обучение модели
Затем мы обучим построенную модель. Это можно сделать в несколько строк кода:
public void train() {
network.init();
IntStream.range(1, epochsNum + 1).forEach(epoch -> {
network.fit(dataSetService.trainIterator());
});
}
Количество эпох — это параметр, который мы можем указать сами . У нас есть небольшой набор данных. В результате будет достаточно нескольких сотен эпох.
5.3. Оценка модели
Наконец, мы можем оценить уже обученную модель. Библиотека Deeplearning4j позволяет легко это сделать:
public Evaluation evaluate() {
return network.evaluate(dataSetService.testIterator());
}
Оценка
— это объект, который содержит вычисленные метрики после обучения модели. Это точность, точность, отзыв и оценка F1 . Кроме того, он имеет дружественный интерфейс для печати:
==========================Scores=====================
# of classes: 11
Accuracy: 0,8406
Precision: 0,7303
Recall: 0,6820
F1 Score: 0,6466
=====================================================
6. Заключение
В этом руководстве мы узнали об архитектуре моделей CNN, методах оптимизации и метриках оценки. Кроме того, мы реализовали модель с помощью библиотеки Deeplearning4j на Java.
Как обычно, код для этого примера доступен на GitHub .