exponenta event banner

Обучение сиамской сети уменьшению размерности

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

Сиамская сеть - это тип сети глубокого обучения, которая использует две или более идентичных подсетей, которые имеют одинаковую архитектуру и совместно используют одни и те же параметры и веса. Сиамские сети обычно используются в задачах, которые включают в себя поиск взаимосвязи между двумя сопоставимыми вещами. Некоторые распространенные приложения для сиамских сетей включают распознавание лиц, проверку подписи [1] или идентификацию перефразирования [2]. Сиамские сети хорошо справляются с этими задачами, потому что их общие веса означают, что во время обучения нужно изучать меньше параметров, и они могут дать хорошие результаты с относительно небольшим количеством данных обучения.

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

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

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

Загрузка и предварительная обработка данных обучения

Загрузите обучающие данные, состоящие из изображений рукописных цифр. Функция digitTrain4DArrayData загружает цифровые изображения и их метки.

[XTrain,YTrain] = digitTrain4DArrayData;

XTrain множество 28 на 28 на 1 на 5000, содержащее 5 000 одноканальных изображений, каждый размер 28 на 28. Значения каждого пикселя находятся между 0 и 1. YTrain - категориальный вектор, содержащий метки для каждого наблюдения, представляющие собой числа от 0 до 9, соответствующие значению записанной цифры.

Отображение случайного выбора изображений.

perm = randperm(numel(YTrain), 9);
imshow(imtile(XTrain(:,:,:,perm),"ThumbnailSize",[100 100]));

Создание пар похожих и разнородных изображений

Чтобы обучить сеть, данные должны быть сгруппированы в пары изображений, которые похожи или отличаются друг от друга. Здесь подобные изображения определяются как имеющие одну и ту же метку, в то время как разные изображения имеют разные метки. Функция getSiameseBatch (определено в разделе «Вспомогательные функции» этого примера) создает рандомизированные пары похожих или разнородных изображений, pairImage1 и pairImage2. Функция также возвращает метку pairLabel, который идентифицирует, является ли пара изображений похожей или непохожей друг на друга. Подобные пары изображений имеют pairLabel = 1, в то время как разные пары имеют pairLabel = 0.

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

batchSize = 10;
[pairImage1,pairImage2,pairLabel] = getSiameseBatch(XTrain,YTrain,batchSize);

Отображение созданных пар изображений.

for i = 1:batchSize
subplot(2,5,i)
imshow([pairImage1(:,:,:,i) pairImage2(:,:,:,i)]);
if pairLabel(i) == 1
    s = "similar";
else
    s = "dissimilar";
end
title(s)
end

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

Определение сетевой архитектуры

Архитектура сиамской сети показана на следующей схеме.

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

Для первых двух полностью соединенных слоев укажите размер выхода 1024 и используйте инициализатор He weight.

Для конечного полностью подключенного слоя укажите размер вывода два и используйте инициализатор He weights.

layers = [
    imageInputLayer([28 28],'Name','input1','Normalization','none')
    fullyConnectedLayer(1024,'Name','fc1','WeightsInitializer','he')
    reluLayer('Name','relu1')
    fullyConnectedLayer(1024,'Name','fc2','WeightsInitializer','he')
    reluLayer('Name','relu2')
    fullyConnectedLayer(2,'Name','fc3','WeightsInitializer','he')];

lgraph = layerGraph(layers);

Чтобы обучить сеть с помощью пользовательского цикла обучения и включить автоматическое дифференцирование, преобразуйте график слоев в dlnetwork объект.

dlnet = dlnetwork(lgraph);

Определение функции градиентов модели

Создание функции modelGradients (определено в разделе «Вспомогательные функции» данного примера). modelGradients функция принимает сиамский dlnetwork объект dlnet and мини-пакет входных данных dlX1 и dlX2 с их этикетками pairLabels. Функция возвращает значения потерь и градиенты потерь относительно обучаемых параметров сети.

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

Найти контрастные потери между выходами последнего полностью подключенного уровня, векторы признаков features1 и features1 от pairImage1 и pairImage2соответственно. Контрастные потери для пары даны в [3]

потеря = 12yd2 + 12 (1-y) max (margin-d, 0) 2,

где y - значение метки пары (y = 1 для аналогичных изображений; y = 0 для разнородных изображений), а d - евклидово расстояние между двумя векторами признаков f1 и f2: d=‖f1-f2‖2.

