В этом примере показано, как обучить нейронную сеть, которая устойчива к соперничающим примерам с помощью быстрого метода знака градиента (FGSM) соперничающее обучение.
Нейронные сети могут быть восприимчивы к явлению, известному как соперничающие примеры [1], где очень небольшие изменения во входе могут заставить его быть неправильно классифицированным. Эти изменения часто незаметны людям.
Методы для создания соперничающих примеров включают FGSM [2] и основной итерационный метод (BIM) [3], также известный как спроектированный градиентный спуск [4]. Эти методы могут значительно ухудшить точность сети.
Можно использовать соперничающее обучение [5], чтобы обучить нейронные сети, которые устойчивы к соперничающим примерам. В этом примере показано, как к:
Обучите сеть классификации изображений.
Исследуйте сетевую робастность путем генерации соперничающих примеров.
Обучите сеть классификации изображений, которая устойчива к соперничающим примерам.
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);
Создайте функциональный 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 является простым методом, который делает один шаг в направлении градиента из функции потерь , относительно изображения вы хотите найти соперничающий пример для, и метка класса . Соперничающий пример вычисляется как
.
Параметр средства управления, как отличающийся соперничающие примеры смотрят от оригинальных изображений. В этом примере значения пикселей между 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 со значением, немного больше, чем . В данном примере во время соперничающего обучения, вы тревожите изображения с помощью размера шага .
Обучите новую сеть с соперничающим обучением 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
функция предварительно обрабатывает мини-пакет предикторов и меток с помощью следующих шагов:
Извлеките данные изображения из массива входящей ячейки и конкатенируйте в четырехмерный массив.
Извлеките данные о метке из массива входящей ячейки и конкатенируйте в категориальный массив вдоль второго измерения.
Одногорячий кодируют категориальные метки в числовые массивы. Кодирование в первую размерность производит закодированный массив, который совпадает с формой сетевого выхода.
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.
dlfeval
| dlnetwork
| dlgradient
| arrayDatastore
| minibatchqueue