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

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

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

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

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

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

Если вы используете операции нормализации партии . в функции модели, то вы должны задать поведение и для обучения, и для предсказания. Например, можно задать логическую опцию 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

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

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

[XTrain,YTrain,anglesTrain] = digitTrain4DArrayData;

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

dsTrain = combine(dsXTrain,dsYTrain,dsAnglesTrain);

classNames = categories(YTrain);
numClasses = numel(classNames);
numResponses = size(anglesTrain,2);
numObservations = numel(YTrain);

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

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

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

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

  • Блок свертки-batchnorm-ReLU с 16 фильтрами 5 на 5.

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

  • Пропускное соединение с блоком свертки-batchnorm с 32 свертками 1 на 1.

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

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

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

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

Определите параметры для каждой из операций и включите их в struct. Используйте формат parameters.OperationName.ParameterName где parameters - struct, O perationName - имя операции (для примера «conv1») и ParameterName - имя параметра (для примера - «Веса»).

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

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

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

Инициализируйте параметры для первого сверточного слоя.

filterSize = [5 5];
numChannels = 1;
numFilters = 16;

sz = [filterSize numChannels numFilters];
numOut = prod(filterSize) * numFilters;
numIn = prod(filterSize) * numFilters;

parameters.conv1.Weights = initializeGlorot(sz,numOut,numIn);
parameters.conv1.Bias = initializeZeros([numFilters 1]);

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

parameters.batchnorm1.Offset = initializeZeros([numFilters 1]);
parameters.batchnorm1.Scale = initializeOnes([numFilters 1]);
state.batchnorm1.TrainedMean = zeros(numFilters,1,'single');
state.batchnorm1.TrainedVariance = ones(numFilters,1,'single');

Инициализируйте параметры для второго сверточного слоя.

filterSize = [3 3];
numChannels = 16;
numFilters = 32;

sz = [filterSize numChannels numFilters];
numOut = prod(filterSize) * numFilters;
numIn = prod(filterSize) * numFilters;

parameters.conv2.Weights = initializeGlorot(sz,numOut,numIn);
parameters.conv2.Bias = initializeZeros([numFilters 1]);

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

parameters.batchnorm2.Offset = initializeZeros([numFilters 1]);
parameters.batchnorm2.Scale = initializeOnes([numFilters 1]);
state.batchnorm2.TrainedMean = zeros(numFilters,1,'single');
state.batchnorm2.TrainedVariance = ones(numFilters,1,'single');

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

filterSize = [3 3];
numChannels = 32;
numFilters = 32;

sz = [filterSize numChannels numFilters];
numOut = prod(filterSize) * numFilters;
numIn = prod(filterSize) * numFilters;

parameters.conv3.Weights = initializeGlorot(sz,numOut,numIn);
parameters.conv3.Bias = initializeZeros([numFilters 1]);

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

parameters.batchnorm3.Offset = initializeZeros([numFilters 1]);
parameters.batchnorm3.Scale = initializeOnes([numFilters 1]);
state.batchnorm3.TrainedMean = zeros(numFilters,1,'single');
state.batchnorm3.TrainedVariance = ones(numFilters,1,'single');

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

filterSize = [1 1];
numChannels = 16;
numFilters = 32;

sz = [filterSize numChannels numFilters];
numOut = prod(filterSize) * numFilters;
numIn = prod(filterSize) * numFilters;

parameters.convSkip.Weights = initializeGlorot(sz,numOut,numIn);
parameters.convSkip.Bias = initializeZeros([numFilters 1]);

Инициализируйте параметры и состояние для слоя нормализации партии . в пропускающем соединении.

parameters.batchnormSkip.Offset = initializeZeros([numFilters 1]);
parameters.batchnormSkip.Scale = initializeOnes([numFilters 1]);
state.batchnormSkip.TrainedMean = zeros([numFilters 1],'single');
state.batchnormSkip.TrainedVariance = ones([numFilters 1],'single');

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

sz = [numClasses 6272];
numOut = numClasses;
numIn = 6272;
parameters.fc1.Weights = initializeGlorot(sz,numOut,numIn);
parameters.fc1.Bias = initializeZeros([numClasses 1]);

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

sz = [numResponses 6272];
numOut = numResponses;
numIn = 6272;
parameters.fc2.Weights = initializeGlorot(sz,numOut,numIn);
parameters.fc2.Bias = initializeZeros([numResponses 1]);

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

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

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

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

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

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

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

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

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

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

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