Параметр margin используется для ограничения: если два изображения в паре отличаются друг от друга, то их расстояние должно быть как минимум margin, либо возникнут потери.

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

Укажите параметры обучения

Укажите значение запаса для использования во время обучения.

margin = 0.3;

Укажите параметры для использования во время обучения. Обучение для 3000 итераций.

numIterations = 3000;
miniBatchSize = 180;

Укажите параметры оптимизации ADAM:

  • Установка коэффициента обучения на 0.0001.

  • Инициализируйте среднюю градиентную скорость и среднюю градиентно-квадратную скорость затухания с помощью [].

  • Задать коэффициент градиентного затухания равным 0.9 и квадрат градиентного коэффициента распада до 0.99.

learningRate = 1e-4;
trailingAvg = [];
trailingAvgSq = [];
gradDecay = 0.9;
gradDecaySq = 0.99;

Обучение на GPU, если он доступен. Для использования графического процессора требуется Toolbox™ параллельных вычислений и поддерживаемое устройство графического процессора. Сведения о поддерживаемых устройствах см. в разделе Поддержка графического процессора по выпуску (Parallel Computing Toolbox). Для автоматического определения наличия графического процессора и размещения соответствующих данных на графическом процессоре установите значение executionEnvironment кому "auto". Если у вас нет графического процессора или вы не хотите использовать его для обучения, установите значение executionEnvironment кому "cpu". Для обеспечения использования графического процессора для обучения установите значение executionEnvironment кому "gpu".

executionEnvironment = "auto";

Для контроля хода обучения можно построить график потерь обучения после каждой итерации. Создание переменной plots который содержит "training-progress". Если вы не хотите отображать ход обучения, установите для этого значения значение "none".

plots = "training-progress";

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

plotRatio = 16/9;

if plots == "training-progress"
    trainingPlot = figure;
    trainingPlot.Position(3) = plotRatio*trainingPlot.Position(4);
    trainingPlot.Visible = 'on';
    
    trainingPlotAxes = gca;
    
    lineLossTrain = animatedline(trainingPlotAxes);
    xlabel(trainingPlotAxes,"Iteration")
    ylabel(trainingPlotAxes,"Loss")
    title(trainingPlotAxes,"Loss During Training")
end

Чтобы оценить, насколько хорошо работает сеть при уменьшении размерности, вычислите и постройте график уменьшенных характеристик набора тестовых данных после каждой итерации. Загрузите тестовые данные, состоящие из изображений рукописных цифр, аналогичных обучающим данным. Преобразование тестовых данных в dlarray и укажите метки размеров 'SSCB' (пространственный, пространственный, канальный, пакетный). При использовании графического процессора преобразуйте тестовые данные в gpuArray.

[XTest,YTest] = digitTest4DArrayData;
dlXTest = dlarray(single(XTest),'SSCB');

% If training on a GPU, then convert data to gpuArray.
if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
    dlXTest = gpuArray(dlXTest);           
end 

Инициализируйте параметры графика для графика с уменьшенными характеристиками тестовых данных.

dimensionPlot = figure;
dimensionPlot.Position(3) = plotRatio*dimensionPlot.Position(4);
dimensionPlot.Visible = 'on';

dimensionPlotAxes = gca;

uniqueGroups = unique(YTest);
colors = hsv(length(uniqueGroups));

Инициализируйте счетчик, чтобы отслеживать общее число итераций.

iteration = 1;

Модель поезда

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

Для каждой итерации:

  • Извлеките пакет пар изображений и меток с помощью getSiameseBatch функция, определенная в разделе Создание пакетов пар изображений.

  • Преобразовать данные изображения в dlarray объекты с базовым типом single и укажите метки размеров 'SSCB' (пространственный, пространственный, канальный, пакетный).

  • Для обучения GPU преобразуйте данные изображения в gpuArray объекты.

  • Оценка градиентов модели с помощью dlfeval и modelGradients функция.

  • Обновление параметров сети с помощью adamupdate функция.

