Обучите сеть классификации изображений, устойчивую к соперничающим примерам

В этом примере показано, как обучить нейронную сеть, которая устойчива к соперничающим примерам с помощью быстрого метода знака градиента (FGSM) соперничающее обучение.

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

Методы для создания соперничающих примеров включают FGSM [2] и основной итерационный метод (BIM) [3], также известный как спроектированный градиентный спуск [4]. Эти методы могут значительно ухудшить точность сети.

Можно использовать соперничающее обучение [5], чтобы обучить нейронные сети, которые устойчивы к соперничающим примерам. В этом примере показано, как к:

  1. Обучите сеть классификации изображений.

  2. Исследуйте сетевую робастность путем генерации соперничающих примеров.

  3. Обучите сеть классификации изображений, которая устойчива к соперничающим примерам.

Загрузите обучающие данные

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

rng default
[XTrain,TTrain] = digitTrain4DArrayData;

dsXTrain = arrayDatastore(XTrain,'IterationDimension',4);
dsTTrain = arrayDatastore(TTrain);

dsTrain = combine(dsXTrain,dsTTrain);

Извлеките имена классов.

classes = categories(TTrain);

Создайте сетевую архитектуру

Задайте сеть классификации изображений.

layers = [
    imageInputLayer([28 28 1],'Normalization','none','Name','input')
    convolution2dLayer(3,32,'Padding',1,'Name','conv1')
    reluLayer('Name','relu1')
    convolution2dLayer(3,64,'Padding',1,'Name','conv3')
    reluLayer('Name','relu3')
    maxPooling2dLayer(2,'Stride',2,'Name','pool')
    fullyConnectedLayer(10,'Name','fc2')
    softmaxLayer('Name','softmax')];
lgraph = layerGraph(layers);

Создайте dlnetwork объект от графика слоев.

dlnet = dlnetwork(lgraph);

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

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

Обучение сети

Обучите сеть с помощью пользовательского учебного цикла.

Задайте опции обучения. Обучайтесь в течение 30 эпох с мини-пакетным размером 100 и скоростью обучения 0,01.

numEpochs = 30;
miniBatchSize = 100;
learnRate = 0.01;
executionEnvironment = "auto";

Создайте minibatchqueue возразите, что процессы и управляют мини-пакетами изображений во время обучения. Для каждого мини-пакета:

  • Используйте пользовательский мини-пакет, предварительно обрабатывающий функциональный preprocessMiniBatch (заданный в конце этого примера), чтобы преобразовать метки в одногорячие закодированные переменные.

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

  • Обучайтесь на графическом процессоре, если вы доступны. По умолчанию, minibatchqueue объект преобразует каждый выход в gpuArray если графический процессор доступен. Используя графический процессор требует Parallel Computing Toolbox™ и поддерживаемого устройства графического процессора. Для получения информации о поддерживаемых устройствах смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox).

mbq = minibatchqueue(dsTrain, ...
    'MiniBatchSize',miniBatchSize,...
    'MiniBatchFcn',@preprocessMiniBatch,...
    'MiniBatchFormat',{'SSCB',''});

Инициализируйте график процесса обучения.

figure
lineLossTrain = animatedline('Color',[0.85 0.325 0.098]);
ylim([0 inf])
xlabel("Iteration")
ylabel("Loss")
grid on

Инициализируйте скоростной параметр для решателя SGDM.

velocity = [];

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

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

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

  • Отобразите прогресс обучения.

iteration = 0;
start = tic;

% Loop over epochs.
for epoch = 1:numEpochs
    % Shuffle data.
    shuffle(mbq)

    % Loop over mini-batches.
    while hasdata(mbq)
        iteration = iteration +1;

        % Read mini-batch of data.
        [dlX,dlT] = next(mbq);

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

        % Evaluate the model gradients, state, and loss.
        [gradients,state,loss] = dlfeval(@modelGradients,dlnet,dlX,dlT);
        dlnet.State = state;

        % Update the network parameters using the SGDM optimizer.
        [dlnet,velocity] = sgdmupdate(dlnet,gradients,velocity,learnRate);

        % Display the training progress.
        D = duration(0,0,toc(start),'Format','hh:mm:ss');
        addpoints(lineLossTrain,iteration,loss)
        title("Epoch: " + epoch + ", Elapsed: " + string(D))
        drawnow
    end
