В этом примере показано, как обновить сетевое состояние в сети, заданной как функция.
Операция нормализации партии. нормирует каждый входной канал через мини-пакет. Чтобы ускорить обучение сверточных нейронных сетей и уменьшать чувствительность к сетевой инициализации, используйте операции нормализации партии. между свертками и нелинейностью, такой как слои 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');
Инициализируйте параметры для полносвязного слоя, соответствующего классификации выход.
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™ и поддерживаемого устройства графического процессора. Для получения информации о поддерживаемых устройствах смотрите Поддержку графического процессора Релизом (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
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
функция предварительно обрабатывает данные с помощью следующих шагов:
Извлеките данные изображения из массива входящей ячейки и конкатенируйте в числовой массив. Конкатенация данных изображения по четвертой размерности добавляет третью размерность в каждое изображение, чтобы использоваться в качестве одноэлементной размерности канала.
Извлеките метку и угловые данные из массивов входящей ячейки и конкатенируйте в категориальный массив и числовой массив, соответственно.
Одногорячий кодируют категориальные метки в числовые массивы. Кодирование в первую размерность производит закодированный массив, который совпадает с формой сетевого выхода.
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
batchnorm
| crossentropy
| dlarray
| dlconv
| dlfeval
| dlgradient
| fullyconnect
| minibatchqueue
| onehotdecode
| onehotencode
| relu
| sgdmupdate
| softmax