Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

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

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

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

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

  2. 層のプロパティの宣言 – 層のプロパティと、学習中にどのパラメーターが学習されるかを指定します。

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

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

  5. 逆方向関数の作成 (オプション) – 入力データおよび学習可能なパラメーターにおける損失の微分を指定します (逆伝播)。逆方向関数を指定しない場合、順方向関数は 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
    % 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,…,Xnn 個の層入力

  • Z1,…,Zm は層の順方向関数の m 個の出力

  • dLdZ1,…,dLdZm は次の層から逆伝播された勾配

  • forward が定義された場合、memoryforward のメモリ出力。そうでない場合、memory[]

出力において、dLdX1,…,dLdXn は層入力についての損失の微分で、dLdW1,…,dLdWkk 個の学習可能なパラメーターについての損失の微分です。フォワード パスとバックワード パスの間に使用されない変数が保存されることを防いでメモリ使用量を削減するには、対応する入力引数を ~ に置き換えます。

ヒント

backward への入力の数が変化する可能性がある場合、layer の後に入力引数ではなく varargin を使用します。この場合、varargin は入力の cell 配列です。ここで、i=1,…,NumInputs について varargin{i}Xi に対応し、j=1,…,NumOutputs について varargin{NumInputs+j} および varargin{NumInputs+NumOutputs+j} はそれぞれ Zj および dLdZj に対応し、varargin{end}memory に対応します。

出力の数が変化する可能性がある場合、出力引数ではなく varargout を使用します。この場合、varargout は出力の cell 配列です。ここで、i=1,…,NumInputs について varargout{i}dLdXit=1,…,k について varargout{NumInputs+t}dLdWt に対応します。k は学習可能なパラメーターの数です。

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(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

GPU 互換性

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

多くの MATLAB 組み込み関数が入力引数 gpuArray (Parallel Computing Toolbox) および dlarray をサポートしています。dlarray オブジェクトをサポートしている関数の一覧については、dlarray をサポートする関数の一覧を参照してください。GPU で実行される関数の一覧については、GPU での MATLAB 関数の実行 (Parallel Computing Toolbox)を参照してください。深層学習に GPU を使用するには、Compute Capability 3.0 以上の CUDA® 対応 NVIDIA® GPU も必要です。MATLAB での GPU の使用の詳細は、MATLAB での GPU 計算 (Parallel Computing Toolbox)を参照してください。

参照

[1] He, Kaiming, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. "Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification." In Proceedings of the IEEE international conference on computer vision, pp. 1026-1034. 2015.

参考

|

関連するトピック