end

Тестирование сети

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

Создайте minibatchqueue объект, содержащий тестовые данные.

[XTest,TTest] = digitTest4DArrayData;

dsXTest = arrayDatastore(XTest,'IterationDimension',4);
dsTTest = arrayDatastore(TTest);

dsTest = combine(dsXTest,dsTTest);

mbqTest = minibatchqueue(dsTest, ...
    'MiniBatchSize',miniBatchSize, ...
    'MiniBatchFcn',@preprocessMiniBatch, ...
    'MiniBatchFormat','SSCB');

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

YPred = modelPredictions(dlnet,mbqTest,classes);
acc = mean(YPred == TTest)
acc = 0.9866

Сетевая точность очень высока.

Тестовая сеть с соперничающими входными параметрами

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

Можно сгенерировать соперничающие примеры с помощью методов, таких как FGSM и BIM. FGSM является простым методом, который делает один шаг в направлении градиента XL(X,T) из функции потерь L, относительно изображения X вы хотите найти соперничающий пример для, и метка класса T. Соперничающий пример вычисляется как

Xadv=X+ϵ.sign(XL(X,T)).

Параметр ϵ средства управления, как отличающийся соперничающие примеры смотрят от оригинальных изображений. В этом примере значения пикселей между 0 и 1, таким образом, ϵ значение 0,1 изменяет каждое отдельное пиксельное значение до 10% области значений. Значение ϵ зависит от шкалы изображений. Например, если ваше изображение вместо этого между 0 и 255, необходимо умножить это значение на 255.

BIM является простым улучшением FGSM, который применяет FGSM по нескольким итерациям и применяет порог. После каждой итерации BIM отсекает возмущение, чтобы гарантировать, что величина не превышает ϵ. Этот метод может дать к соперничающим примерам с меньшим количеством искажения, чем FGSM. Для получения дополнительной информации о генерации соперничающих примеров, смотрите, Генерируют Нецеленаправленные и Целенаправленные Соперничающие Примеры для Классификации Изображений.

Создайте соперничающие примеры с помощью BIM. Установите epsilon к 0,1.

epsilon = 0.1;

Для BIM размером возмущения управляет параметр α представление размера шага в каждой итерации. Это - когда BIM обычно берет многих, меньших, шаги FGSM в направлении градиента.

Задайте размер шага alpha и количество итераций.

alpha = 0.01;
numAdvIter = 20;

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

reset(mbqTest)
[XAdv,YPredAdv] = adversarialExamples(dlnet,mbqTest,epsilon,alpha,numAdvIter,classes);

Вычислите точность сети на соперничающих данных в качестве примера.

accAdversarial = mean(YPredAdv == TTest)
accAdversarial = 0.0114

Постройте график результатов.

visualizePredictions(XAdv,YPredAdv,TTest);

Вы видите, что точность сильно ухудшается BIM, даже при том, что возмущение изображений едва отображается.

Обучите устойчивую сеть

Можно обучить сеть, чтобы быть устойчивыми против соперничающих примеров. Один популярный метод является соперничающим обучением. Соперничающее обучение включает применение соперничающих возмущений к обучающим данным во время учебного процесса [4] [5].

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

Соперничающее обучение включает применение метода FGSM к каждому мини-пакету обучающих данных. Однако для обучения быть эффективными, эти критерии должны применяться:

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

  • Для сети, чтобы быть устойчивым к возмущениям размера ϵ, выполните обучение FGSM со значением, немного больше, чем ϵ. В данном примере во время соперничающего обучения, вы тревожите изображения с помощью размера шага α=1.25ϵ.

Обучите новую сеть с соперничающим обучением FGSM. Запустите при помощи той же нетренированной сетевой архитектуры как в исходной сети.

dlnetRobust = dlnetwork(lgraph);     

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

numIter = 1;
initialization = "random";
alpha = 1.25*epsilon;

Инициализируйте график процесса обучения.

figure
lineLossRobustTrain = animatedline('Color',[0.85 0.325 0.098]);
ylim([0 inf])
xlabel("Iteration")
ylabel("Loss")
grid on

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

velocity = [];
iteration = 0;
start = tic;

