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

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

Операция нормализации партии. нормирует каждый входной канал через мини-пакет. Чтобы ускорить обучение сверточных нейронных сетей и уменьшать чувствительность к сетевой инициализации, используйте операции нормализации партии. между свертками и нелинейностью, такой как слои 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 функционируйте загружает изображения, их метки цифры и их углы вращения от вертикали. Создайте 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)

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

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

  • convolution-batchnorm-ReLU блокируется с 16 фильтрами 5 на 5.

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

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

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

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

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

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

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

Создайте struct parameters содержа параметры модели. Инициализируйте learnable веса слоя и смещения с помощью 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');

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

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]

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

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

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

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

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

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

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

numEpochs = 20;
miniBatchSize = 128;

plots = "training-progress";

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Похожие темы