Задайте пользовательский слой глубокого обучения с настраиваемыми параметрами

Если Deep Learning Toolbox™ не предоставляет слой, который вам нужен для задачи классификации или регрессии, то можно задать свой собственный пользовательский слой, используя этот пример в качестве руководства. Список встроенных слоев см. в Списке слоев глубокого обучения.

Чтобы определить пользовательский слой глубокого обучения, можно использовать шаблон, представленный в этом примере, который проходит через следующие шаги:

  1. Назовите слой - Дайте слою имя, чтобы вы могли использовать его в MATLAB®.

  2. Объявить свойства слоя - Задать свойства слоя и какие параметры узнаются во время обучения.

  3. Создайте функцию конструктора (необязательно) - задайте, как создать слой и инициализировать его свойства. Если вы не задаете функцию конструктора, то при создании программное обеспечение инициализирует Name, Description, и Type свойства с [] и устанавливает количество входов и выходов слоя равным 1.

  4. Создайте прямые функции - Задайте, как данные проходят вперед через слой (прямое распространение) во время предсказания и во время обучения.

  5. Создайте обратную функцию (необязательно) - Задайте производные потерь относительно входных данных и настраиваемых параметров (обратное распространение). Если вы не задаете обратную функцию, то передние функции должны поддерживать dlarray объекты.

Определение обратной функции опционально, когда передние функции поддерживают dlarray объекты как вход. Использование dlarray облегчает работу с данными высоких размерностей, позволяя пометить размеры. Для примера можно пометить, какие размерности соответствуют пространственным, временным, канальным и пакетным размерностям, используя 'S', 'T', 'C', и 'B' метки, соответственно. Для неопределенных и других размерностей используйте 'U' метка. Для dlarray функции объекта, которые работают над конкретными размерностями, можно задать метки размера путем форматирования dlarray объект непосредственно, или при помощи 'DataFormat' опция.

Использование форматированных dlarray объекты в пользовательских слоях также позволяют вам задавать слои, где входы и выходы имеют различные форматы, такие как слои, которые перестраивают, добавляют или удаляют размерности. Например, можно задать слой, который принимает за вход мини-пакет изображений с форматом 'SSCB' (пространственный, пространственный, канальный, пакетный) и выхода мини-пакета последовательностей с форматом 'CBT' (канал, пакет, время).

Включение поддержки использования форматированных dlarray объекты в пользовательских слоях прямых функциях, также наследуются от nnet.layer.Formattable класс при определении пользовательского слоя. Для получения примера смотрите Задать Пользовательский Слой Глубокого Обучения с Форматированными Входами.

Этот пример показывает, как создать слой PReLU, который является слоем с настраиваемым параметром и использовать его в сверточной нейронной сети. Слой PReLU выполняет пороговую операцию, где для каждого канала любое входное значение, меньше нуля, умножается на скаляр, выученный во время обучения. [1] Для значений меньше нуля слой PReLU применяет коэффициенты масштабирования αi в каждый канал входа. Эти коэффициенты образуют настраиваемый параметр, который слой учит во время обучения.

