Ускорение пользовательских функций цикла обучения

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

При использовании 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);

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

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

Создайте 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.

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

Создайте структуры parameters и state которые содержат инициализированные параметры модели и состояние, соответственно, используя modelParameters function, перечисленная в разделе Параметры модели Function примера.

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

[parameters,state] = modelParameters(numClasses,numResponses);

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

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

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

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

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

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

Задайте опции обучения. Обучайте на 20 эпох с мини-партией размером 32. Отображение графика может сделать обучение занимает больше времени. Отключите график путем установки plots переменная в "none". Чтобы включить график, установите эту переменную на "training-progress".

numEpochs = 20;
miniBatchSize = 32;
plots = "none";

Обучите ускоренную модель

Ускорите функцию градиентов модели, используя dlaccelerate функция.

accfun = dlaccelerate(@modelGradients);

Очистите все превентивные кэшированные следы ускоренной функции с помощью clearCache функция.

clearCache(accfun)

Использование 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 и функция ускоренных градиентов модели.

  • Обновляйте параметры сети с помощью 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
        % accelerated function.
        [gradients,state,loss] = dlfeval(accfun, parameters, dlX, dlT1, dlT2, 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');
            loss = double(gather(extractdata(loss)));
            addpoints(lineLossTrain,iteration,loss)
            title("Epoch: " + epoch + ", Elapsed: " + string(D))
            drawnow
        end
    end
end

Проверяйте эффективность ускоренной функции путем проверки HitRate свойство. The HitRate свойство содержит процент вызовов функций, которые повторно используют кэшированную трассировку.

accfun.HitRate
ans = 99.9679

Ускорение предсказаний

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

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

Ускорите функцию модели, используя dlaccelerate функция.

accfun2 = dlaccelerate(@model);

Очистите все превентивные кэшированные следы ускоренной функции с помощью clearCache функция.

clearCache(accfun2)

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

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

  • Укажите тот же размер мини-пакета, что и для обучения.

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

  • Для одинарного выхода datastore задайте формат пакета 'SSCB' (пространственный, пространственный, канальный, пакетный).

numOutputs = 1;
mbqTest = minibatchqueue(dsTest,numOutputs, ...
    'MiniBatchSize',miniBatchSize, ...
    'MiniBatchFcn',@preprocessMiniBatchPredictors, ...
    'MiniBatchFormat','SSCB');

Закольцовывайте мини-пакеты и классифицируйте изображения с помощью modelPredictions функции, перечисленной в конце примера.

[labelsPred,anglesPred] = modelPredictions(accfun2,parameters,state,mbqTest,classNames);

Проверяйте эффективность ускоренной функции путем проверки HitRate свойство. The HitRate свойство содержит процент вызовов функций, которые повторно используют кэшированную трассировку.

accfun2.HitRate
ans = 98.7261

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

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 функция принимает параметры модели, мини-пакет входных данных 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 функция предварительно обрабатывает данные с помощью следующих шагов:

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

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

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

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

См. также

| | | | |

Похожие темы