Если Deep Learning Toolbox™ не предоставляет слой, необходимый для классификации или регрессии, можно определить собственный пользовательский слой. Список встроенных слоев см. в разделе Список слоев глубокого обучения.
В примере «Определение пользовательского слоя глубокого обучения с помощью обучаемых параметров» показано, как создать пользовательский слой PreLU, и выполняются следующие шаги:
Имя слоя - присвойте слою имя, чтобы его можно было использовать в MATLAB ®.
Объявить свойства слоя (Declare the layer properties) - укажите свойства слоя и параметры, которые будут изучены во время обучения.
Создать функцию конструктора (необязательно) - укажите способ построения слоя и инициализации его свойств. Если функция конструктора не указана, то при создании программа инициализирует Name, Description, и Type свойства с [] и устанавливает количество входов и выходов слоя равным 1.
Создать функции прямой передачи - укажите способ передачи данных через уровень (прямое распространение) во время прогнозирования и во время обучения.
Создать обратную функцию (необязательно) - укажите производные потери относительно входных данных и обучаемых параметров (обратное распространение). Если функция обратного направления не указана, то функции прямого направления должны поддерживать dlarray объекты.
Если функция пересылки использует только те функции, которые поддерживают dlarray объекты, то создание обратной функции является необязательным. В этом случае программа автоматически определяет производные с помощью автоматического дифференцирования. Список функций, поддерживающих dlarray см. Список функций с поддержкой dlarray. Если вы хотите использовать функции, которые не поддерживают dlarray объекты или требуется использовать определенный алгоритм для обратной функции, то можно определить пользовательскую обратную функцию, используя этот пример в качестве руководства.
В примере «Определение пользовательского уровня глубокого обучения с учитываемыми параметрами» показано, как создать уровень PReLU. Уровень PReLU выполняет пороговую операцию, где для каждого канала любое входное значение, меньшее нуля, умножается на скаляр, усвоенный во время тренировки. [1] Для значений, меньших нуля, уровень PReLU применяет масштабные коэффициенты αi к каждому каналу входа. Эти коэффициенты формируют обучаемый параметр, который уровень изучает во время обучения.
Операция PReLU задается
xi≤0
где - вход нелинейной активации f на канале i, а - коэффициент, регулирующий наклон отрицательной части. Нижний индекс i в указывает, что нелинейная активация может изменяться на разных каналах.
Просмотрите слой, созданный в примере «Определение пользовательского слоя глубокого обучения с обучаемыми параметрами». Этот слой не имеет backward функция.
classdef preluLayer < nnet.layer.Layer % Example custom PReLU layer. properties (Learnable) % Layer learnable parameters % Scaling coefficient Alpha end methods function layer = preluLayer(numChannels, name) % layer = preluLayer(numChannels, name) creates a PReLU layer % for 2-D image input with numChannels channels and specifies % the layer name. % Set layer name. layer.Name = name; % Set layer description. layer.Description = "PReLU with " + numChannels + " channels"; % Initialize scaling coefficient. layer.Alpha = rand([1 1 numChannels]); end function Z = predict(layer, X) % Z = predict(layer, X) forwards the input data X through the % layer and outputs the result Z. Z = max(X,0) + layer.Alpha .* min(0,X); end end end
Реализация backward функция, которая возвращает производные потерь относительно входных данных и обучаемых параметров.
Синтаксис для backward является [dLdX1,…,dLdXn,dLdW1,…,dLdWk] = backward(layer,X1,…,Xn,Z1,…,Zm,dLdZ1,…,dLdZm,memory), где:
X1,…,Xn являются n вводы слоев
Z1,…,Zm являются m выходы функций прямого уровня
dLdZ1,…,dLdZm являются градиентами, распространяемыми назад от следующего слоя
memory - выходной сигнал памяти forward если forward определяется, в противном случае memory является [].
Для выходных данных, dLdX1,…,dLdXn являются производными потерь по отношению к входам слоя и dLdW1,…,dLdWk являются производными от потери в отношении k обучаемые параметры. Чтобы уменьшить использование памяти за счет предотвращения сохранения неиспользуемых переменных между прямым и обратным проходом, замените соответствующие входные аргументы на ~.
Совет
Если количество входов в backward может варьироваться, а затем использовать varargin вместо входных аргументов после layer. В этом случае varargin - массив ячеек входов, где varargin{i} соответствует Xi для i=1,…,NumInputs, varargin{NumInputs+j} и varargin{NumInputs+NumOutputs+j} соответствуют Zj и dLdZj, соответственно, для j=1,…,NumOutputs, и varargin{end} соответствует memory.
Если количество выходов может варьироваться, используйте varargout вместо выходных аргументов. В этом случае varargout - массив ячеек выходных сигналов, где varargout{i} соответствует dLdXi для i=1,…,NumInputs и varargout{NumInputs+t} соответствует dLdWt для t=1,…,k, где k - количество обучаемых параметров.
Поскольку уровень PReLU имеет только один вход, один выход, один обучаемый параметр и не требует выходных данных прямой функции уровня или значения памяти, синтаксис для backward для уровня PReLU [dLdX,dLdAlpha] = backward(layer,X,~,dLdZ,~). Размеры X те же, что и в прямой функции. Размеры dLdZ те же, что и размеры выходного сигнала Z прямой функции. Размеры и тип данных dLdX совпадают с измерениями и типом данных X. Измерение и тип данных dLdAlpha совпадает с измерением и типом данных обучаемого параметра Alpha.
Во время обратного прохода слой автоматически обновляет обучаемые параметры, используя соответствующие производные.
Для включения пользовательского уровня в сеть функции прямого уровня должны принимать выходные данные предыдущего уровня и передавать массивы с размером, ожидаемым для следующего уровня. Аналогично, когда backward указано, backward функция должна принимать входы с тем же размером, что и соответствующий выход прямой функции, и обратно распространять производные с тем же размером.
Производная потери по отношению к входным данным
∂xi
где ) - градиент, распространяемый от следующего слоя, и производная активации
< 0.
Производная потери относительно обучаемых параметров
∂αi
где i индексирует каналы, j индексирует элементы по высоте, ширине и наблюдениям, а градиент активации равен
< 0.
Создайте обратную функцию, которая возвращает эти производные.
function [dLdX, dLdAlpha] = backward(layer, X, ~, dLdZ, ~)
% [dLdX, dLdAlpha] = backward(layer, X, ~, dLdZ, ~)
% backward propagates the derivative of the loss function
% through the layer.
% Inputs:
% layer - Layer to backward propagate through
% X - Input data
% dLdZ - Gradient propagated from the deeper layer
% Outputs:
% dLdX - Derivative of the loss with respect to the
% input data
% dLdAlpha - Derivative of the loss with respect to the
% learnable parameter Alpha
dLdX = layer.Alpha .* dLdZ;
dLdX(X>0) = dLdZ(X>0);
dLdAlpha = min(0,X) .* dLdZ;
dLdAlpha = sum(dLdAlpha,[1 2]);
% Sum over all observations in mini-batch.
dLdAlpha = sum(dLdAlpha,4);
endПросмотр завершенного файла класса слоев.
classdef preluLayer < nnet.layer.Layer % Example custom PReLU layer. properties (Learnable) % Layer learnable parameters % Scaling coefficient Alpha end methods function layer = preluLayer(numChannels, name) % layer = preluLayer(numChannels, name) creates a PReLU layer % for 2-D image input with numChannels channels and specifies % the layer name. % Set layer name. layer.Name = name; % Set layer description. layer.Description = "PReLU with " + numChannels + " channels"; % Initialize scaling coefficient. layer.Alpha = rand([1 1 numChannels]); end function Z = predict(layer, X) % Z = predict(layer, X) forwards the input data X through the % layer and outputs the result Z. Z = max(X,0) + layer.Alpha .* min(0,X); end function [dLdX, dLdAlpha] = backward(layer, X, ~, dLdZ, ~) % [dLdX, dLdAlpha] = backward(layer, X, ~, dLdZ, ~) % backward propagates the derivative of the loss function % through the layer. % Inputs: % layer - Layer to backward propagate through % X - Input data % dLdZ - Gradient propagated from the deeper layer % Outputs: % dLdX - Derivative of the loss with respect to the % input data % dLdAlpha - Derivative of the loss with respect to the % learnable parameter Alpha dLdX = layer.Alpha .* dLdZ; dLdX(X>0) = dLdZ(X>0); dLdAlpha = min(0,X) .* dLdZ; dLdAlpha = sum(dLdAlpha,[1 2]); % Sum over all observations in mini-batch. dLdAlpha = sum(dLdAlpha,4); end end end
Если функции прямого уровня полностью поддерживают dlarray объекты, то слой совместим с GPU. В противном случае, чтобы быть совместимым с GPU, функции уровня должны поддерживать входы и обратные выходы типа gpuArray(Панель инструментов параллельных вычислений).
Поддержка многих встроенных функций MATLAB gpuArray(Панель инструментов параллельных вычислений) и dlarray входные аргументы. Список функций, поддерживающих dlarray см. Список функций с поддержкой dlarray. Список функций, выполняемых на графическом процессоре, см. в разделе Выполнение функций MATLAB на графическом процессоре (панель инструментов параллельных вычислений). Чтобы использовать графический процессор для глубокого обучения, необходимо также иметь поддерживаемое устройство графического процессора. Сведения о поддерживаемых устройствах см. в разделе Поддержка графического процессора по выпуску (Parallel Computing Toolbox). Дополнительные сведения о работе с графическими процессорами в MATLAB см. в разделе Вычисления графического процессора в MATLAB (Parallel Computing Toolbox).
[1] «Углубление в выпрямители: превышение производительности на уровне человека при классификации ImageNet». В 2015 году Международная конференция IEEE по компьютерному зрению (ICCV), 1026-34. Сантьяго, Чили: IEEE, 2015. https://doi.org/10.1109/ICCV.2015.123.