% Loop over mini-batches.
for iteration = 1:numIterations
    
    % Extract mini-batch of image pairs and pair labels
    [X1,X2,pairLabels] = getSiameseBatch(XTrain,YTrain,miniBatchSize);
    
    % Convert mini-batch of data to dlarray. Specify the dimension labels
    % 'SSCB' (spatial, spatial, channel, batch) for image data
    dlX1 = dlarray(single(X1),'SSCB');
    dlX2 = dlarray(single(X2),'SSCB');
    
    % If training on a GPU, then convert data to gpuArray.
    if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
        dlX1 = gpuArray(dlX1);
        dlX2 = gpuArray(dlX2);
    end       
    
    % Evaluate the model gradients and the generator state using
    % dlfeval and the modelGradients function listed at the end of the
    % example.
    [gradients,loss] = dlfeval(@modelGradients,dlnet,dlX1,dlX2,pairLabels,margin);
    lossValue = double(gather(extractdata(loss)));
    
    % Update the Siamese network parameters.
    [dlnet.Learnables,trailingAvg,trailingAvgSq] = ...
        adamupdate(dlnet.Learnables,gradients, ...
        trailingAvg,trailingAvgSq,iteration,learningRate,gradDecay,gradDecaySq);
    
    % Update the training loss progress plot.
    if plots == "training-progress"
        addpoints(lineLossTrain,iteration,lossValue);
    end
            
    % Update the reduced-feature plot of the test data.        
    % Compute reduced features of the test data:
    dlFTest = predict(dlnet,dlXTest);
    FTest = extractdata(dlFTest);
       
    figure(dimensionPlot);
    for k = 1:length(uniqueGroups)
        % Get indices of each image in test data with the same numeric 
        % label (defined by the unique group):
        ind = YTest==uniqueGroups(k);
        % Plot this group:
        plot(dimensionPlotAxes,gather(FTest(1,ind)'),gather(FTest(2,ind)'),'.','color',...
            colors(k,:));
        hold on
    end
    
    legend(uniqueGroups)
    
    % Update title of reduced-feature plot with training progress information.
    title(dimensionPlotAxes,"2-D Feature Representation of Digits Images. Iteration = " +...
        iteration);
    legend(dimensionPlotAxes,'Location','eastoutside');
    xlabel(dimensionPlotAxes,"Feature 1")
    ylabel(dimensionPlotAxes,"Feature 2")
    
    hold off    
    drawnow    
end

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

Использование обученной сети для поиска похожих изображений

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

groupX = XTest;

dlGroupX = dlarray(single(groupX),'SSCB');

if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
    dlGroupX = gpuArray(dlGroupX);           
end 

Извлеките один тестовый образ из группы и просмотрите его. Удалите тестовый образ из группы, чтобы он не появлялся в наборе аналогичных изображений.

testIdx = randi(5000);
testImg = dlGroupX(:,:,:,testIdx);

trialImgDisp = extractdata(testImg);

figure
imshow(trialImgDisp, 'InitialMagnification', 500);

dlGroupX(:,:,:,testIdx) = [];

Найдите уменьшенные возможности тестового изображения с помощью predict.

trialF = predict(dlnet,testImg);

Найдите 2-D уменьшенное представление каждого из изображений в группе с помощью обученной сети.

FGroupX = predict(dlnet,dlGroupX);

Используйте уменьшенное представление элемента для поиска девяти изображений в группе, ближайших к тестовому изображению, с помощью евклидовой метрики расстояния. Отображение изображений.

distances = vecnorm(extractdata(trialF - FGroupX));
[~,idx] = sort(distances);
sortedImages = groupX(:,:,:,idx);

figure
imshow(imtile(sortedImages(:,:,:,1:9)), 'InitialMagnification', 500);

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

Вспомогательные функции

Функция градиентов модели

Функция modelGradients принимает сиамцев dlnetwork объект dlnet, пара входных данных мини-партии X1 и X2и этикетка pairLabels. Функция возвращает градиенты потерь относительно обучаемых параметров в сети, а также контрастные потери между признаками уменьшенной размерности парных изображений. В этом примере функция modelGradients вводится в разделе Определение функции градиентов модели.

function [gradients, loss] = modelGradients(net,X1,X2,pairLabel,margin)
% The modelGradients function calculates the contrastive loss between the
% paired images and returns the loss and the gradients of the loss with 
% respect to the network learnable parameters

    % Pass first half of image pairs forward through the network
    F1 = forward(net,X1);
    % Pass second set of image pairs forward through the network
    F2 = forward(net,X2);
    
    % Calculate contrastive loss
    loss = contrastiveLoss(F1,F2,pairLabel,margin);
    
    % Calculate gradients of the loss with respect to the network learnable
    % parameters
    gradients = dlgradient(loss, net.Learnables);

end

