Обучите сложенные автоэнкодеры для классификации изображений

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

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

Один из способов эффективного обучения нейронной сети с несколькими слоями - это обучение одного слоя за раз. Вы можете добиться этого, обучив специальный тип сети, известный как автоэнкодер для каждого желаемого скрытого слоя.

В этом примере показано, как обучить нейронную сеть с двумя скрытыми слоями для классификации цифр в изображениях. Сначала вы обучаете скрытые слои индивидуально без проверки с помощью автоэнкодеров. Затем вы обучаете конечный слой softmax и соединяете слои вместе, чтобы сформировать сложенную сеть, которую вы обучаете один последний раз контролируемым образом.

Набор данных

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

Каждое цифровое изображение составляет 28 на 28 пикселей, и существует 5000 примеров обучения. Можно загрузить обучающие данные и просмотреть некоторые изображения.

% Load the training data into memory
[xTrainImages,tTrain] = digitTrainCellArrayData;

% Display some of the training images
clf
for i = 1:20
    subplot(4,5,i);
    imshow(xTrainImages{i});
end

Метки для изображений хранятся в матрице 10 на 5000, где в каждом столбце один элемент будет равен 1, чтобы указать класс, которому принадлежит цифра, а все другие элементы в столбце будут равны 0. Следует отметить, что если десятый элемент равен 1, то цифровое изображение равняется нулю.

Обучение первого автоэнкодера

Начните с настройки разреженного автоэнкодера на обучающих данных без использования меток.

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

Нейронные сети имеют веса, случайным образом инициализированные перед обучением. Поэтому результаты обучения каждый раз различаются. Чтобы избежать такого поведения, явным образом установите seed генератора случайных чисел.

rng('default')

Установите размер скрытого слоя для автоэнкодера. Для автоэнкодера, который вы собираетесь обучать, рекомендуется сделать это меньше, чем размер входа.

hiddenSize1 = 100;

Тип автоэнкодера, который вы будете обучать, является разреженным автоэнкодером. Этот автоэнкодер использует регуляризаторы, чтобы узнать разреженное представление на первом слое. Можно управлять влиянием этих регуляторов путем установки различных параметров:

  • L2WeightRegularization управляет влиянием регулятора L2 на веса сети (а не смещения). Обычно это должно быть довольно мало.

  • SparsityRegularization управляет влиянием регулятора разреженности, который пытается применить ограничение на разреженность выхода из скрытого слоя. Обратите внимание, что это отличается от применения регулятора разреженности к весам.

  • SparsityProportion является параметром регулятора разреженности. Он управляет разреженностью выхода из скрытого слоя. Низкое значение для SparsityProportion обычно приводит к тому, что каждый нейрон в скрытом слое «специализируется», давая только высокий выход для небольшого количества обучающих примеров. Для примера, если SparsityProportion установлено равным 0,1, это эквивалентно утверждению, что каждый нейрон в скрытом слое должен иметь средний выход 0,1 по сравнению с обучающими примерами. Это значение должно быть от 0 до 1. Идеальное значение варьируется в зависимости от характера задачи.

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

autoenc1 = trainAutoencoder(xTrainImages,hiddenSize1, ...
    'MaxEpochs',400, ...
    'L2WeightRegularization',0.004, ...
    'SparsityRegularization',4, ...
    'SparsityProportion',0.15, ...
    'ScaleData', false);

Можно просмотреть схему автоэнкодера. Автоэнкодер состоит из энкодера, за которой следует декодер. Энкодер преобразует вход в скрытое представление, и декодер пытается обратить это отображение назад, чтобы восстановить исходный вход.

view(autoenc1)

Визуализация весов первого автоэнкодера

Отображение, выученное частью энкодера автоэнкодера, может быть полезным для извлечения функций из данных. Каждый нейрон в энкодере имеет связанный с ним вектор весов, который будет настроен, чтобы ответить на конкретную визуальную функцию. Можно просмотреть представление этих функций.

figure()
plotWeights(autoenc1);

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

100-мерный выход из скрытого слоя автоэнкодера является сжатой версией входа, которая суммирует свою реакцию на визуализированные выше функции. Обучите следующий автоэнкодер для набора из этих векторов, извлеченных из обучающих данных. Во-первых, необходимо использовать энкодер из обученного автоэнкодера, чтобы сгенерировать функции.

feat1 = encode(autoenc1,xTrainImages);

Настройка второго автоэнкодера

