Обучите устойчивую нейронную сеть для глубокого обучения с якобской регуляризацией

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

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

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

В этом примере показано, как:

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

  2. Сравните его предсказания с сетью, обученной без якобианской регуляризации.

Загрузка обучающих данных

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

[XTrain,YTrain] = digitTrain4DArrayData;

dsXTrain = arrayDatastore(XTrain,'IterationDimension',4);
dsYTrain = arrayDatastore(YTrain);

dsTrain = combine(dsXTrain,dsYTrain);

Определите количество классов в обучающих данных.

classes = categories(YTrain);
numClasses = numel(classes);

Затем примените шум к обучающим изображениям, чтобы создать состязательные примеры. Сравните изображения из обучающих данных без шума и с шумом, влияющим на 10% пикселей.

Выберите 16 изображений случайным образом.

numImages = size(XTrain,4);
randompick = randperm(numImages,16);
XOriginal = XTrain(:,:,:,randompick);

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

noiseProp = 0.1;
noise = rand(size(XOriginal));
idx = rand(size(XOriginal)) < noiseProp;

XNoisy = XOriginal;
XNoisy(idx) = noise(idx);

Постройте график оригинальных изображений рядом с шумными изображениями.

I1 = imtile(XOriginal);
I2 = imtile(XNoisy);

figure;
subplot(1,2,1)
imshow(I1)
subplot(1,2,2)
imshow(I2)

Определение сети

Определите архитектуру сети.

Задайте входной слой изображения того же размера, что и обучающие изображения.

imageInputSize = size(XTrain, 1:3)
imageInputSize = 1×3

    28    28     1

layers = [
    imageInputLayer(imageInputSize,'Name','input','Mean',mean(XTrain,4))
    convolution2dLayer(5,20,'Name','conv1')
    batchNormalizationLayer('Name','bn1')
    reluLayer('Name','relu1')
    convolution2dLayer(3,20,'Padding',1,'Name','conv2')
    batchNormalizationLayer('Name','bn2')
    reluLayer('Name','relu2')
    convolution2dLayer(3,20,'Padding',1,'Name','conv3')
    batchNormalizationLayer('Name','bn3')
    reluLayer('Name','relu3')
    fullyConnectedLayer(10,'Name','fc')
    softmaxLayer('Name','softmax')];
lgraph = layerGraph(layers);

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

dlnet = dlnetwork(lgraph);

Задайте функцию градиентов модели

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

Настройка опций обучения

Train на 15 эпох с мини-партией размером 32.

numEpochs = 15;
miniBatchSize = 32;

Задайте опции для оптимизации SGDM. Задайте скорость обучения 0,01 и импульс 0,9.

learningRate = 0.01;
momentum = 0.9;

Якобская регуляризация λJRявляется гиперпараметром, который контролирует эффект якобианского термина регуляризации на обучение сети. Если коэффициент слишком велик, то член перекрестной энтропии не эффективно минимизируется, и точность классификации сети плоха. Если коэффициент слишком мал, обученная сеть не имеет ожидаемой робастности с белым шумом. Для примера выберите λJR=1.

jacobianRegularizationCoefficient = 1;

Обучите модель

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

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

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

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