function loss = contrastiveLoss(F1,F2,pairLabel,margin)
% The contrastiveLoss function calculates the contrastive loss between
% the reduced features of the paired images 
    
    % Define small value to prevent taking square root of 0
    delta = 1e-6;
    
    % Find Euclidean distance metric
    distances = sqrt(sum((F1 - F2).^2,1) + delta);
    
    % label(i) = 1 if features1(:,i) and features2(:,i) are features
    % for similar images, and 0 otherwise
    lossSimilar = pairLabel.*(distances.^2);
 
    lossDissimilar = (1 - pairLabel).*(max(margin - distances, 0).^2);
    
    loss = 0.5*sum(lossSimilar + lossDissimilar,'all');
end

Создание пакетов пар изображений

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

function [X1,X2,pairLabels] = getSiameseBatch(X,Y,miniBatchSize)
% getSiameseBatch returns a randomly selected batch of paired images. 
% On average, this function produces a balanced set of similar and 
% dissimilar pairs.
    pairLabels = zeros(1, miniBatchSize);
    imgSize = size(X(:,:,:,1));
    X1 = zeros([imgSize 1 miniBatchSize]);
    X2 = zeros([imgSize 1 miniBatchSize]);
    
    for i = 1:miniBatchSize
        choice = rand(1);
        if choice < 0.5
            [pairIdx1, pairIdx2, pairLabels(i)] = getSimilarPair(Y);
        else
            [pairIdx1, pairIdx2, pairLabels(i)] = getDissimilarPair(Y);
        end
        X1(:,:,:,i) = X(:,:,:,pairIdx1);
        X2(:,:,:,i) = X(:,:,:,pairIdx2);
    end
    
end

function [pairIdx1,pairIdx2,pairLabel] = getSimilarPair(classLabel)
% getSimilarPair returns a random pair of indices for images
% that are in the same class and the similar pair label = 1.

    % Find all unique classes.
    classes = unique(classLabel);
    
    % Choose a class randomly which will be used to get a similar pair.
    classChoice = randi(numel(classes));
    
    % Find the indices of all the observations from the chosen class.
    idxs = find(classLabel==classes(classChoice));
    
    % Randomly choose two different images from the chosen class.
    pairIdxChoice = randperm(numel(idxs),2);
    pairIdx1 = idxs(pairIdxChoice(1));
    pairIdx2 = idxs(pairIdxChoice(2));
    pairLabel = 1;
end

function  [pairIdx1,pairIdx2,pairLabel] = getDissimilarPair(classLabel)
% getDissimilarPair returns a random pair of indices for images
% that are in different classes and the dissimilar pair label = 0.

    % Find all unique classes.
    classes = unique(classLabel);
    
    % Choose two different classes randomly which will be used to get a dissimilar pair.
    classesChoice = randperm(numel(classes), 2);
    
    % Find the indices of all the observations from the first and second classes.
    idxs1 = find(classLabel==classes(classesChoice(1)));
    idxs2 = find(classLabel==classes(classesChoice(2)));
    
    % Randomly choose one image from each class.
    pairIdx1Choice = randi(numel(idxs1));
    pairIdx2Choice = randi(numel(idxs2));
    pairIdx1 = idxs1(pairIdx1Choice);
    pairIdx2 = idxs2(pairIdx2Choice);
    pairLabel = 0;
end

Ссылки

[1] Бромли, Дж., И. Гайон, Я. ЛеКанн, Э. Зекингер и Р. Шах. «Проверка подписи с использованием» сиамской «нейронной сети задержки времени». В трудах 6-й Международной конференции по нейронным системам обработки информации (NIPS 1993), 1994, pp737-744. Доступна при проверке подписи с использованием нейронной сети задержки времени «Siamese» на веб-сайте NIPS Proceedings.

[2] Венпег, Ю. и Х. Шютце. «Сверточная нейронная сеть для идентификации парафраза». В трудах 2015 года Конференция Североамериканского кахаптера ACL, 2015, pp901-911. Доступен в сверточной нейронной сети для идентификации парафраза на сайте ACL Anthology.

[3] Hadsell, R., С. Чопра и И. Леканн. «Уменьшение размерности путем изучения инвариантного сопоставления». В трудах Конференции IEEE Computer Society 2006 по компьютерному зрению и распознаванию образов (CVPR 2006), 2006, pp1735-1742.

См. также

| | | |

Связанные темы