Если Deep Learning Toolbox™ не предоставляет слой, необходимый для задачи классификации или регрессии, то можно задать свой собственный пользовательский слой. Список встроенных слоев см. в Списке слоев глубокого обучения.
Пример Define Custom Deep Learning Layer with Настраиваемые Параметры показывает, как создать пользовательский слой PreLU, и проходит следующие шаги:
Назовите слой - Дайте слою имя, чтобы вы могли использовать его в MATLAB®.
Объявить свойства слоя - Задать свойства слоя и какие параметры узнаются во время обучения.
Создайте функцию конструктора (необязательно) - задайте, как создать слой и инициализировать его свойства. Если вы не задаете функцию конструктора, то при создании программное обеспечение инициализирует Name
, Description
, и Type
свойства с []
и устанавливает количество входов и выходов слоя равным 1.
Создайте прямые функции - Задайте, как данные проходят вперед через слой (прямое распространение) во время предсказания и во время обучения.
Создайте обратную функцию (необязательно) - Задайте производные потерь относительно входных данных и настраиваемых параметров (обратное распространение). Если вы не задаете обратную функцию, то передние функции должны поддерживать dlarray
объекты.
Если прямая функция использует только функции, которые поддерживают dlarray
объекты, тогда создание обратной функции необязательно. В этом случае программное обеспечение автоматически определяет производные с помощью автоматической дифференциации. Список функций, поддерживающих dlarray
объекты, см. Список функций с поддержкой dlarray. Если вы хотите использовать функции, которые не поддерживают dlarray
объекты, или хотят использовать определенный алгоритм для обратной функции, тогда можно задать пользовательскую обратную функцию, используя этот пример в качестве руководства.
Пример Define Custom Deep Learning Layer with Настраиваемые Параметры показывает, как создать слой PReLU. Слой PReLU выполняет пороговую операцию, где для каждого канала любое входное значение, меньше нуля, умножается на скаляр, выученный во время обучения. [1] Для значений меньше нуля слой PReLU применяет коэффициенты масштабирования в каждый канал входа. Эти коэффициенты образуют настраиваемый параметр, который слой учит во время обучения.
Операция PReLU определяется
где является входом нелинейной f активации на канале i, и - коэффициент, контролирующий наклон отрицательной детали. Индекс i в указывает, что нелинейная активация может варьироваться в разных каналах.
Просмотрите слой, созданный в примере Define Custom Deep Learning Layer with Настраиваемые Параметры. Этот слой не имеет 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
функция должна принимать входы с таким же размером, как и соответствующий выход прямой функции, и назад распространять производные с таким же размером.
Производная потерь относительно входных данных является
где - градиент, распространенный из следующего слоя, и производная активации,
Производная от потерь относительно настраиваемых параметров
где i индексирует каналы, j индексирует элементы по высоте, ширине и наблюдениям, и градиент активации,
Создайте обратную функцию, которая возвращает эти производные.
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
Если функции слоя forward полностью поддерживают dlarray
объекты, тогда слой совместим с графическим процессором. В противном случае, чтобы быть совместимым с графический процессор, функции слоя должны поддерживать входы и выходные выходы возврата типа gpuArray
(Parallel Computing Toolbox).
Многие встроенные функции MATLAB поддерживают gpuArray
(Parallel Computing Toolbox) и dlarray
входные параметры. Список функций, поддерживающих dlarray
объекты, см. Список функций с поддержкой dlarray. Список функций, которые выполняются на графическом процессоре, см. в разделе Запуск функций MATLAB на графическом процессоре (Parallel Computing Toolbox). Для использования графический процессор для глубокого обучения необходимо иметь также поддерживаемое графический процессор. Для получения информации о поддерживаемых устройствах смотрите Поддержку GPU by Release (Parallel Computing Toolbox). Для получения дополнительной информации о работе с графическими процессорами в MATLAB, смотрите GPU Computing в MATLAB (Parallel Computing Toolbox).
[1] «Углубление выпрямителей: превышение эффективности на уровне человека при классификации ImageNet». В 2015 году IEEE International Conference on Компьютерное Зрение (ICCV), 1026-34. Сантьяго, Чили: IEEE, 2015. https://doi.org/10.1109/ICCV.2015.123.