Main Content

カスタム層の逆方向関数の指定

目的の分類または回帰問題に必要な層が Deep Learning Toolbox™ に用意されていない場合、独自のカスタム層を定義できます。組み込み層の一覧については、深層学習層の一覧を参照してください。

学習可能なパラメーターを含むカスタム深層学習層の定義の例では、カスタム PReLU 層を作成しする方法を示し、次のステップを実行します。

  1. 層の命名 — MATLAB® で使用できるように層に名前を付けます。

  2. 層のプロパティの宣言 — 層のプロパティ (学習可能なパラメーターや状態パラメーターなど) を指定します。

  3. コンストラクター関数の作成 (オプション) — 層の構築とそのプロパティ初期化の方法を指定します。コンストラクター関数を指定しない場合、作成時に NameDescription、および Type の各プロパティは [] で初期化され、層の入力および出力の数は 1 に設定されます。

  4. 初期化関数の作成 (オプション) — ネットワークの初期化時に学習可能なパラメーターと状態パラメーターを初期化する方法を指定します。初期化関数を指定しない場合、ネットワークの初期化時にパラメーターは初期化されません。

  5. 順方向関数の作成 — 予測時および学習時に層経由でデータを順方向にパス (順伝播) する方法を指定します。

  6. リセット ステート関数の作成 (オプション) — 状態パラメーターをリセットする方法を指定します。

  7. 逆方向関数の作成 (オプション) — 入力データおよび学習可能なパラメーターにおける損失の微分を指定します (逆伝播)。逆方向関数を指定しない場合、順方向関数は dlarray オブジェクトをサポートしなければなりません。

順方向関数が dlarray オブジェクトをサポートする関数のみを使用する場合、逆方向関数の作成はオプションです。この場合、ソフトウェアは自動微分を使用して微分を自動的に求めます。dlarray オブジェクトをサポートしている関数の一覧については、dlarray をサポートする関数の一覧を参照してください。dlarray オブジェクトをサポートしない関数を使用する場合、または逆方向関数に特定のアルゴリズムを使用する場合、この例を参考にしてカスタム逆方向関数を定義できます。

カスタム層の作成

学習可能なパラメーターを含むカスタム深層学習層の定義の例では、PReLU 層の作成方法を示します。PReLU 層はしきい値処理を実行します。各チャネルについて、入力値がゼロよりも小さい場合は、学習時に得られたスカラーによって乗算されます。[1] 0 より小さい値の場合、PReLU 層は入力の各チャネルにスケーリング係数 αi を適用します。これらの係数は学習可能なパラメーターとなり、学習時にその層によって学習されます。

PReLU 演算は次の式で表されます。