% Loop over epochs.
for epoch = 1:numEpochs
    % Shuffle data.
    shuffle(mbq)

    % Loop over mini-batches.
    while hasdata(mbq)
        iteration = iteration + 1;

        % Read mini-batch of data.
        [dlX,dlT] = next(mbq);

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

        % Apply adversarial perturbations to the data.
        dlX = basicIterativeMethod(dlnetRobust,dlX,dlT,alpha,epsilon, ...
            numIter,initialization);

        % Evaluate the model gradients, state, and loss.
        [gradients,state,loss] = dlfeval(@modelGradients,dlnetRobust,dlX,dlT);
        dlnet.State = state;

        % Update the network parameters using the SGDM optimizer.
        [dlnetRobust,velocity] = sgdmupdate(dlnetRobust,gradients,velocity,learnRate);

        % Display the training progress.
        D = duration(0,0,toc(start),'Format','hh:mm:ss');
        addpoints(lineLossRobustTrain,iteration,loss)
        title("Epoch: " + epoch + ", Elapsed: " + string(D))
        drawnow
    end
end

Протестируйте устойчивую сеть

Вычислите точность устойчивой сети на тестовых данных цифр. Точность устойчивой сети может быть немного ниже, чем неустойчивая сеть на стандартных данных.

reset(mbqTest)
YPred = modelPredictions(dlnetRobust,mbqTest,classes);
accRobust = mean(YPred == TTest)
accRobust = 0.9972

Вычислите соперничающую точность.

reset(mbqTest)
[XAdv,YPredAdv] = adversarialExamples(dlnetRobust,mbqTest,epsilon,alpha,numAdvIter,classes);
accRobustAdv = mean(YPredAdv == TTest)
accRobustAdv = 0.7558

Соперничающая точность устойчивой сети намного лучше, чем та из исходной сети.

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

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

modelGradients функционируйте берет в качестве входа dlnetwork объект dlnet и мини-пакет входных данных dlX с соответствием маркирует T и возвращает градиенты потери относительно настраиваемых параметров в dlnet, сетевое состояние и потеря. Чтобы вычислить градиенты автоматически, используйте dlgradient функция.

function [gradients,state,loss] = modelGradients(dlnet,dlX,T)

[dlYPred,state] = forward(dlnet,dlX);

loss = crossentropy(dlYPred,T);
gradients = dlgradient(loss,dlnet.Learnables);

loss = double(gather(extractdata(loss)));

end

Введите функцию градиентов

modelGradientsInput функционируйте берет в качестве входа dlnetwork объект dlnet и мини-пакет входных данных dlX с соответствием маркирует T и возвращает градиенты потери относительно входных данных dlX.

function gradient = modelGradientsInput(dlnet,dlX,T)

T = squeeze(T);
T = dlarray(T,'CB');

[dlYPred] = forward(dlnet,dlX);

loss = crossentropy(dlYPred,T);
gradient = dlgradient(loss,dlX);

end

Функция предварительной обработки мини-пакета

preprocessMiniBatch функция предварительно обрабатывает мини-пакет предикторов и меток с помощью следующих шагов:

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

  2. Извлеките данные о метке из массива входящей ячейки и конкатенируйте в категориальный массив вдоль второго измерения.

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

function [X,T] = preprocessMiniBatch(XCell,TCell)

% Concatenate.
X = cat(4,XCell{1:end});

X = single(X);

% Extract label data from the cell and concatenate.
T = cat(2,TCell{1:end});

% One-hot encode labels.
T = onehotencode(T,1);

end

Функция предсказаний модели

modelPredictions функционируйте берет в качестве входа dlnetwork объект dlnet, minibatchqueue из входных данных mbq, и сетевые классы, и вычисляют предсказания модели путем итерации по всем данным в minibatchqueue объект. Функция использует onehotdecode функционируйте, чтобы найти предсказанный класс с самым высоким счетом.

function predictions = modelPredictions(dlnet,mbq,classes)

predictions = [];

while hasdata(mbq)
    
    dlXTest = next(mbq);
    dlYPred = predict(dlnet,dlXTest);
    
    YPred = onehotdecode(dlYPred,classes,1)';
    
    predictions = [predictions; YPred];
end

end

Соперничающая функция в качестве примера