После обучения первого автоэнкодера вы подобным образом обучаете второй автоэнкодер. Основным различием является то, что вы используете функции, которые были сгенерированы из первого автоэнкодера, в качестве обучающих данных во втором автоэнкодере. Кроме того, вы уменьшаете размер скрытого представления до 50, так что энкодер во втором автоэнкодере узнает еще меньшее представление входных данных.

hiddenSize2 = 50;
autoenc2 = trainAutoencoder(feat1,hiddenSize2, ...
    'MaxEpochs',100, ...
    'L2WeightRegularization',0.002, ...
    'SparsityRegularization',4, ...
    'SparsityProportion',0.1, ...
    'ScaleData', false);

Еще раз можно просмотреть схему автоэнкодера с view функция.

view(autoenc2)

Можно извлечь второй набор функций, передав предыдущий набор через энкодер от второго автоэнкодера.

feat2 = encode(autoenc2,feat1);

Исходные векторы в обучающих данных имели 784 размерности. После прохождения их через первый энкодер это сократилось до 100 размерностей. После использования второго энкодера это снова уменьшили до 50 размерностей. Теперь можно обучить конечный слой, чтобы классифицировать эти 50-мерные векторы в различные классы цифр.

Настройка последнего слоя softmax

Обучите слой softmax для классификации 50-мерных векторов функций. В отличие от автоэнкодеров, вы обучаете слой softmax под наблюдением с помощью меток для обучающих данных.

softnet = trainSoftmaxLayer(feat2,tTrain,'MaxEpochs',400);

Можно просмотреть схему слоя softmax с view функция.

view(softnet)

Формирование сложенной нейронной сети

Вы обучили три отдельных компонента сложенной нейронной сети в изоляции. На данной точке может быть полезно просмотреть три нейронные сети, которые вы обучили. Они autoenc1, autoenc2, и softnet.

view(autoenc1)
view(autoenc2)
view(softnet)

Как было объяснено, энкодеры из автоэнкодеров использовались для извлечения функций. Можно сложить энкодеры из автоэнкодеров вместе с слоем softmax, чтобы сформировать сложенную сеть для классификации.

stackednet = stack(autoenc1,autoenc2,softnet);

Можно просмотреть схему сложенной сети с view функция. Сеть формируется энкодерами из автоэнкодеров и слоя softmax.

view(stackednet)

При сформированной полной сети можно вычислить результаты на тестовом наборе. Чтобы использовать изображения со сложенной сетью, вы должны перестроить тестовые изображения в матрицу. Вы можете сделать это, сложив столбцы изображения, чтобы сформировать вектор, и затем сформировав матрицу из этих векторов.

% Get the number of pixels in each image
imageWidth = 28;
imageHeight = 28;
inputSize = imageWidth*imageHeight;

% Load the test images
[xTestImages,tTest] = digitTestCellArrayData;

% Turn the test images into vectors and put them in a matrix
xTest = zeros(inputSize,numel(xTestImages));
for i = 1:numel(xTestImages)
    xTest(:,i) = xTestImages{i}(:);
end

Можно визуализировать результаты с помощью матрицы неточностей. Числа в нижнем правом квадрате матрицы дают общую точность.

y = stackednet(xTest);
plotconfusion(tTest,y);

Тонкая настройка сложенной нейронной сети

Результаты для сложенной нейронной сети могут быть улучшены путем выполнения обратного распространения по всей многослойной сети. Этот процесс часто упоминается как тонкая настройка.

Вы отлично настраиваете сеть, переобучая ее на обучающих данных контролируемым образом. Прежде чем вы сможете сделать это, вы должны перестроить обучающие изображения в матрицу, как это было сделано для тестовых изображений.

% Turn the training images into vectors and put them in a matrix
xTrain = zeros(inputSize,numel(xTrainImages));
for i = 1:numel(xTrainImages)
    xTrain(:,i) = xTrainImages{i}(:);
end

% Perform fine tuning
stackednet = train(stackednet,xTrain,tTrain);

Затем результаты снова просматриваются с помощью матрицы неточностей.

y = stackednet(xTest);
plotconfusion(tTest,y);

Сводные данные

Этот пример показал, как обучить сложенную нейронную сеть классифицировать цифры в изображениях с помощью автоэнкодеров. Шаги, которые были описаны, могут быть применены к другим подобным задачам, таким как классификация изображений букв или даже небольших изображений объектов определенной категории.

Для просмотра документации необходимо авторизоваться на сайте