mbq = minibatchqueue(dsTrain,...
    'MiniBatchSize',miniBatchSize,...
    'MiniBatchFcn', @preprocessMiniBatch,...
    'PartialMiniBatch',"discard",...
    '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
    
    % Reset and shuffle mini-batch queue.
    shuffle(mbq);
    
    while hasdata(mbq)
        iteration = iteration + 1;
        
        % Read mini-batch of data.
        [dlX, dlY] = next(mbq);
     
        % Evaluate the model gradients and the network state using
        % dlfeval and the modelGradients function listed at the end of the example.
        [gradTotalLoss, state, totalLoss] = dlfeval(@modelGradients, dlnet, dlX, dlY, ...
            miniBatchSize, jacobianRegularizationCoefficient);
        dlnet.State = state;
        
        % Update the network parameters.
        [dlnet, velocity] = sgdmupdate(dlnet,gradTotalLoss,velocity,learningRate,momentum);
        
        % Plot the training progress.
        D = duration(0,0,toc(start),'Format','hh:mm:ss');
        addpoints(lineLossTrain,iteration,double(gather(extractdata(totalLoss))))
        title("Training with Jacobian regularization" + ", Epoch: " + epoch + ", Elapsed: " + string(D))
        drawnow
        
    end
end

Загрузка ссылочной сети

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

dlnetReference = load("dlnetWithoutJacobian.mat").dlnetReference;

Экспериментальная модель

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

[XTest, YTest] = digitTest4DArrayData;
classes = categories(YTest);

Проходите через тестовые изображения, которые сети не видели раньше. С каждым проходом добавьте шум, влияющий на 0% до 50% пикселей с шагами 5%.

% Initialize test parameters and arrays.
noiseProps = 0:0.05:0.5;

% Prepare arguments for mini-batch queue.
dsYTest = arrayDatastore(YTest);
miniBatchSize = 5000;
        
for i = 1:numel(noiseProps)
    % Load the noise proportion.
    noiseProp = noiseProps(i);
    fprintf("Testing robustness to noise proportion %1.2g\n", noiseProp)
    
    % Set a proportion of the pixels to a random grayscale value.         
    noise = rand(size(XTest));
    idx = rand(size(XTest)) < noiseProp;
    XNoisy = XTest;
    XNoisy(idx) = noise(idx);
    
    % Prepare mini-batch queue with noisy test data.
    dsXTest = arrayDatastore(XNoisy,'IterationDimension',4);
    dsTest = combine(dsXTest,dsYTest);
    mbq = minibatchqueue(dsTest,...
        'MiniBatchSize',miniBatchSize,...
        'MiniBatchFcn', @preprocessMiniBatch,...
        'MiniBatchFormat',{'SSCB',''});
        
    % Loop over batches to find predicted classifications.
    while hasdata(mbq)
        [dlXNoisy, dlY] = next(mbq);
        
        % Classify noisy data with the robust network.
        dlYPredNoisy = predict(dlnet, dlXNoisy);
        
        % Convert the predictions into labels.
        YPred = onehotdecode(dlYPredNoisy, classes, 1)';
        YTestBatch = onehotdecode(dlY, classes, 1)';
        
        % Evaluate accuracy of predictions.
        accuracyRobust(i) =  mean(YPred == YTestBatch);
        
        % Classify noisy data with reference network.
        dlYPredNoisy = predict(dlnetReference, dlXNoisy);
        
        % Convert the predictions into labels.
        YPred = onehotdecode(dlYPredNoisy, classes, 1)';
        
        % Evaluate accuracy of predictions.
        accuracyReference(i) =  mean(YPred == YTestBatch);
    end

end
Testing robustness to noise proportion 0
Testing robustness to noise proportion 0.05
Testing robustness to noise proportion 0.1
Testing robustness to noise proportion 0.15
Testing robustness to noise proportion 0.2
Testing robustness to noise proportion 0.25
Testing robustness to noise proportion 0.3
Testing robustness to noise proportion 0.35
Testing robustness to noise proportion 0.4
Testing robustness to noise proportion 0.45
Testing robustness to noise proportion 0.5

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

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

x = noiseProps';

figure;

plot(x,accuracyRobust*100, '-o', x,accuracyReference*100, '-o')
xlabel('Proportion of noise')
ylabel('Accuracy (%)')
xlim([0,0.5]);
ylim([0,100]);
title('Image classification accuracy')
legend('Jacobian regularization', 'Reference');

Пример конкретного теста

Добавьте шум, затрагивающий 15% пикселей, к первому тестовому изображению, которое содержит число 0. Постройте график как оригинальные изображения, так и изображения, возмущенного белым шумом. Используйте обученную якобской регуляризации сеть и ссылке сеть, чтобы классифицировать изображение.

% Choose test image
testchoice = 1;

% Add noise, with a proportion of 0.15, to the first image.
noise = rand(size(XTest(:,:,:,testchoice)));
idx = rand(size(XTest(:,:,:,testchoice))) < 0.15;
XNoisy = XTest(:,:,:,testchoice);
XNoisy(idx) = noise(idx);

% Convert to dlarray.
dlXTest  = dlarray(XTest(:,:,:,testchoice),'SSCB');
dlXNoisy = dlarray(XNoisy,'SSCB');

% Print true number classification
disp("True digit label: " + char(YTest(testchoice)));
True digit label: 0

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

dlYPredTestJR = predict(dlnet, dlXTest);
YPredTestJR = onehotdecode(dlYPredTestJR, classes, 1)';
disp("Robust network classification of original image: " + char(YPredTestJR));
Robust network classification of original image: 0

Классифицируйте шумное изображение при помощи сети, обученной якобианской регуляризации.

dlYPredNoisyJR = predict(dlnet, dlXNoisy);
YPredNoisyJR = onehotdecode(dlYPredNoisyJR, classes, 1)';
disp("Robust network classification of noisy image: " + char(YPredNoisyJR));
Robust network classification of noisy image: 0

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

dlYPredTest = predict(dlnetReference, dlXTest);
YPredTestR = onehotdecode(dlYPredTest, classes, 1)';
disp("Reference network classification of original image: " + char(YPredTestR));
Reference network classification of original image: 0

Классифицируйте шумное изображение при помощи сети, обученной без якобианской регуляризации.

dlYPredNoisy = predict(dlnetReference, dlXNoisy);
YPredNoisyR = onehotdecode(dlYPredNoisy, classes, 1)';
disp("Reference network classification of noisy image: " + char(YPredNoisyR));
Reference network classification of noisy image: 8

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

figure;
I1 = XTest(:,:,:,testchoice);
subplot(1,2,1)
imshow(I1)
title('Original image')
xlabel({"Prediction without"; "Jacobian regularization: " + char(YPredTestR);...
    "Prediction with"; "Jacobian regularization: " + char(YPredTestJR)})
I2 = XNoisy;
subplot(1,2,2)
imshow(I2)
title('Noisy image')
xlabel({"Prediction without"; "Jacobian regularization: " + char(YPredNoisyR);...
    "Prediction with"; "Jacobian regularization: " + char(YPredNoisyJR)})

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

Цель якобианской регуляризации состоит в том, чтобы наказать большие изменения предсказания y относительно небольших изменений во входе x. Это делает сеть более устойчивой к входным данным, загрязненных шумом. Якобиан J кодирует изменение предсказания относительно входов путем содержания частных производных y по отношению к x.

J=[y1x1y1xnymx1ymxn]

Якобианская регуляризация достигается путем добавления нормы Фробениуса якобиана к функции потерь, которая впоследствии минимизируется, когда вы обучаете сеть. Однако якобиан может быть дорогим в вычислении, требуя m назад проходит через сеть, где m - размер выхода y. Поэтому вместо вычисления полного якобиана приближение к норме Фробениуса якобиана (JR) вычисляется следующим образом [4]:

JF2=tr(JJ)=EvN(0,Im)vJJv1mprojk=1mprojvkJ22=1mprojk=1mprojx[vky]22.

где vkN(0,Im) является рисунком из стандартного распределения Normal и Im является единичной матрицей m на m. Это может быть реализовано следующим образом:

JR=0

Выбор размера мини-пакета B

Для i=1,,mproj

  1. Дискретизация случайного вектора vN(0,Im)

  2. Нормализуйте случайный вектор v=vv2

  3. Вычислите производную x(vy)

  4. JR=JR+mx(vy)22Bmproj

Градиент скалярного произведения вектора требует одного обратного прохода для вычисления. Таким образом, это приближение требует только mproj обратные проходы для вычисления, и на практике, mproj=1.

В этом примере перекрестная энтропия между предсказанной классификацией y и истинную классификацию z используется, что приводит к функции потерь

loss=crossentropy+λJR2JR

где λJR - якобианский коэффициент регуляризации. Приближение нормы Фробениуса якобиана требует принятия градиентов относительно xи фаза обучения требует принятия градиентов потерь относительно параметров. Эти расчеты требуют поддержки автоматической дифференциации второго порядка.

The modelGradients функция используется во время обучения сети. Он принимает за вход в сеть, входные данные dlX, их соответствующие классификации dlY, размер мини-пакета miniBatchSize, и якобианский коэффициент регуляризации jacobianRegularizationCoefficient. Функция возвращает градиент потерь относительно параметров сети gradTotalLoss, состояние сети state, и общие потери totalLoss. Чтобы вычислить приближение к норме якобиана, берётся производная векторно-векторного точечного продукта. Поскольку производная второго порядка необходима для вычисления градиента функции потерь относительно сетевых параметров, необходимо задать опцию 'EnableHigherDerivatives' на 'true' при вызове функции dlgradient.

function [gradTotalLoss, state, totalLoss] = modelGradients(net, dlX, dlY, miniBatchSize, jacobianRegularizationCoefficient)

% Find prediction and loss.
[dlZ,state] = forward(net, dlX);
loss = crossentropy(dlZ, dlY);

numClasses = size(dlZ,1);
numProjections = 1;
regularizationTerm = 0;

% Compute Jacobian term and its gradient.
for i = 1:numProjections
   
    % Sample a matrix whose elements are drawn from the standard Normal distribution.
    rndarray = randn(numClasses, miniBatchSize);
    
    % Normalize the columns of the random matrix.
    rndarray = normc(rndarray);
    
    % Compute the vector-vector product.
    vectorproduct = rndarray(:)' * dlZ(:);  
   
    % Compute the gradient of the vector-vector product. Since another
    % derivative will be taken, set EnableHigherDerivatives to true.
    vectorJacobianTerm = dlgradient(vectorproduct, dlX, 'EnableHigherDerivatives', true);
    
    % Multiply by necessary constants to obtain approximation of the
    % Frobenius norm of the Jacobian.
    regularizationTerm = regularizationTerm + numClasses*sum(vectorJacobianTerm.^2,'all') /(numProjections*miniBatchSize);
end
totalLoss = loss + jacobianRegularizationCoefficient/2 * regularizationTerm;

% Calculate the gradient of the loss.
gradTotalLoss = dlgradient(totalLoss, net.Learnables);
end

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

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

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

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

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

function [X, Y] = preprocessMiniBatch(XCell,YCell)
    % Extract image data from cell and concatenate
    X = cat(4,XCell{1:end});

    % Extract label data from cell and concatenate
    Y = cat(2,YCell{1:end});
    
    % One-hot encode labels
    Y = onehotencode(Y,1);
end

Ссылки

  1. Хоффман, Джуди, Дэниел Робертс и Шо Яида. «Устойчивое обучение с якобианской регуляризацией». Препринт, представленный 7 августа 2019 года. https://arxiv.org/abs/1908.02729.

  2. Сегеди, Кристиан, Войцех Заремба, Илья Суцкевер, Жоан Бруна, Думитру Эрхан, Иан Гудфеллоу и Роб Фергус. «Интригующие свойства нейронных сетей». Препринт, представленный 19 февраля 2014 года. http://arxiv.org/abs/1312.6199.

  3. Ма, Эйвери, Фарташ Фагхри и Амир-Масуд Фарахманд. Состязательная робастность через регуляризацию: подход второго порядка. Препринт, представленный, 3 апреля 2020 года. http://arxiv.org/abs/2004.01832.

  4. Гудфеллоу, Ян Дж., Джонатон Шленс и Кристиан Сегеди. «Объяснение и использование состязательных примеров». Препринт, представленный, 20 марта 2015 года. http://arxiv.org/abs/1412.6572.

См. также

| | | | | | | |

Похожие темы

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