Обучите сиамскую сеть для сокращения размерности

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

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

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

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

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

Загрузите и предварительно обработайте обучающие данные

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

[XTrain,YTrain] = digitTrain4DArrayData;

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

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

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

Создайте пары подобных и отличающихся изображений

Чтобы обучить сеть, данные должны быть сгруппированы в пары изображений, которые или подобны или отличаются. Здесь, подобные изображения заданы как наличие той же метки, в то время как отличающиеся изображения имеют различные метки. Функциональный getSiameseBatch (заданный в разделе Supporting Functions этого примера), создает рандомизированные пары подобных или отличающихся изображений, 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 парных изображений создается для каждой итерации учебного цикла. Это гарантирует, что сеть обучена на большом количестве случайных пар изображений приблизительно с равными пропорциями подобных и отличающихся пар.

Архитектура сети Define

Сиамская сетевая архитектура проиллюстрирована в следующей схеме.

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

Для первых двух полносвязных слоев задайте выходной размер 1 024 и используйте Его инициализатор веса.

Для итогового полносвязного слоя задайте выходной размер два и используйте инициализатор весов Его.

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);

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

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

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

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

loss=12yd2+12(1-y)max(margin-d,0)2,

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

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

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

Задайте опции обучения

Задайте значение margin использовать во время обучения.

margin = 0.3;

Задайте опции, чтобы использовать во время обучения. Обучайтесь для 3 000 итераций.

numIterations = 3000;
miniBatchSize = 180;

Задайте опции для оптимизации ADAM:

  • Установите скорость обучения на 0.0001.

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

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

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

Обучайтесь на графическом процессоре, если вы доступны. Используя графический процессор требует Parallel Computing 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 функция, определяемая в разделе Create Batches of Image Pairs.

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

  • Для обучения графического процессора преобразуйте данные изображения в 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

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

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

Можно использовать обучивший сеть, чтобы найти выбор изображений, которые похожи друг на друга из группы. В этом случае используйте тестовые данные в качестве группы изображений. Преобразуйте группу изображений к 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);

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

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 введен в разделе Define Model Gradients Function.

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 введен в разделе Create Pairs of Similar и Dissimilar Images.

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] Бромли, J. i. Guyon, И. Лекун, Э. Зекингер и Р. Шах. "Верификация подписи с помощью "сиамской" Нейронной сети С временной задержкой". В Продолжениях 6-й Международной конференции по вопросам Нейронных Систем обработки информации (NIPS 1993), 1994, pp737-744. Доступный при Верификации Подписи с помощью "сиамской" Нейронной сети С временной задержкой на веб-сайте Продолжений NIPS.

[2] Wenpeg, Y. и H Schütze. "Сверточная нейронная сеть для Идентификации Пересказа". В Продолжениях 2 015 Конференций североамериканского Cahapter ACL, 2015, pp901-911. Доступный в Сверточной нейронной сети для Идентификации Пересказа на веб-сайте Антологии ACL.

[3] Hadsell, R., С. Чопра и И. Лекун. "Сокращение размерности путем Обучения Инвариантному Отображению". В Продолжениях 2 006 Конференций Общества эпохи компьютеризации IEEE по Компьютерному зрению и Распознаванию образов (CVPR 2006), 2006, pp1735-1742.

Смотрите также

| | | |

Похожие темы