В этом примере показано, как оценить увеличение эффективности использования ускоренной функции.
При использовании dlfeval
функция в пользовательском цикле обучения, программа отслеживает каждый вход dlarray
объект функции градиентов модели для определения вычислительного графика, используемого для автоматической дифференциации. Этот процесс трассировки может занять некоторое время и может потратить время на пересчет того же трассировки. Оптимизируя, кэшируя и повторно используя трассировки, можно ускорить градиентные расчеты в функциях глубокого обучения. Можно также оптимизировать, кэшировать и повторно использовать трассировки для ускорения других функций глубокого обучения, которые не требуют автоматической дифференциации, для примера можно также ускорить функции модели и функции, используемые для предсказания.
Чтобы ускорить вызовы функций глубокого обучения, используйте dlaccelerate
функция для создания AcceleratedFunction
объект, который автоматизирует, кэширует и повторно использует трассировки. Можно использовать dlaccelerate
функция для ускорения функций модели и функций градиентов непосредственно или для ускорения подфункций, используемых этими функциями. Увеличение эффективности наиболее заметно для более глубоких сетей и циклов обучения со многими эпохами и итерациями.
Возвращенный AcceleratedFunction
объект кэширует следы вызовов к базовой функции и повторно использует результат кэширования, когда тот же входной шаблон повторяется.
Попробуйте использовать dlaccelerate
для вызовов функций, которые:
являются длительными
иметь dlarray
объект, структуры dlarray
объекты, или dlnetwork
объекты как входы
не имеют побочных эффектов, таких как запись в файлы или отображение выхода
Этот пример сравнивает время обучения и предсказания при использовании, а не при использовании ускорения.
The digitTrain4DArrayData
функция загружает изображения, их метки цифр и углы поворота от вертикали. Создание arrayDatastore
объекты для изображений, меток и углов, а затем используйте combine
функция, чтобы создать один datastore, который содержит все обучающие данные. Извлеките имена классов и количество недискретных ответов.
[imagesTrain,labelsTrain,anglesTrain] = digitTrain4DArrayData;
dsImagesTrain = arrayDatastore(imagesTrain,'IterationDimension',4);
dsLabelsTrain = arrayDatastore(labelsTrain);
dsAnglesTrain = arrayDatastore(anglesTrain);
dsTrain = combine(dsImagesTrain,dsLabelsTrain,dsAnglesTrain);
classNames = categories(labelsTrain);
numClasses = numel(classNames);
numResponses = size(anglesTrain,2);
numObservations = numel(labelsTrain);
Создайте datastore, содержащий тестовые данные, предоставленные digitTest4DArrayData
функция с использованием тех же шагов.
[imagesTest,labelsTest,anglesTest] = digitTest4DArrayData;
dsImagesTest = arrayDatastore(imagesTest,'IterationDimension',4);
dsLabelsTest = arrayDatastore(labelsTest);
dsAnglesTest = arrayDatastore(anglesTest);
dsTest = combine(dsImagesTest,dsLabelsTest,dsAnglesTest);
Задайте следующую сеть, которая предсказывает и метки, и углы поворота.
Блок свертки-batchnorm-ReLU с 16 фильтрами 5 на 5.
Ветвь из двух блоков свертки-batchnorm каждый с 32 фильтрами 3 на 3 с операцией ReLU между
Пропускное соединение с блоком свертки-batchnorm с 32 свертками 1 на 1.
Объедините обе ветви с помощью сложения и последующей операции ReLU
Для вывода регрессии выход ветвь с полностью связанной операцией размера 1 (количество откликов).
Для вывода классификации выход ветвь с полностью связанной операцией размера 10 (количество классов) и операцией softmax.
Создайте struct parametersBaseline
содержащие параметры модели с помощью modelParameters
функции, перечисленной в конце примера. The modelParameters
функция создает структуры parameters
и state
которые содержат инициализированные параметры модели и состояние, соответственно.
Выходные выходы используют формат parameters.OperationName.ParameterName
где parameters
- структура, O perationName
- имя операции (для примера «conv1») и ParameterName
- имя параметра (для примера - «Веса»).
[parametersBaseline,stateBaseline] = modelParameters(numClasses,numResponses);
Создайте копию параметров и состояния для базовой модели, которая будет использоваться для ускоренной модели.
parametersAccelerated = parametersBaseline; stateAccelerated = stateBaseline;
Создайте функцию model
, перечисленный в конце примера, который вычисляет выходы модели глубокого обучения, описанной ранее.
Функция model
принимает параметры модели parameters
, входные данные dlX
, флаг doTraining
который определяет, должна ли модель возвращать выходы для обучения или предсказания, и состояние сети state
. Сеть выводит предсказания для меток, предсказания для углов и обновленное состояние сети.
Создайте функцию modelGradients
, перечисленный в конце примера, который берёт параметры модели, мини-пакет входных данных dlX
с соответствующими целями T1
и T2
содержит метки и углы, соответственно, и возвращает градиенты потерь относительно настраиваемых параметров, обновленного состояния сети и соответствующих потерь.
Задайте опции обучения. Обучайте на 20 эпох с мини-партией размером 32. Отображение графика может сделать обучение занимает больше времени. Отключите график путем установки plots
переменная в "none"
. Чтобы включить график, установите эту переменную на "training-progress"
.
numEpochs = 20;
miniBatchSize = 32;
plots = "none";
Использование 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','',''}, ... 'PartialMiniBatch','discard');
Инициализируйте параметры для Adam.
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
Обучите модель. Для каждой эпохи перетасуйте данные и закольцовывайте по мини-пакетам данных. Для каждого мини-пакета:
Оцените градиенты модели и потери с помощью dlfeval
и modelGradients
функция.
Обновляйте параметры сети с помощью adamupdate
функция.
Обновите график процесса обучения.
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,dlT1,dlT2] = next(mbq); % Evaluate the model gradients, state, and loss using dlfeval and the % model gradients function. [gradients,stateBaseline,loss] = dlfeval(@modelGradients,parametersBaseline,dlX,dlT1,dlT2,stateBaseline); % Update the network parameters using the Adam optimizer. [parametersBaseline,trailingAvg,trailingAvgSq] = adamupdate(parametersBaseline,gradients, ... trailingAvg,trailingAvgSq,iteration); % Display the training progress. if plots == "training-progress" D = duration(0,0,toc(start),'Format','hh:mm:ss'); loss = double(gather(extractdata(loss))); addpoints(lineLossTrain,iteration,loss) title("Epoch: " + epoch + ", Elapsed: " + string(D)) drawnow end end end elapsedBaseline = toc(start)
elapsedBaseline = 285.8978
Ускорите функцию градиентов модели, используя dlaccelerate
функция.
accfun = dlaccelerate(@modelGradients);
Очистите все ранее кэшированные трассировки ускоренной функции с помощью clearCache
функция.
clearCache(accfun)
Инициализируйте параметры для Adam.
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
Обучите модель, используя функцию ускоренных градиентов модели в вызове dlfeval
функция.
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,dlT1,dlT2] = next(mbq); % Evaluate the model gradients, state, and loss using dlfeval and the % accelerated function. [gradients,stateAccelerated,loss] = dlfeval(accfun, parametersAccelerated, dlX, dlT1, dlT2, stateAccelerated); % Update the network parameters using the Adam optimizer. [parametersAccelerated,trailingAvg,trailingAvgSq] = adamupdate(parametersAccelerated,gradients, ... trailingAvg,trailingAvgSq,iteration); % Display the training progress. if plots == "training-progress" D = duration(0,0,toc(start),'Format','hh:mm:ss'); loss = double(gather(extractdata(loss))); addpoints(lineLossTrain,iteration,loss) title("Epoch: " + epoch + ", Elapsed: " + string(D)) drawnow end end end elapsedAccelerated = toc(start)
elapsedAccelerated = 188.5316
Проверяйте эффективность ускоренной функции путем проверки HitRate
свойство. The HitRate
свойство содержит процент вызовов функций, которые повторно используют кэшированную трассировку.
accfun.HitRate
ans = 99.9679
Сравните время обучения на столбчатой диаграмме.
figure bar(categorical(["Baseline" "Accelerated"]),[elapsedBaseline elapsedAccelerated]); ylabel("Time (seconds)") title("Training Time")
Вычислите скорость ускорения.
speedup = elapsedBaseline / elapsedAccelerated
speedup = 1.5164
Измерьте время, необходимое для предсказаний с помощью тестовых данных набора.
После обучения создание предсказаний по новым данным не требует меток. Создание minibatchqueue
объект, содержащий только предикторы тестовых данных:
Чтобы игнорировать метки для проверки, установите количество выходов мини-очереди пакетов равным 1.
Укажите тот же размер мини-пакета, что и для обучения.
Предварительно обработайте предикторы, используя preprocessMiniBatchPredictors
функции, перечисленной в конце примера.
Для одинарного выхода datastore задайте формат пакета 'SSCB'
(пространственный, пространственный, канальный, пакетный).
numOutputs = 1; mbqTest = minibatchqueue(dsTest,numOutputs, ... 'MiniBatchSize',miniBatchSize, ... 'MiniBatchFcn',@preprocessMiniBatchPredictors, ... 'MiniBatchFormat','SSCB');
Закольцовывайте мини-пакеты и классифицируйте изображения с помощью modelPredictions
функция, перечисленная в конце примера и измеряющая истекшее время.
tic [labelsPred,anglesPred] = modelPredictions(@model,parametersBaseline,stateBaseline,mbqTest,classNames); elapsedPredictionBaseline = toc
elapsedPredictionBaseline = 5.5070
Поскольку функция предсказаний модели требует мини-пакетной очереди в качестве входных данных, функция не поддерживает ускорение. Чтобы ускорить предсказание, ускорите функцию модели.
Ускорите функцию модели, используя dlaccelerate
функция.
accfun2 = dlaccelerate(@model);
Очистите все ранее кэшированные трассировки ускоренной функции с помощью clearCache
функция.
clearCache(accfun2)
Сбросьте мини-очередь пакетов.
reset(mbqTest)
Закольцовывайте мини-пакеты и классифицируйте изображения с помощью modelPredictions
функция, перечисленная в конце примера и измеряющая истекшее время.
tic [labelsPred,anglesPred] = modelPredictions(accfun2,parametersBaseline,stateBaseline,mbqTest,classNames); elapsedPredictionAccelerated = toc
elapsedPredictionAccelerated = 4.3057
Проверяйте эффективность ускоренной функции путем проверки HitRate
свойство. The HitRate
свойство содержит процент вызовов функций, которые повторно используют кэшированную трассировку.
accfun2.HitRate
ans = 98.7261
Сравните время предсказания на столбчатой диаграмме.
figure bar(categorical(["Baseline" "Accelerated"]),[elapsedPredictionBaseline elapsedPredictionAccelerated]); ylabel("Time (seconds)") title("Prediction Time")
Вычислите скорость ускорения.
speedup = elapsedPredictionBaseline / elapsedPredictionAccelerated
speedup = 1.2790
The modelParameters
функция создает структуры parameters
и state
которые содержат инициализированные параметры модели и состояние, соответственно для модели, описанной в разделе Define Deep Learning Model. Функция принимает за вход количество классов и количество откликов и инициализирует настраиваемые параметры. Функция:
инициализирует веса слоев с помощью initializeGlorot
функция
инициализирует смещения слоя с помощью initializeZeros
функция
инициализирует параметры смещения и шкалы нормализации партии . с помощью initializeZeros
функция
инициализирует параметры шкалы нормализации партии . с помощью initializeOnes
функция
инициализирует состояние нормализации партии ., обученное среднее с initializeZeros
функция
инициализирует состояние нормализации партии ., обученное отклонение со initializeOnes
Функция , взятая в качестве примера,
Функции , взятые в качестве примера, инициализации присоединены к этому примеру как вспомогательные файлы. Чтобы получить доступ к этим файлам, откройте пример как live скрипт. Чтобы узнать больше об инициализации настраиваемых параметров для моделей глубокого обучения, смотрите Initialize Learnable Parameters for Model Function.
Выходные выходы используют формат parameters.OperationName.ParameterName
где parameters
- структура, O perationName
- имя операции (для примера «conv1») и ParameterName
- имя параметра (для примера - «Веса»).
function [parameters,state] = modelParameters(numClasses,numResponses) % First convolutional layer. 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]); % First batch normalization layer. parameters.batchnorm1.Offset = initializeZeros([numFilters 1]); parameters.batchnorm1.Scale = initializeOnes([numFilters 1]); state.batchnorm1.TrainedMean = initializeZeros([numFilters 1]); state.batchnorm1.TrainedVariance = initializeOnes([numFilters 1]); % Second convolutional layer. 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]); % Second batch normalization layer. parameters.batchnorm2.Offset = initializeZeros([numFilters 1]); parameters.batchnorm2.Scale = initializeOnes([numFilters 1]); state.batchnorm2.TrainedMean = initializeZeros([numFilters 1]); state.batchnorm2.TrainedVariance = initializeOnes([numFilters 1]); % Third convolutional layer. 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]); % Third batch normalization layer. parameters.batchnorm3.Offset = initializeZeros([numFilters 1]); parameters.batchnorm3.Scale = initializeOnes([numFilters 1]); state.batchnorm3.TrainedMean = initializeZeros([numFilters 1]); state.batchnorm3.TrainedVariance = initializeOnes([numFilters 1]); % Convolutional layer in the skip connection. 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]); % Batch normalization layer in the skip connection. parameters.batchnormSkip.Offset = initializeZeros([numFilters 1]); parameters.batchnormSkip.Scale = initializeOnes([numFilters 1]); state.batchnormSkip.TrainedMean = initializeZeros([numFilters 1]); state.batchnormSkip.TrainedVariance = initializeOnes([numFilters 1]); % Fully connected layer corresponding to the classification output. sz = [numClasses 6272]; numOut = numClasses; numIn = 6272; parameters.fc1.Weights = initializeGlorot(sz,numOut,numIn); parameters.fc1.Bias = initializeZeros([numClasses 1]); % Fully connected layer corresponding to the regression output. sz = [numResponses 6272]; numOut = numResponses; numIn = 6272; parameters.fc2.Weights = initializeGlorot(sz,numOut,numIn); parameters.fc2.Bias = initializeZeros([numResponses 1]); 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','same'); % 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','same','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','same'); % 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
function, принимает параметры модели, мини-пакет входных данных 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
объект. Функция использует onehotdecode
функция для поиска предсказанного класса с самым высоким счетом.
function [predictions1, predictions2] = modelPredictions(modelFcn,parameters,state,mbq,classes) doTraining = false; predictions1 = []; predictions2 = []; while hasdata(mbq) dlXTest = next(mbq); [dlYPred1,dlYPred2] = modelFcn(parameters,dlXTest,doTraining,state); YPred1 = onehotdecode(dlYPred1,classes,1)'; YPred2 = extractdata(dlYPred2)'; predictions1 = [predictions1; YPred1]; predictions2 = [predictions2; YPred2]; end end
The preprocessMiniBatch
функция предварительно обрабатывает данные с помощью следующих шагов:
Извлеките данные изображения из входящего массива ячеек и соедините в числовой массив. Конкатенация данных изображения по четвертому измерению добавляет третье измерение к каждому изображению, которое используется в качестве размерности одинарного канала.
Извлеките данные о метках и углах из входящих массивов ячеек и соедините вдоль второго измерения в категориальный массив и числовой массив, соответственно.
Однократное кодирование категориальных меток в числовые массивы. Кодирование в первую размерность создает закодированный массив, который совпадает с формой выходного сигнала сети.
function [X,Y,angle] = preprocessMiniBatch(XCell,YCell,angleCell) % Preprocess predictors. X = preprocessMiniBatchPredictors(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
The preprocessMiniBatchPredictors
функция предварительно обрабатывает мини-пакет предикторов путем извлечения данных изображения из массива входа ячеек и конкатенации в числовой массив. Для входов полутонового цвета, конкатенация по четвертому измерению добавляет третье измерение каждому изображению, чтобы использовать в качестве размерности синглтонного канала.
function X = preprocessMiniBatchPredictors(XCell) % Concatenate. X = cat(4,XCell{1:end}); end
AcceleratedFunction
| clearCache
| dlaccelerate
| dlarray
| dlfeval
| dlgradient