Сгенерируйте соперничающие примеры для minibatchqueue объект с помощью основного итерационного метода (BIM) и предсказывает класс соперничающих примеров с помощью обучившего сеть dlnet.

function [XAdv,predictions] = adversarialExamples(dlnet,mbq,epsilon,alpha,numIter,classes)

XAdv = {};
predictions = [];
iteration = 0;

% Generate adversarial images for each mini-batch.
while hasdata(mbq)

    iteration = iteration +1;
    [dlX,dlT] = next(mbq);

    initialization = "zero";
    
    % Generate adversarial images.
    XAdvMBQ = basicIterativeMethod(dlnet,dlX,dlT,alpha,epsilon, ...
        numIter,initialization);

    % Predict the class of the adversarial images.
    dlYPred = predict(dlnet,XAdvMBQ);
    YPred = onehotdecode(dlYPred,classes,1)';

    XAdv{iteration} = XAdvMBQ;
    predictions = [predictions; YPred];
end

% Concatenate.
XAdv = cat(4,XAdv{:});

end

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

Сгенерируйте соперничающие примеры с помощью основного итерационного метода (BIM). Этот метод запускается для нескольких итераций с порогом в конце каждой итерации, чтобы гарантировать, что записи не превышают epsilon. Когда numIter установлен в 1, это эквивалентно использованию быстрого метода знака градиента (FGSM).

function XAdv = basicIterativeMethod(dlnet,dlX,dlT,alpha,epsilon,numIter,initialization)

% Initialize the perturbation.
if initialization == "zero"
    delta = zeros(size(dlX),'like',dlX);
else
    delta = epsilon*(2*rand(size(dlX),'like',dlX) - 1);
end

for i = 1:numIter
  
    % Apply adversarial perturbations to the data.
    gradient = dlfeval(@modelGradientsInput,dlnet,dlX+delta,dlT);
    delta = delta + alpha*sign(gradient);
    delta(delta > epsilon) = epsilon;
    delta(delta < -epsilon) = -epsilon;
end

XAdv = dlX + delta;

end

Визуализируйте функцию результатов предсказания

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

function visualizePredictions(XTest,YPred,TTest)

figure
height = 4;
width = 4;
numImages = height*width;

% Select random images from the data.
indices = randperm(size(XTest,4),numImages);

XTest = extractdata(XTest);
XTest = XTest(:,:,:,indices);
YPred = YPred(indices);
TTest = TTest(indices);

% Plot images with the predicted label.
for i = 1:(numImages)
    subplot(height,width,i)
    imshow(XTest(:,:,:,i))

    % If the prediction is correct, use green. If the prediction is false,
    % use red.
    if YPred(i) == TTest(i)
        color = "\color{green}";
    else
        color = "\color{red}";
    end
    title("Prediction: " + color + string(YPred(i)))
end

end

Ссылки

[1] Szegedy, христианин, Войцех Зэремба, Илья Сутскевер, Джоан Бруна, Думитру Эрхэн, Иэн Гудфеллоу и Роб Фергус. “Заинтриговывая Свойства Нейронных сетей”. Предварительно распечатайте, представленный 19 февраля 2014. https://arxiv.org/abs/1312.6199.

[2] Весельчак, Иэн Дж., Джонатон Шленс и Кристиан Сзеджеди. “Объясняя и Используя Соперничающие Примеры”. Предварительно распечатайте, представленный 20 марта 2015. https://arxiv.org/abs/1412.6572.

[3] Куракин, Алексей, Иэн Гудфеллоу и Сами Бенхио. “Соперничающие Примеры в Материальном мире”. Предварительно распечатайте, представленный 10 февраля 2017. https://arxiv.org/abs/1607.02533.

[4] Madry, Александр, Александр Мэкелов, Людвиг Шмидт, Димитрис Ципрас и Эдриан Влэду. “К Моделям Глубокого обучения, Стойким к Соперничающим Нападениям”. Предварительно распечатайте, представленный 4 сентября 2019. https://arxiv.org/abs/1706.06083.

[5] Вонг, Эрик, Лесли Райс и Х. Зико Кольтер. “Быстро Лучше, чем Свободный: Пересматривание Соперничающего Обучения”. Предварительно распечатайте, представленный 12 января 2020. https://arxiv.org/abs/2001.03994.

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

| | | |

Похожие темы