Если Deep Learning Toolbox™ не предоставляет слой, который вам нужен для задачи классификации или регрессии, то можно задать свой собственный пользовательский слой, используя этот пример в качестве руководства. Список встроенных слоев см. в Списке слоев глубокого обучения.
Чтобы определить пользовательский слой глубокого обучения, можно использовать шаблон, представленный в этом примере, который проходит через следующие шаги:
Назовите слой - Дайте слою имя, чтобы вы могли использовать его в MATLAB®.
Объявить свойства слоя - Задать свойства слоя и какие параметры узнаются во время обучения.
Создайте функцию конструктора (необязательно) - задайте, как создать слой и инициализировать его свойства. Если вы не задаете функцию конструктора, то при создании программное обеспечение инициализирует Name
, Description
, и Type
свойства с []
и устанавливает количество входов и выходов слоя равным 1.
Создайте прямые функции - Задайте, как данные проходят вперед через слой (прямое распространение) во время предсказания и во время обучения.
Создайте обратную функцию (необязательно) - Задайте производные потерь относительно входных данных и настраиваемых параметров (обратное распространение). Если вы не задаете обратную функцию, то передние функции должны поддерживать dlarray
объекты.
Чтобы создать пользовательский слой, поддерживающий генерацию кода:
Слой должен задать прагму %#codegen
в определении слоя.
Входные входы predict
должны быть:
Последовательный по размерности. Каждый вход должен иметь одинаковое количество размерностей.
Согласованность в размере пакета. Каждый вход должен иметь одинаковый размер пакета.
Выходные выходы predict
должен быть согласован по размерности и размеру партии с входами слоя.
Нескалярные свойства должны иметь одинарный, двойной или символьный массив.
Скалярные свойства должны иметь числовой, логический или строковый тип.
Генерация кода поддерживает промежуточные слои только с 2-D входом изображения.
В этом примере показано, как создать слой PReLU [1], который является слоем с настраиваемым параметром, и использовать его в сверточной нейронной сети. PReLU слоя выполняет операцию порога, где для каждого канала любое значение входа, меньше нуля, умножается на скаляр, выученный во время обучения. Для значений, меньших нуля, слой PReLU применяет коэффициенты масштабирования в каждый канал входа. Эти коэффициенты образуют настраиваемый параметр, который слой учит во время обучения.
Этот рисунок из [1] сравнивает функции слоя ReLU и PReLU.
Скопируйте слой с настраиваемых параметров шаблоном в новый файл в MATLAB. Этот шаблон описывает структуру слоя с настраиваемыми параметрами и включает функции, которые определяют поведение слоя.
classdef myLayer < nnet.layer.Layer % & nnet.layer.Formattable (Optional) properties % (Optional) Layer properties. % Layer properties go here. end properties (Learnable) % (Optional) Layer learnable parameters. % Layer learnable parameters go here. end methods function layer = myLayer() % (Optional) Create a myLayer. % This function must have the same name as the class. % Layer constructor function goes here. end function [Z1, …, Zm] = predict(layer, X1, …, Xn) % Forward input data through the layer at prediction time and % output the result. % % Inputs: % layer - Layer to forward propagate through % X1, ..., Xn - Input data % Outputs: % Z1, ..., Zm - Outputs of layer forward function % Layer forward function for prediction goes here. end function [Z1, …, Zm, memory] = forward(layer, X1, …, Xn) % (Optional) Forward input data through the layer at training % time and output the result and a memory value. % % Inputs: % layer - Layer to forward propagate through % X1, ..., Xn - Input data % Outputs: % Z1, ..., Zm - Outputs of layer forward function % memory - Memory value for custom backward propagation % Layer forward function for training goes here. end function [dLdX1, …, dLdXn, dLdW1, …, dLdWk] = ... backward(layer, X1, …, Xn, Z1, …, Zm, dLdZ1, …, dLdZm, memory) % (Optional) Backward propagate the derivative of the loss % function through the layer. % % Inputs: % layer - Layer to backward propagate through % X1, ..., Xn - Input data % Z1, ..., Zm - Outputs of layer forward function % dLdZ1, ..., dLdZm - Gradients propagated from the next layers % memory - Memory value from forward function % Outputs: % dLdX1, ..., dLdXn - Derivatives of the loss with respect to the % inputs % dLdW1, ..., dLdWk - Derivatives of the loss with respect to each % learnable parameter % Layer backward function goes here. end end end
Сначала дайте слою имени. В первой линии файла класса замените существующее имя myLayer
с codegenPreluLayer
и добавить комментарий, описывающий слой.
classdef codegenPreluLayer < nnet.layer.Layer % Example custom PReLU layer with codegen support. ... end
Далее переименуйте myLayer
функция конструктора (первая функция в methods
section) так, чтобы оно имело то же имя что и слой.
methods function layer = codegenPreluLayer() ... end ... end
Сохраните файл класса слоя в новом файле с именем codegenPreluLayer.m
. Имя файла должно совпадать с именем слоя. Чтобы использовать слой, необходимо сохранить файл в текущей папке или в папке на пути MATLAB.
Добавьте %#codegen
директива (или прагма) к определению слоя, чтобы указать, что вы намерены сгенерировать код для этого слоя. Добавление этой директивы предписывает анализатору кода MATLAB помочь вам диагностировать и исправить нарушения, которые приводят к ошибкам во время генерации кода.
classdef codegenPreluLayer < nnet.layer.Layer % Example custom PReLU layer with codegen support. %#codegen ... end
Объявление свойств слоя в properties
и объявить настраиваемые параметры путем их перечисления в properties (Learnable)
раздел.
По умолчанию пользовательские промежуточные слои имеют эти свойства.
Свойство | Описание |
---|---|
Name | Имя слоя, заданное как вектор символов или строковый скаляр. Чтобы включить слой в график слоев, необходимо задать непустое уникальное имя слоя. Если вы обучаете последовательную сеть с слоем и Name установлено в '' затем программа автоматически присваивает слою имя во время обучения. |
Description | Однострочное описание слоя, заданное как вектор символов или строковый скаляр. Это описание появляется, когда слой отображается в |
Type | Тип слоя, заданный как вектор символов или строковый скаляр. Значение Type появляется, когда слой отображается в Layer массив. Если тип слоя не задан, программа отображает имя класса слоя. |
NumInputs | Количество входов слоя, заданное в виде положительного целого числа. Если вы не задаете это значение, то программное обеспечение автоматически устанавливает NumInputs к количеству имен в InputNames . Значение по умолчанию является 1. |
InputNames | Входные имена слоя, заданные как массив ячеек из векторов символов. Если вы не задаете это значение и NumInputs больше 1, затем программное обеспечение автоматически устанавливает InputNames на {'in1',...,'inN'} , где N равно NumInputs . Значение по умолчанию {'in'} . |
NumOutputs | Количество выходов слоя в виде положительного целого числа. Если вы не задаете это значение, то программное обеспечение автоматически устанавливает NumOutputs к количеству имен в OutputNames . Значение по умолчанию является 1. |
OutputNames | Выходные имена слоя, заданные как массив ячеек из векторов символов. Если вы не задаете это значение и NumOutputs больше 1, затем программное обеспечение автоматически устанавливает OutputNames на {'out1',...,'outM'} , где M равно NumOutputs . Значение по умолчанию {'out'} . |
Если слой не имеет других свойств, можно опустить properties
раздел.
Совет
Если вы создаете слой с несколькими входами, то вы должны задать NumInputs
или InputNames
свойства в конструкторе слоев. Если вы создаете слой с несколькими выходами, то необходимо задать NumOutputs
или OutputNames
свойства в конструкторе слоев. Для получения примера смотрите Задать Пользовательский Слой Глубокого Обучения с Несколькими Входами.
Для поддержки генерации кода:
Нескалярные свойства должны иметь одинарный, двойной или символьный массив.
Скалярные свойства должны быть числовыми или иметь логический тип или строку.
Слой PReLU не требует никаких дополнительных свойств, поэтому можно удалить properties
раздел.
Слой PReLU имеет только один настраиваемый параметр, коэффициент масштабирования a. Объявите этот настраиваемый параметр в properties (Learnable)
и вызовите параметр Alpha
.
properties (Learnable)
% Layer learnable parameters
% Scaling coefficient
Alpha
end
Создайте функцию, которая создает слой и инициализирует свойства слоя. Задайте любые переменные, необходимые для создания слоя в качестве входов для функции конструктора.
Функция конструктора слоя PReLU требует двух входных параметров: количества каналов ожидаемых входных данных и имени слоя. Количество каналов задает размер настраиваемого параметра Alpha
. Задайте два входных параметров с именем numChannels
и name
в codegenPreluLayer
функция. Добавьте комментарий к верхней части функции, которая объясняет синтаксис функции.
function layer = codegenPreluLayer(numChannels, name) % layer = codegenPreluLayer(numChannels) creates a PReLU layer with % numChannels channels and specifies the layer name. ... end
Генерация кода не поддерживает arguments
блоки.
Инициализируйте свойства слоя, включая настраиваемые параметры, в функции конструктора. Замените комментарий % Layer constructor function goes here
с кодом, который инициализирует свойства слоя.
Установите Name
свойство для входного параметра name
.
% Set layer name.
layer.Name = name;
Дайте слою однострочного описания путем установки Description
свойство слоя. Установите описание, чтобы описать тип слоя и его размер.
% Set layer description. layer.Description = "PReLU with " + numChannels + " channels";
Для уровня PReLU, когда входные значения отрицательны, слой умножает каждый канал входа на соответствующий канал Alpha
. Инициализируйте настраиваемый параметр Alpha
как случайный вектор размера 1 на 1-by- numChannels
. С третьей размерностью, заданным как size numChannels
, слой может использовать поэлементное умножение входа в прямой функции. Alpha
является свойством объекта слоя, поэтому вы должны назначить вектор layer.Alpha
.
% Initialize scaling coefficient.
layer.Alpha = rand([1 1 numChannels]);
Просмотрите завершенную функцию конструктора.
function layer = codegenPreluLayer(numChannels, name)
% layer = codegenPreluLayer(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
С помощью этой функции конструктора команда codegenPreluLayer(3,'prelu')
создает слой PReLU с тремя каналами и именем 'prelu'
.
Создайте передовые функции слоя для использования во времени предсказания и времени обучения.
Создайте функцию с именем predict
который распространяет данные вперед через слой во время предсказания и выводит результат.
Синтаксис для predict
является [Z1,…,Zm] = predict(layer,X1,…,Xn)
, где X1,…,Xn
являются ли n
входы и Z1,…,Zm
слоя являются ли
m
выходы слоя. Значения n
и m
должен соответствовать NumInputs
и NumOutputs
свойства слоя.
Совет
Если количество входов в predict
может варьироваться, затем использовать varargin
вместо X1,…,Xn
. В этом случае varargin
- массив ячеек входных входов, где varargin{i}
соответствует Xi
. Если количество выходов может варьироваться, используйте varargout
вместо Z1,…,Zm
. В этом случае varargout
- массив ячеек выходов, где varargout{j}
соответствует Zj
.
Поскольку слой PReLU имеет только один вход и один выход, синтаксис для predict
для слоя PReLU Z = predict(layer,X)
.
Генерация кода поддерживает пользовательские промежуточные слои только с 2-D входом изображения. Входы - h w c N массивы, где h, w, и c соответствуют высоте, ширине, и количество каналов изображений, соответственно, и N - количество наблюдений. Размерность наблюдения равна 4.
Для поддержки генерации кода все входы уровня должны иметь одинаковое количество размерностей и размер пакета.
По умолчанию слой использует predict
как прямая функция во время обучения. Чтобы использовать другую прямую функцию во время обучения или сохранить значение, необходимое для пользовательской обратной функции, необходимо также создать функцию с именем forward
. Программное обеспечение не генерирует код для forward
функция, но она должна быть совместимой с генерацией кода.
The forward
функция распространяет данные вперед через слой во время обучения, а также выводит значение памяти.
Синтаксис для forward
является [Z1,…,Zm,memory] = forward(layer,X1,…,Xn)
, где X1,…,Xn
являются ли n
входы слоя, Z1,…,Zm
являются ли m
выходы слоя и memory
- память слоя.
Совет
Если количество входов в forward
может варьироваться, затем использовать varargin
вместо X1,…,Xn
. В этом случае varargin
- массив ячеек входных входов, где varargin{i}
соответствует Xi
. Если количество выходов может варьироваться, используйте varargout
вместо Z1,…,Zm
. В этом случае varargout
- массив ячеек выходов, где varargout{j}
соответствует Zj
для j
= 1, …, NumOutputs
и varargout{NumOutputs + 1}
соответствует memory
.
Операция PReLU определяется
где является входом нелинейной f активации на канале i, и - коэффициент, контролирующий наклон отрицательной детали. Индекс i в указывает, что нелинейная активация может варьироваться в разных каналах.
Реализуйте эту операцию в predict
. В predict
, а вход X
соответствует x в уравнении. Область выхода Z
соответствует .
Добавьте комментарий к верхней части функции, которая объясняет синтаксисы функции.
Совет
Если вы предварительно распределяете массивы, используя такие функции, как zeros
Затем необходимо убедиться, что типы данных этих массивов соответствуют входам функции слоя. Чтобы создать массив нулей того совпадающий тип данных, что и другой массив, используйте 'like'
опция zeros
. Для примера инициализировать массив нулей размера sz
с тем совпадающим типом данных, что и массив X
, использовать Z = zeros(sz,'like',X)
.
Реализация backward
функция опциональна, когда передние функции полностью поддерживают dlarray
вход. Для поддержки генерации кода, predict
функция должна также поддерживать числовой вход.
Один из способов вычислить выход операции PReLU - использовать следующий код.
Z = max(X,0) + layer.Alpha .* min(0,X);
.*
операция, вы можете использовать bsxfun
вместо этого функция.Z = max(X,0) + bsxfun(@times, layer.Alpha, min(0,X));
bsxfun
не поддерживает dlarray
вход. Для реализации predict
функция, которая поддерживает генерацию кода и dlarray
введите, используйте if
оператор с isdlarray
функция для выбора соответствующего кода для типа входа. function Z = predict(layer, X)
% Z = predict(layer, X) forwards the input data X through the
% layer and outputs the result Z.
if isdlarray(X)
Z = max(X,0) + layer.Alpha .* min(0,X);
else
Z = max(X,0) + bsxfun(@times, layer.Alpha, min(0,X));
end
end
Потому что predict
функция полностью поддерживает dlarray
объекты, определяющие backward
функция опциональна. Список функций, поддерживающих dlarray
объекты, см. Список функций с поддержкой dlarray.
Просмотрите заполненный файл класса слоя.
classdef codegenPreluLayer < nnet.layer.Layer % Example custom PReLU layer with codegen support. %#codegen properties (Learnable) % Layer learnable parameters % Scaling coefficient Alpha end methods function layer = codegenPreluLayer(numChannels, name) % layer = codegenPreluLayer(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. if isdlarray(X) Z = max(X,0) + layer.Alpha .* min(0,X); else Z = max(X,0) + bsxfun(@times, layer.Alpha, min(0,X)); end end end end
Проверьте совместимость генерации кода пользовательского слоя codegenPreluLayer
.
Задайте пользовательский слой PReLU с поддержкой генерации кода. Чтобы создать этот слой, сохраните файл codegenPreluLayer.m
в текущей папке.
Создайте образец слоя и проверьте его валидность с помощью checkLayer
. Задайте допустимый размер входа как размер единственного наблюдения типового входа для слоя. Слой ожидает 4-D входов массива, где первые три размерности соответствуют высоте, ширине и количеству каналов предыдущего выхода слоя, а четвертая размерность соответствует наблюдениям.
Задайте типовой размер входа наблюдения и установите 'ObservationDimension'
опция 4. Чтобы проверить совместимость генерации кода, установите 'CheckCodegenCompatibility'
опция для true
.
layer = codegenPreluLayer(20,'prelu'); validInputSize = [24 24 20]; checkLayer(layer,validInputSize,'ObservationDimension',4,'CheckCodegenCompatibility',true)
Skipping GPU tests. No compatible GPU device found. Running nnet.checklayer.TestLayerWithoutBackward .......... ........ Done nnet.checklayer.TestLayerWithoutBackward __________ Test Summary: 18 Passed, 0 Failed, 0 Incomplete, 4 Skipped. Time elapsed: 0.53879 seconds.
Функция не обнаруживает проблем со слоем.
[1] «Углубление выпрямителей: превышение эффективности на уровне человека при классификации ImageNet». В 2015 году IEEE International Conference on Компьютерное Зрение (ICCV), 1026-34. Сантьяго, Чили: IEEE, 2015. https://doi.org/10.1109/ICCV.2015.123.