Обновите статистику нормализации партии. Используя функцию модели

В этом примере показано, как обновить сетевое состояние в сети, заданной как функция.

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

Во время обучения операции нормализации партии. сначала нормируют активации каждого канала путем вычитания мини-среднего значения партии и деления на мини-пакетное стандартное отклонение. Затем операция переключает вход learnable смещением β и масштабирует его learnable масштабным коэффициентом γ.

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

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

Если вы используете операции нормализации партии. в функции модели, то необходимо задать поведение и для обучения и для предсказания. Например, можно задать булев параметр doTraining управлять, использует ли модель мини-пакетную статистику в статистике набора обучающих данных или набора данных для предсказания.

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

if doTraining
    [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm1.TrainedMean = trainedMean;
    state.batchnorm1.TrainedVariance = trainedVariance;
else
    dlY = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
end

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

digitTrain4DArrayData функционируйте загружает изображения, их метки цифры и их углы вращения от вертикали.

[XTrain,YTrain,anglesTrain] = digitTrain4DArrayData;
classNames = categories(YTrain);
numClasses = numel(classNames);
numObservations = numel(YTrain);

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

idx = randperm(numObservations,64);
I = imtile(XTrain(:,:,:,idx));
figure
imshow(I)

Задайте модель глубокого обучения

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

  • Блок свертки, нормализации партии., операций ReLU с 16 фильтрами 5 на 5

  • Ветвь двух блоков свертки и операций нормализации партии., каждого с 32 3х3 фильтрами и разделенный операцией ReLU

  • Связь пропуска с блоком свертки и операций нормализации партии. с 32 свертками 1 на 1

  • Объедините обе ветви с помощью операции сложения, сопровождаемой операцией ReLU

  • Для регрессии выход, ветвь с полностью операцией connect размера 1 (количество ответов)

  • Для классификации выход, ветвь с полностью операцией connect размера 10 (количество классов) и softmax операцией

Задайте и инициализируйте параметры модели и состояние

Задайте параметры для каждой из операций и включайте их в struct. Используйте формат parameters.OperationName.ParameterName где parameters struct, OperationName имя операции (например, conv_1), и ParameterName имя параметра (например, Weights).

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

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

parameters.conv1.Weights = dlarray(initializeGaussian([5,5,1,16]));
parameters.conv1.Bias = dlarray(zeros(16,1,'single'));

parameters.batchnorm1.Offset = dlarray(zeros(16,1,'single'));
parameters.batchnorm1.Scale = dlarray(ones(16,1,'single'));
state.batchnorm1.TrainedMean = zeros(16,1,'single');
state.batchnorm1.TrainedVariance  = ones(16,1,'single');

parameters.convSkip.Weights = dlarray(initializeGaussian([1,1,16,32]));
parameters.convSkip.Bias = dlarray(zeros(32,1,'single'));

parameters.batchnormSkip.Offset = dlarray(zeros(32,1,'single'));
parameters.batchnormSkip.Scale = dlarray(ones(32,1,'single'));
state.batchnormSkip.TrainedMean = zeros(32,1,'single');
state.batchnormSkip.TrainedVariance = ones(32,1,'single');

parameters.conv2.Weights = dlarray(initializeGaussian([3,3,16,32]));
parameters.conv2.Bias = dlarray(zeros(32,1,'single'));

parameters.batchnorm2.Offset = dlarray(zeros(32,1,'single'));
parameters.batchnorm2.Scale = dlarray(ones(32,1,'single'));
state.batchnorm2.TrainedMean = zeros(32,1,'single');
state.batchnorm2.TrainedVariance  = ones(32,1,'single');

parameters.conv3.Weights = dlarray(initializeGaussian([3,3,32,32]));
parameters.conv3.Bias = dlarray(zeros(32,1,'single'));

parameters.batchnorm3.Offset = dlarray(zeros(32,1,'single'));
parameters.batchnorm3.Scale = dlarray(ones(32,1,'single'));
state.batchnorm3.TrainedMean = zeros(32,1,'single');
state.batchnorm3.TrainedVariance  = ones(32,1,'single');

parameters.fc2.Weights = dlarray(initializeGaussian([numClasses,6272]));
parameters.fc2.Bias = dlarray(zeros(numClasses,1,'single'));

parameters.fc1.Weights = dlarray(initializeGaussian([1,6272]));
parameters.fc1.Bias = dlarray(zeros(1,1,'single'));

Просмотрите struct состояния.

state
state = struct with fields:
       batchnorm1: [1×1 struct]
    batchnormSkip: [1×1 struct]
       batchnorm2: [1×1 struct]
       batchnorm3: [1×1 struct]

Просмотрите параметры состояния для batchnorm1 операция.

state.batchnorm1
ans = struct with fields:
        TrainedMean: [16×1 single]
    TrainedVariance: [16×1 single]

Функция модели Define

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

Функциональный model берет в качестве входа входные данные dlX, параметры модели parameters, флаг doTraining, который задает, возвращает ли модель выходные параметры для обучения или предсказания и сетевого state состояния. Сетевые выходные параметры предсказания для меток, предсказания для углов и обновленное сетевое состояние.

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

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

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

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

numEpochs = 20;
miniBatchSize = 128;
plots = "training-progress";

numIterationsPerEpoch = floor(numObservations./miniBatchSize);

Обучайтесь на графическом процессоре, если вы доступны. Используя графический процессор требует Parallel Computing Toolbox™, и CUDA® включил NVIDIA®, графический процессор с вычисляет возможность 3.0 или выше.

executionEnvironment = "auto";

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

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

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

Для каждого мини-пакета:

  • Преобразуйте метки в фиктивные переменные.

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

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

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

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

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

if plots == "training-progress"
    figure

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

Инициализируйте параметры для решателя Адама.

trailingAvg = [];
trailingAvgSq = [];

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

iteration = 0;
start = tic;

% Loop over epochs.
for epoch = 1:numEpochs
    
    % Shuffle data.
    idx = randperm(numObservations);
    XTrain = XTrain(:,:,:,idx);
    YTrain = YTrain(idx);
    anglesTrain = anglesTrain(idx);
    
    % Loop over mini-batches
    for i = 1:numIterationsPerEpoch
        iteration = iteration + 1;
        idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
        
        % Read mini-batch of data and convert the labels to dummy
        % variables.
        X = XTrain(:,:,:,idx);
        
        Y1 = zeros(numClasses, miniBatchSize, 'single');
        for c = 1:numClasses
            Y1(c,YTrain(idx)==classNames(c)) = 1;
        end
        
        Y2 = anglesTrain(idx)';
        Y2 = single(Y2);
        
        % Convert mini-batch of data to dlarray.
        dlX = dlarray(X,'SSCB');
        
        % If training on a GPU, then convert data to gpuArray.
        if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
            dlX = gpuArray(dlX);
        end
        
        % Evaluate the model gradients, state, and loss using dlfeval and the
        % modelGradients function.
        [gradients,state,loss] = dlfeval(@modelGradients, dlX, Y1, Y2, parameters, state);
        
        % Update the network parameters using the Adam optimizer.
        [parameters,trailingAvg,trailingAvgSq] = adamupdate(parameters,gradients, ...
            trailingAvg,trailingAvgSq,iteration);
        
        % Display the training progress.
        if plots == "training-progress"
            D = duration(0,0,toc(start),'Format','hh:mm:ss');
            addpoints(lineLossTrain,iteration,double(gather(extractdata(loss))))
            title("Epoch: " + epoch + ", Elapsed: " + string(D))
            drawnow
        end
    end
end

Тестовая модель

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

[XTest,YTest,anglesTest] = digitTest4DArrayData;

Преобразуйте данные в dlarray объект с форматом размерности 'SSCB'. Для предсказания графического процессора также преобразуйте данные в gpuArray.

dlXTest = dlarray(XTest,'SSCB');
if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
    dlXTest = gpuArray(dlXTest);
end

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

[dlYPred,anglesPred] = modelPredictions(parameters,state,dlXTest,miniBatchSize);

Оцените точность классификации.

[~,idx] = max(extractdata(dlYPred),[],1);
labelsPred = classNames(idx);
accuracy = mean(labelsPred==YTest)
accuracy = 0.9912

Оцените точность регрессии.

angleRMSE = sqrt(mean((extractdata(anglesPred) - anglesTest').^2))
angleRMSE =

    6.1576

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

idx = randperm(size(XTest,4),9);
figure
for i = 1:9
    subplot(3,3,i)
    I = XTest(:,:,:,idx(i));
    imshow(I)
    hold on
    
    sz = size(I,1);
    offset = sz/2;
    
    thetaPred = extractdata(anglesPred(idx(i)));
    plot(offset*[1-tand(thetaPred) 1+tand(thetaPred)],[sz 0],'r--')
    
    thetaValidation = anglesTest(idx(i));
    plot(offset*[1-tand(thetaValidation) 1+tand(thetaValidation)],[sz 0],'g--')
    
    hold off
    label = string(labelsPred(idx(i)));
    title("Label: " + label)
end

Функция модели

Функциональный model берет в качестве входа входные данные dlX, параметры модели parameters, флаг doTraining, который задает, возвращает ли модель выходные параметры для обучения или предсказания и сетевого state состояния. Функция возвращает предсказания для меток, предсказания для углов и обновленное сетевое состояние.

function [dlY1,dlY2,state] = model(dlX,parameters,doTraining,state)

% Convolution
weights = parameters.conv1.Weights;
bias = parameters.conv1.Bias;
dlY = dlconv(dlX,weights,bias,'Padding',2);

% Batch normalization, ReLU
offset = parameters.batchnorm1.Offset;
scale = parameters.batchnorm1.Scale;
trainedMean = state.batchnorm1.TrainedMean;
trainedVariance = state.batchnorm1.TrainedVariance;

if doTraining
    [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm1.TrainedMean = trainedMean;
    state.batchnorm1.TrainedVariance = trainedVariance;
else
    dlY = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
end

dlY = relu(dlY);

% Convolution, batch normalization (skip connection)
weights = parameters.convSkip.Weights;
bias = parameters.convSkip.Bias;
dlYSkip = dlconv(dlY,weights,bias,'Stride',2);

offset = parameters.batchnormSkip.Offset;
scale = parameters.batchnormSkip.Scale;
trainedMean = state.batchnormSkip.TrainedMean;
trainedVariance = state.batchnormSkip.TrainedVariance;

if doTraining
    [dlYSkip,trainedMean,trainedVariance] = batchnorm(dlYSkip,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnormSkip.TrainedMean = trainedMean;
    state.batchnormSkip.TrainedVariance = trainedVariance;
else
    dlYSkip = batchnorm(dlYSkip,offset,scale,trainedMean,trainedVariance);
end

% Convolution
weights = parameters.conv2.Weights;
bias = parameters.conv2.Bias;
dlY = dlconv(dlY,weights,bias,'Padding',1,'Stride',2);

% Batch normalization, ReLU
offset = parameters.batchnorm2.Offset;
scale = parameters.batchnorm2.Scale;
trainedMean = state.batchnorm2.TrainedMean;
trainedVariance = state.batchnorm2.TrainedVariance;

if doTraining
    [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm2.TrainedMean = trainedMean;
    state.batchnorm2.TrainedVariance = trainedVariance;
else
    dlY = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
end

dlY = relu(dlY);

% Convolution
weights = parameters.conv3.Weights;
bias = parameters.conv3.Bias;
dlY = dlconv(dlY,weights,bias,'Padding',1);

% Batch normalization
offset = parameters.batchnorm3.Offset;
scale = parameters.batchnorm3.Scale;
trainedMean = state.batchnorm3.TrainedMean;
trainedVariance = state.batchnorm3.TrainedVariance;

if doTraining
    [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm3.TrainedMean = trainedMean;
    state.batchnorm3.TrainedVariance = trainedVariance;
else
    dlY = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);
end

% Addition, ReLU
dlY = dlYSkip + dlY;
dlY = relu(dlY);

% Fully connect (angles)
weights = parameters.fc1.Weights;
bias = parameters.fc1.Bias;
dlY2 = fullyconnect(dlY,weights,bias);

% Fully connect, softmax (labels)
weights = parameters.fc2.Weights;
bias = parameters.fc2.Bias;
dlY1 = fullyconnect(dlY,weights,bias);
dlY1 = softmax(dlY1);

end

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

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

function [gradients,state,loss] = modelGradients(dlX,T1,T2,parameters,state)

doTraining = true;
[dlY1,dlY2,state] = model(dlX,parameters,doTraining,state);

lossLabels = crossentropy(dlY1,T1);
lossAngles = mse(dlY2,T2);

loss = lossLabels + 0.1*lossAngles;
gradients = dlgradient(loss,parameters);

end

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

modelPredictions функционируйте берет параметры модели, сетевое состояние, массив входных данных dlX, и мини-пакетный размер, и возвращает предсказания модели путем итерации по мини-пакетам заданного размера с помощью model функция с doTraining набор опции к false.

function [dlYPred,anglesPred] = modelPredictions(parameters,state,dlX,miniBatchSize)

doTraining = false;

numObservations = size(dlX,4);
numIterations = ceil(numObservations / miniBatchSize);

numClasses = size(parameters.fc2.Weights,1);

dlYPred = zeros(numClasses,numObservations,'like',dlX);
anglesPred = zeros(1,numObservations,'like',dlX);

for i = 1:numIterations
    idx = (i-1)*miniBatchSize+1:min(i*miniBatchSize,numObservations);
    
    [dlYPred(:,idx),anglesPred(idx)] = model(dlX(:,:,:,idx), parameters,doTraining,state);
end

end

Функция инициализации весов

initializeGaussian функциональные демонстрационные веса от Распределения Гаусса со средним значением 0 и стандартным отклонением 0.01.

function parameter = initializeGaussian(sz)
parameter = randn(sz,'single').*0.01;
end

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

| | | | | | | | |

Похожие темы