Этот рисунок из [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 с preluLayer.

classdef preluLayer < nnet.layer.Layer
    ...
end

Далее переименуйте myLayer функция конструктора (первая функция в methods section) так, чтобы оно имело то же имя что и слой.

    methods
        function layer = preluLayer()           
            ...
        end

        ...
     end

Сохраните слой

Сохраните файл класса слоя в новом файле с именем preluLayer.m. Имя файла должно совпадать с именем слоя. Чтобы использовать слой, необходимо сохранить файл в текущей папке или в папке на пути MATLAB.

Объявление свойств и настраиваемых параметров

Объявление свойств слоя в properties и объявить настраиваемые параметры путем их перечисления в properties (Learnable) раздел.

По умолчанию пользовательские промежуточные слои имеют эти свойства.

СвойствоОписание
NameИмя слоя, заданное как вектор символов или строковый скаляр. Чтобы включить слой в график слоев, необходимо задать непустое уникальное имя слоя. Если вы обучаете последовательную сеть с слоем и Name установлено в ''затем программа автоматически присваивает слою имя во время обучения.
Description

Однострочное описание слоя, заданное как вектор символов или строковый скаляр. Это описание появляется, когда слой отображается в Layer массив. Если вы не задаете описание слоя, то программа отображает имя класса слоя.

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 в preluLayer функция. Добавьте комментарий к верхней части функции, которая объясняет синтаксис функции.

        function layer = preluLayer(numChannels, name)
            % layer = preluLayer(numChannels) creates a PReLU layer with
            % numChannels channels and specifies the layer name.

            ...
        end

Инициализация свойств слоя

Инициализируйте свойства слоя, включая настраиваемые параметры в функции конструктора. Замените комментарий % 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 = 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

С помощью этой функции конструктора команда preluLayer(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.

Совет

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

Поскольку слой PReLU имеет только один вход и один выход, синтаксис для predict для слоя PReLU Z = predict(layer,X).

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

Размерности входов зависят от типа данных и выхода связанных слоев:

Вход слояВход сигналаРазмерность наблюдения
2-D изображенияh -by- w -by- c -by- N, где h, w и c соответствуют высоте, ширине и количеству каналов изображений, соответственно, а N - количеству наблюдений.4
3-D изображения<reservedrangesplaceholder9>-by-<reservedrangesplaceholder8>-by-<reservedrangesplaceholder7>-by-<reservedrangesplaceholder6>-by-<reservedrangesplaceholder5>, где h, w, d, и c соответствуют высоте, ширине, глубине, и количество каналов 3D изображений, соответственно, и N - количество наблюдений.5
Векторные последовательностиc -by- N -by- S, где c - количество функций последовательностей, N - количество наблюдений, а S - длина последовательности.2
2-D последовательности изображенийh -by- w -by- c -by- N -by- S, где h, w и c соответствуют высоте, ширине и количеству каналов изображений, соответственно, N является количеством наблюдений, а S - длиной последовательности.4
3-D последовательности изображенийh -by- w -by- d -by- c -by- N -by- S, где h, w, d и c соответствуют высоте, ширине, глубине и количеству каналов 3-D изображений, соответственно, N количество наблюдений, а S - длина последовательности.5

Для слоев, которые выводят последовательности, слои могут выводить последовательности любой длины или выводить данные без временной размерности. Обратите внимание, что при обучении сети, которая выводит последовательности, используя trainNetwork function, длины входа и выхода последовательностей должны совпадать.

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.

Совет

Если у пользовательского слоя есть dlnetwork объект для настраиваемого параметра, затем в forward функцию пользовательского слоя используйте forward функция dlnetwork объект. Использование dlnetwork forward объекта функция гарантирует, что программное обеспечение использует правильные операции слоя для обучения.

Операция PReLU определяется

f(xi)={xiесли xi>0αixiесли xi0

где xi является входом нелинейной f активации на канале i, и αi - коэффициент, контролирующий наклон отрицательной детали. Индекс i в αi указывает, что нелинейная активация может варьироваться в разных каналах.

Реализуйте эту операцию в predict. В predict, а вход X соответствует x в уравнении. Область выхода Z соответствует f(xi). Слой PReLU не требует памяти или другой прямой функции для обучения, поэтому можно удалить forward функция из файла класса. Добавьте комментарий к верхней части функции, которая объясняет синтаксисы функции.

Совет

Если вы предварительно распределяете массивы, используя такие функции, как zerosЗатем необходимо убедиться, что типы данных этих массивов соответствуют входам функции слоя. Чтобы создать массив нулей того совпадающий тип данных, что и другой массив, используйте 'like' опция zeros. Для примера инициализировать массив нулей размера sz с тем совпадающим типом данных, что и массив X, использовать Z = zeros(sz,'like',X).

        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

Потому что predict функция использует только функции, которые поддержка dlarray объекты, определяющие backward функция опциональна. Список функций, поддерживающих dlarray объекты, см. Список функций с поддержкой dlarray.

Завершенный слой

Просмотрите заполненный файл класса слоя.

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

Совместимость с GPU

Если функции слоя 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).

В этом примере функции MATLAB, используемые в predict все dlarray поддержки объекты, поэтому слой совместим с графическим процессором.

Проверяйте валидность слоя, используя checkLayer

Проверьте валидность слоя пользовательского слоя preluLayer.

Задайте пользовательский слой PReLU. Чтобы создать этот слой, сохраните файл preluLayer.m в текущей папке.

Создайте образец слоя и проверьте его валидность с помощью checkLayer. Задайте допустимый размер входного сигнала, чтобы быть размером одного наблюдения типового входа для слоя. Слой ожидает 4-D входов массива, где первые три размерности соответствуют высоте, ширине и количеству каналов предыдущего выхода слоя, а четвертая размерность соответствует наблюдениям.

Задайте типовой размер входа наблюдения и набора 'ObservationDimension' по 4.

layer = preluLayer(20,'prelu');
validInputSize = [24 24 20];
checkLayer(layer,validInputSize,'ObservationDimension',4)
Skipping GPU tests. No compatible GPU device found.
 
Skipping code generation compatibility tests. To check validity of the layer for code generation, specify the 'CheckCodegenCompatibility' and 'ObservationDimension' options.
 
Running nnet.checklayer.TestLayerWithoutBackward
.......... ...
Done nnet.checklayer.TestLayerWithoutBackward
__________

Test Summary:
	 13 Passed, 0 Failed, 0 Incomplete, 9 Skipped.
	 Time elapsed: 0.15907 seconds.

Здесь функция не обнаруживает никаких проблем со слоем.

Включение пользовательского слоя в сеть

Можно использовать пользовательский слой так же, как и любой другой слой в Deep Learning Toolbox. В этом разделе показано, как создать и обучить сеть для классификации цифр с помощью слоя PReLU, созданного ранее.

Загрузите пример обучающих данных.

[XTrain,YTrain] = digitTrain4DArrayData;

Задайте пользовательский слой PReLU. Чтобы создать этот слой, сохраните файл preluLayer.m в текущей папке. Создайте массив слоев, включая пользовательский слой preluLayer.

layers = [ 
    imageInputLayer([28 28 1])
    convolution2dLayer(5,20)
    batchNormalizationLayer
    preluLayer(20,'prelu')
    fullyConnectedLayer(10)
    softmaxLayer
    classificationLayer];

Установите опции обучения и обучите сеть.

options = trainingOptions('adam','MaxEpochs',10);
net = trainNetwork(XTrain,YTrain,layers,options);
Training on single CPU.
Initializing input data normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:00 |       10.94% |       3.0526 |          0.0010 |
|       2 |          50 |       00:00:05 |       71.88% |       0.8378 |          0.0010 |
|       3 |         100 |       00:00:11 |       85.94% |       0.4878 |          0.0010 |
|       4 |         150 |       00:00:16 |       88.28% |       0.4068 |          0.0010 |
|       6 |         200 |       00:00:21 |       96.09% |       0.1691 |          0.0010 |
|       7 |         250 |       00:00:27 |       97.66% |       0.1370 |          0.0010 |
|       8 |         300 |       00:00:33 |       99.22% |       0.0744 |          0.0010 |
|       9 |         350 |       00:00:38 |       99.22% |       0.0592 |          0.0010 |
|      10 |         390 |       00:00:42 |      100.00% |       0.0466 |          0.0010 |
|========================================================================================|

Оцените эффективность сети, предсказав новые данные и вычислив точность.

[XTest,YTest] = digitTest4DArrayData;
YPred = classify(net,XTest);
accuracy = sum(YTest==YPred)/numel(YTest)
accuracy = 0.9190

Ссылки

[1] «Углубление выпрямителей: превышение эффективности на уровне человека при классификации ImageNet». В 2015 году IEEE International Conference on Компьютерное Зрение (ICCV), 1026-34. Сантьяго, Чили: IEEE, 2015. https://doi.org/10.1109/ICCV.2015.123.

См. также

|

Похожие темы