numEpochs = 20;
miniBatchSize = 128;

plots = "training-progress";

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

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

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

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

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

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

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

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

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

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

trailingAvg = [];
trailingAvgSq = [];

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

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

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

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;
        
        [dlX,dlY1,dlY2] = next(mbq);
        
        % Evaluate the model gradients, state, and loss using dlfeval and the
        % modelGradients function.
        [gradients,state,loss] = dlfeval(@modelGradients, parameters, dlX, dlY1, dlY2, 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

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

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

[XTest,Y1Test,anglesTest] = digitTest4DArrayData;

dsXTest = arrayDatastore(XTest,'IterationDimension',4);
dsYTest = arrayDatastore(Y1Test);
dsAnglesTest = arrayDatastore(anglesTest);

dsTest = combine(dsXTest,dsYTest,dsAnglesTest);

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

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

[classesPredictions,anglesPredictions,classCorr,angleDiff] = modelPredictions(parameters,state,mbqTest,classNames);

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

accuracy = mean(classCorr)
accuracy = 0.9840

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

angleRMSE = sqrt(mean(angleDiff.^2))
angleRMSE = single
    6.3669

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

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 = anglesPredictions(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(classesPredictions(idx(i)));
    title("Label: " + label)
end

Моделируйте функцию

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

function [dlY1,dlY2,state] = model(parameters,dlX,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, softmax (labels)
    weights = parameters.fc1.Weights;
    bias = parameters.fc1.Bias;
    dlY1 = fullyconnect(dlY,weights,bias);
    dlY1 = softmax(dlY1);
    
    % Fully connect (angles)
    weights = parameters.fc2.Weights;
    bias = parameters.fc2.Bias;
    dlY2 = fullyconnect(dlY,weights,bias);

end

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

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

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

    doTraining = true;
    [dlY1,dlY2,state] = model(parameters,dlX,doTraining,state);
    
    lossLabels = crossentropy(dlY1,T1);
    lossAngles = mse(dlY2,T2);
    
    loss = lossLabels + 0.1*lossAngles;
    gradients = dlgradient(loss,parameters);

end

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

The modelPredictions функция принимает параметры модели, состояние сети, minibatchqueue входных данных mbq, и сетевых классов, и возвращает предсказания модели путем итерации по всем данным в minibatchqueue использование model функция со doTraining значение опции установлено в false. Функция возвращает предсказанные классы и углы, а также сравнение с истинными значениями. Для классов сравнение является вектором таковых и нулей, который представляет правильные и неправильные предсказания. Для углов сравнение является различием между предсказанным углом и истинным значением.

function [classesPredictions,anglesPredictions,classCorr,angleDiff] = modelPredictions(parameters,state,mbq,classes)

    doTraining = false;
    
    classesPredictions = [];
    anglesPredictions = [];
    classCorr = [];
    angleDiff = [];
    
    while hasdata(mbq)
        [dlX,dlY1,dlY2] = next(mbq);
        
        % Make predictions using the model function.
        [dlY1Pred,dlY2Pred] = model(parameters,dlX,doTraining,state);
        
        % Determine predicted classes.
        Y1PredBatch = onehotdecode(dlY1Pred,classes,1);
        classesPredictions = [classesPredictions Y1PredBatch];
        
        % Dermine predicted angles
        Y2PredBatch = extractdata(dlY2Pred);
        anglesPredictions = [anglesPredictions Y2PredBatch];
        
        % Compare predicted and true classes
        Y1 = onehotdecode(dlY1,classes,1);
        classCorr = [classCorr Y1PredBatch == Y1];
        
        % Compare predicted and true angles
        angleDiffBatch = Y2PredBatch - dlY2;
        angleDiff = [angleDiff extractdata(gather(angleDiffBatch))];
        
    end

end

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

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

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

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

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

function [X,Y,angle] = preprocessMiniBatch(XCell,YCell,angleCell)
    
    % Extract image data from cell and concatenate
    X = cat(4,XCell{:});
    % Extract label data from cell and concatenate
    Y = cat(2,YCell{:});
    % Extract angle data from cell and concatenate
    angle = cat(2,angleCell{:});
        
    % One-hot encode labels
    Y = onehotencode(Y,1);    
    
end

См. также

| | | | | | | | | | | |

Похожие темы