f(xi)={xiif xi>0αixiif xi0

ここで、xi はチャネル i の非線形活性化 f の入力、αi は負の部分の勾配を制御する係数です。αi の添字 i は、別のチャネルでは非線形活性化が変わる場合があることを示しています。

学習可能なパラメーターを含むカスタム深層学習層の定義の例で作成された層を表示します。この層には関数 backward がありません。

classdef preluLayer < nnet.layer.Layer ...
        & nnet.layer.Acceleratable
    % Example custom PReLU layer.

    properties (Learnable)
        % Layer learnable parameters
            
        % Scaling coefficient
        Alpha
    end

    methods
        function layer = preluLayer(args) 
            % layer = preluLayer creates a PReLU layer.
            %
            % layer = preluLayer(Name=name) also specifies the
            % layer name.
    
            arguments
                args.Name = "";
            end
    
            % Set layer name.
            layer.Name = args.Name;

            % Set layer description.
            layer.Description = "PReLU";
        end

        function layer = initialize(layer,layout)
            % layer = initialize(layer,layout) initializes the layer
            % learnable parameters using the specified input layout.

            % Skip initialization of nonempty parameters.
            if ~isempty(layer.Alpha)
                return
            end

            % Input data size.
            sz = layout.Size;
            ndims = numel(sz);

            % Find number of channels.
            idx = finddim(layout,"C");
            numChannels = sz(idx);

            % Initialize Alpha.
            szAlpha = ones(1,ndims);
            szAlpha(idx) = numChannels;
            layer.Alpha = rand(szAlpha);
        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

メモ

層にカスタム逆方向関数がある場合でも、nnet.layer.Formattable から引き続き継承できます。

逆方向関数の作成

入力データおよび学習可能なパラメーターについての損失の微分を返す関数 backward を実装します。

関数 backward の構文は、層のタイプによって異なります。

  • dLdX = backward(layer,X,Z,dLdZ,memory) は、層入力についての損失の微分 dLdX を返します。この場合、layer は 1 つの入力と 1 つの出力をもちます。Z は順方向関数の出力に対応し、dLdZZ についての損失の微分に対応します。関数の入力 memory は、順方向関数のメモリ出力に対応します。

  • [dLdX,dLdW] = backward(layer,X,Z,dLdZ,memory) は、学習可能なパラメーターについての損失の微分 dLdW も返します。この場合、layer は 1 つの学習可能なパラメーターをもちます。

  • [dLdX,dLdSin] = backward(layer,X,Z,dLdZ,dLdSout,memory) は、状態入力についての損失の微分 dLdSin も返します。この場合、layer は 1 つの状態パラメーターをもちます。dLdSout は層の状態出力についての損失の微分に対応します。

  • [dLdX,dLdW,dLdSin] = backward(layer,X,Z,dLdZ,dLdSout,memory) は、学習可能なパラメーターについての損失の微分 dLdW、および層の状態入力についての損失の微分 dLdSin も返します。この場合、layer は 1 つの状態パラメーターと 1 つの学習可能なパラメーターをもちます。

複数の入力、複数の出力、複数の学習可能なパラメーター、または複数の状態パラメーターを使用して、層の構文を調整できます。

  • 複数の入力をもつ層の場合、XdLdX をそれぞれ X1,...,XNdLdX1,...,dLdXN に置き換えます。ここで、N は入力の数です。

  • 複数の出力をもつ層の場合、ZdLdZ をそれぞれ Z1,...,ZMdLdZ1,...,dLdZM に置き換えます。ここで、M は出力の数です。

  • 複数の学習可能なパラメーターをもつ層の場合、dLdWdLdW1,...,dLdWP に置き換えます。ここで、P は学習可能なパラメーターの数です。

  • 複数の状態パラメーターをもつ層の場合、dLdSindLdSout をそれぞれ dLdSin1,...,dLdSinKdLdSout1,...,dLdSoutK に置き換えます。ここで、K は状態パラメーターの数です。

フォワード パスとバックワード パスの間に使用されない変数が保存されることを防いでメモリ使用量を削減するには、対応する入力引数を ~ に置き換えます。

ヒント

backward への入力の数が変化する可能性がある場合、layer の後に入力引数ではなく varargin を使用します。この場合、varargin は入力の cell 配列になります。ここで、最初の N 個の要素は N 個の層入力に対応し、その次の M 個の要素は M 個の層出力に対応し、その次の M 個の要素は M 個の層出力についての損失の微分に対応し、その次の K 個の要素は K 個の状態出力についての損失に関する K 個の微分に対応し、最後の要素は memory に対応します。

出力の数が変化する可能性がある場合、出力引数ではなく varargout を使用します。この場合、varargout は出力の cell 配列になります。ここで、最初の N 個の要素は N 個の層入力についての損失に関する N 個の微分に対応し、その次の P 個の要素は P 個の学習可能なパラメーターについての損失の微分に対応し、その次の K 個の要素は K 個の状態入力についての損失の微分に対応します。

メモ

dlnetwork オブジェクトは、カスタム逆方向関数でメモリ値を必要とするカスタム層をサポートしません。dlnetwork オブジェクトでカスタム逆方向関数をもつカスタム層を使用するには、関数 backward の定義の入力 memory~ でなければなりません。

PReLU 層の入力、出力、および学習可能なパラメーターはそれぞれ 1 つだけで、層の順方向関数やメモリ値の出力を必要としないため、PReLU 層の backward の構文は [dLdX,dLdAlpha] = backward(layer,X,~,dLdZ,~) です。X の次元は、順方向関数の場合と同じです。dLdZ の次元は、順方向関数の出力 Z の次元と同じです。dLdX の次元およびデータ型は、X の次元およびデータ型と同じです。dLdAlpha の次元およびデータ型は、学習可能なパラメーター Alpha の次元およびデータ型と同じです。

バックワード パスの間に、層は対応する微分を使用して、学習可能なパラメーターを自動的に更新します。

カスタム層をネットワークに含めるには、層の順方向関数が前の層の出力を受け入れ、次の層で期待されるサイズの配列を順伝播しなければなりません。同様に、backward を指定する場合、関数 backward は、順方向関数の対応する出力と同じサイズの入力を受け入れ、同じサイズの微分を逆伝播しなければなりません。

入力データについての損失の微分は次のとおりです。

Lxi=Lf(xi)f(xi)xi

ここで、L/f(xi) は次の層から伝播された勾配であり、活性化の微分は次のとおりです。

f(xi)xi={1if xi0αiif xi<0.

学習可能なパラメーターについての損失の微分は次のとおりです。

Lαi=jLf(xij)f(xij)αi

ここで、i はチャネルのインデックス、j は高さ、幅、および観測値の要素のインデックスです。活性化の勾配は次のとおりです。

f(xi)αi={0if xi0xiif xi<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(args) 
            % layer = preluLayer creates a PReLU layer.
            %
            % layer = preluLayer(Name=name) also specifies the
            % layer name.
    
            arguments
                args.Name = "";
            end
    
            % Set layer name.
            layer.Name = args.Name;

            % Set layer description.
            layer.Description = "PReLU";
        end

        function layer = initialize(layer,layout)
            % layer = initialize(layer,layout) initializes the layer
            % learnable parameters using the specified input layout.

            % Skip initialization of nonempty parameters.
            if ~isempty(layer.Alpha)
                return
            end

            % Input data size.
            sz = layout.Size;
            ndims = numel(sz);

            % Find number of channels.
            idx = finddim(layout,"C");
            numChannels = sz(idx);

            % Initialize Alpha.
            szAlpha = ones(1,ndims);
            szAlpha(idx) = numChannels;
            layer.Alpha = rand(szAlpha);
        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

GPU 互換性

層の順方向関数が dlarray オブジェクトを完全にサポートしている場合、層は GPU 互換です。そうでない場合、GPU 互換にするには、層関数が入力をサポートし、gpuArray (Parallel Computing Toolbox) 型の出力を返さなければなりません。

多くの MATLAB 組み込み関数が入力引数 gpuArray (Parallel Computing Toolbox) および dlarray をサポートしています。dlarray オブジェクトをサポートしている関数の一覧については、dlarray をサポートする関数の一覧を参照してください。GPU で実行される関数の一覧については、GPU での MATLAB 関数の実行 (Parallel Computing Toolbox)を参照してください。深層学習に GPU を使用するには、サポートされている GPU デバイスもなければなりません。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。MATLAB での GPU の使用の詳細は、MATLAB での GPU 計算 (Parallel Computing Toolbox)を参照してください。

参照

[1] "Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification." In 2015 IEEE International Conference on Computer Vision (ICCV), 1026–34. Santiago, Chile: IEEE, 2015. https://doi.org/10.1109/ICCV.2015.123.

参考

| | | | | | | | | |

関連するトピック