コード生成用のカスタム深層学習層の定義
目的の分類または回帰問題に必要な層が Deep Learning Toolbox™ に用意されていない場合、この例を指針として使用して独自のカスタム層を定義できます。組み込み層の一覧については、深層学習層の一覧を参照してください。
カスタム深層学習層を定義するために、この例で提供するテンプレートを使用できます。これは、以下の手順を実行します。
層の命名 — MATLAB® で使用できるように層に名前を付けます。
層のプロパティの宣言 — 層のプロパティ (学習可能なパラメーターや状態パラメーターなど) を指定します。
コンストラクター関数の作成 (オプション) — 層を構築してそのプロパティを初期化する方法を指定します。コンストラクター関数を指定しない場合、作成時に
Name
、Description
、およびType
の各プロパティは[]
で初期化され、層の入力および出力の数は1
に設定されます。初期化関数の作成 (オプション) — ネットワークの初期化時に学習可能なパラメーターと状態パラメーターを初期化する方法を指定します。初期化関数を指定しない場合、ネットワークの初期化時にパラメーターは初期化されません。
順方向関数の作成 — 予測時および学習時に層経由でデータを順方向にパス (順伝播) する方法を指定します。
リセット ステート関数の作成 (オプション) — 状態パラメーターをリセットする方法を指定します。
逆方向関数の作成 (オプション) — 入力データおよび学習可能なパラメーターにおける損失の微分を指定します (逆伝播)。逆方向関数を指定しない場合、順方向関数は
dlarray
オブジェクトをサポートしなければなりません。
コード生成用のカスタム層を作成するには、層の定義でプラグマ %#codegen
を指定しなければなりません。コード生成は、状態プロパティ (属性が State
であるプロパティ) をもつカスタム層をサポートしません。
さらに、サードパーティのライブラリを使用するコードを生成する場合は、次の点に注意してください。
コード生成では、2 次元イメージ入力または特徴入力のみをもつカスタム層がサポートされます。
層の順方向関数の入力と出力は、同じバッチ サイズでなければなりません。
非スカラーのプロパティは、single、double、または文字配列でなければなりません。
スカラーのプロパティは、数値型、logical 型、または string 型でなければなりません。
この例では、4 つの学習可能なパラメーターをもつ層である SReLU 層を作成し、それを畳み込みニューラル ネットワークで使用する方法を示します。SReLU 層は、しきい値処理演算を実行します。ここで、層は各チャネルについて、区間外の値をスケーリングします。区間しきい値とスケーリング係数は学習可能なパラメーターです。[1]。
SReLU 演算は次で与えられます。
ここで、xi はチャネル i の入力、tli と tri はそれぞれチャネル i の左と右のしきい値、ali と ari はそれぞれチャネル i の左と右のスケーリング係数です。これらのしきい値とスケーリング係数は学習可能なパラメーターとなり、学習時にその層によって学習されます。
カスタム層テンプレート
カスタム層テンプレートを MATLAB の新しいファイルにコピーします。このテンプレートは、層のクラス定義の構造を提供します。概要は次のとおりです。
層のプロパティ、学習可能なパラメーター、状態パラメーターに関する、オプションの
properties
ブロック。オプションの層コンストラクター関数。
オプションの関数
initialize
。関数
predict
とオプションの関数forward
。状態プロパティをもつ層におけるオプションの関数
resetState
。オプションの関数
backward
。
classdef myLayer < nnet.layer.Layer % ... % & nnet.layer.Formattable ... % (Optional) % & nnet.layer.Acceleratable % (Optional) properties % (Optional) Layer properties. % Declare layer properties here. end properties (Learnable) % (Optional) Layer learnable parameters. % Declare learnable parameters here. end properties (State) % (Optional) Layer state parameters. % Declare state parameters here. end properties (Learnable, State) % (Optional) Nested dlnetwork objects with both learnable % parameters and state parameters. % Declare nested networks with learnable and state parameters here. end methods function layer = myLayer() % (Optional) Create a myLayer. % This function must have the same name as the class. % Define layer constructor function here. end function layer = initialize(layer,layout) % (Optional) Initialize layer learnable and state parameters. % % Inputs: % layer - Layer to initialize % layout - Data layout, specified as a networkDataLayout % object % % Outputs: % layer - Initialized layer % % - For layers with multiple inputs, replace layout with % layout1,...,layoutN, where N is the number of inputs. % Define layer initialization function here. end function [Y,state] = predict(layer,X) % Forward input data through the layer at prediction time and % output the result and updated state. % % Inputs: % layer - Layer to forward propagate through % X - Input data % Outputs: % Y - Output of layer forward function % state - (Optional) Updated layer state % % - For layers with multiple inputs, replace X with X1,...,XN, % where N is the number of inputs. % - For layers with multiple outputs, replace Y with % Y1,...,YM, where M is the number of outputs. % - For layers with multiple state parameters, replace state % with state1,...,stateK, where K is the number of state % parameters. % Define layer predict function here. end function [Y,state,memory] = forward(layer,X) % (Optional) Forward input data through the layer at training % time and output the result, the updated state, and a memory % value. % % Inputs: % layer - Layer to forward propagate through % X - Layer input data % Outputs: % Y - Output of layer forward function % state - (Optional) Updated layer state % memory - (Optional) Memory value for custom backward % function % % - For layers with multiple inputs, replace X with X1,...,XN, % where N is the number of inputs. % - For layers with multiple outputs, replace Y with % Y1,...,YM, where M is the number of outputs. % - For layers with multiple state parameters, replace state % with state1,...,stateK, where K is the number of state % parameters. % Define layer forward function here. end function layer = resetState(layer) % (Optional) Reset layer state. % Define reset state function here. end function [dLdX,dLdW,dLdSin] = backward(layer,X,Y,dLdY,dLdSout,memory) % (Optional) Backward propagate the derivative of the loss % function through the layer. % % Inputs: % layer - Layer to backward propagate through % X - Layer input data % Y - Layer output data % dLdY - Derivative of loss with respect to layer % output % dLdSout - (Optional) Derivative of loss with respect % to state output % memory - Memory value from forward function % Outputs: % dLdX - Derivative of loss with respect to layer input % dLdW - (Optional) Derivative of loss with respect to % learnable parameter % dLdSin - (Optional) Derivative of loss with respect to % state input % % - For layers with state parameters, the backward syntax must % include both dLdSout and dLdSin, or neither. % - For layers with multiple inputs, replace X and dLdX with % X1,...,XN and dLdX1,...,dLdXN, respectively, where N is % the number of inputs. % - For layers with multiple outputs, replace Y and dLdY with % Y1,...,YM and dLdY,...,dLdYM, respectively, where M is the % number of outputs. % - For layers with multiple learnable parameters, replace % dLdW with dLdW1,...,dLdWP, where P is the number of % learnable parameters. % - For layers with multiple state parameters, replace dLdSin % and dLdSout with dLdSin1,...,dLdSinK and % dLdSout1,...,dldSoutK, respectively, where K is the number % of state parameters. % Define layer backward function here. end end end
層の命名とスーパークラスの指定
まず、層に名前を付けます。クラス ファイルの最初の行で、既存の名前 myLayer
を codegenSReLULayer
に置き換え、層を説明するコメントを追加します。
この層の関数は高速化をサポートするため、nnet.layer.Acceleratable
からも継承します。カスタム層の関数の高速化に関する詳細については、Custom Layer Function Accelerationを参照してください。この層は形式を整えられる入力を必要としないため、オプションの nnet.layer.Formattable
スーパークラスを削除します。
classdef codegenSReLULayer < nnet.layer.Layer ... & nnet.layer.Acceleratable % Example custom SReLU layer with codegen support. ... end
次に、コンストラクター関数 myLayer
(methods
セクションの最初の関数) の名前を層と同じ名前に変更します。
methods function layer = codegenSReLULayer() ... end ... end
層の保存
層のクラス ファイルを codegenSReLULayer.m
という名前の新しいファイルに保存します。このファイル名は層の名前に一致しなければなりません。この層を使用するには、このファイルを現在のフォルダーまたは MATLAB パス上のフォルダーに保存しなければなりません。
コード生成プラグマの指定
この層のコードを生成することを示すため、層の定義に %#codegen
命令 (プラグマ) を追加します。この命令は、MATLAB コード アナライザーに対し、コード生成時のエラーの原因となる違反を診断して修正するのに役立つ情報を提供するよう指示します。
classdef codegenSReLULayer < nnet.layer.Layer ... & nnet.layer.Acceleratable % Example custom SReLU layer with codegen support. %#codegen ... end
プロパティおよび学習可能なパラメーターの宣言
層のプロパティを properties
セクションで宣言し、学習可能なパラメーターを properties (Learnable)
セクションにリストすることによって宣言します。
既定では、カスタム層には次のプロパティがあります。これらのプロパティを properties
セクションで宣言しないでください。
Property | 説明 |
---|---|
Name | 層の名前。文字ベクトルまたは string スカラーとして指定します。Layer 配列入力の場合、関数 trainnet および関数 dlnetwork は、名前が "" の層に自動的に名前を割り当てます。 |
Description | 層についての 1 行の説明。string スカラーまたは文字ベクトルとして指定します。この説明は、層が 層の説明を指定しない場合、層のクラス名が表示されます。 |
Type | 層のタイプ。文字ベクトルまたは string スカラーとして指定します。 層のタイプを指定しない場合、層のクラス名が表示されます。 |
NumInputs | 層の入力の数。正の整数として指定します。この値を指定しない場合、NumInputs は InputNames の名前の数に自動的に設定されます。既定値は 1 です。 |
InputNames | 層の入力の名前。文字ベクトルの cell 配列として指定します。この値を指定せず、NumInputs が 1 より大きい場合、InputNames は {'in1',...,'inN'} に自動的に設定されます。ここで、N = NumInputs です。既定値は {'in'} です。 |
NumOutputs | 層の出力の数。正の整数として指定します。この値を指定しない場合、NumOutputs は OutputNames の名前の数に自動的に設定されます。既定値は 1 です。 |
OutputNames | 層の出力の名前。文字ベクトルの cell 配列として指定します。この値を指定せず、NumOutputs が 1 より大きい場合、OutputNames は {'out1',...,'outM'} に自動的に設定されます。ここで、M = NumOutputs です。既定値は {'out'} です。 |
層にその他のプロパティがない場合は、properties
セクションを省略できます。
ヒント
複数の入力がある層を作成する場合、層のコンストラクターで NumInputs
と InputNames
のいずれかのプロパティを設定しなければなりません。複数の出力がある層を作成している場合、層のコンストラクターで NumOutputs
と OutputNames
のいずれかのプロパティを設定しなければなりません。例については、複数の入力があるカスタム深層学習層の定義を参照してください。
コード生成をサポートするには、次のことが必要です。
非スカラーのプロパティは、single 配列、double 配列、または文字配列でなければなりません。
スカラーのプロパティは、数値型、logical 型、または string 型でなければなりません。
SReLU 層には追加のプロパティが必要ないため、properties
セクションは削除できます。
SReLU 層には、左右それぞれのしきい値とスケーリング係数という 4 つの学習可能なパラメーターがあります。この学習可能なパラメーターを properties (Learnable)
セクションで宣言し、パラメーター Alpha
を呼び出します。
properties (Learnable)
% Layer learnable parameters
LeftSlope
RightSlope
LeftThreshold
RightThreshold
end
コンストラクター関数の作成
層を構築する関数を作成し、層のプロパティを初期化します。層を作成するために必要な変数をコンストラクター関数への入力として指定します。
SReLU 層のコンストラクター関数には、1 つのオプションの引数 (層の名前) が必要です。オプションの引数に対応する name
という名前の入力引数を関数 sreluLayer
で指定します。関数の構文を説明するコメントを関数の上部に追加します。
function layer = codegenSReLULayer(name) % layer = codegenSReLULayer creates a SReLU layer. % layer = codegenSReLULayer(name) also specifies the layer % name. ... end
層のプロパティの初期化
コンストラクター関数に学習可能なパラメーターを含め、層のプロパティを初期化します。コメント % Layer constructor function goes here
を、層のプロパティを初期化するコードに置き換えます。
Name
プロパティを入力引数 name
に設定します。
% Set layer name.
layer.Name = name;
層の Description
プロパティを設定して、層に 1 行の説明を指定します。層のタイプの説明を設定します。
% Set layer description. layer.Description = "SReLU";
完成したコンストラクター関数を表示します。
function layer = codegenSReLULayer(args)
% layer = codegenSReLULayer creates a SReLU layer.
% layer = codegenSReLULayer(name) also specifies the layer
% name.
arguments nargin == 0
args.Name = ""
end
% Set layer name.
layer.Name = args.Name;
% Set layer description.
layer.Description = "SReLU";
end
このコンストラクター関数を使用すると、コマンド codegenSreluLayer("srelu")
によって "srelu"
という名前の SReLU 層が作成されます。
初期化関数の作成
ネットワークの初期化時に層の学習可能なパラメーターと状態パラメーターを初期化する関数を作成します。この関数では、プロパティが空の場合、学習可能なパラメーターと状態パラメーターのみを初期化するようにしてください。それ以外の場合に初期化すると、MAT ファイルからネットワークを読み込んだときに、ソフトウェアによって上書きされる可能性があります。
学習可能なパラメーターを初期化するには、入力データのチャネル数と同じ数のチャネルをもつランダム ベクトルを生成します。
ネットワークが使用できるようになるまで入力データのサイズは不明であるため、networkDataLayout
オブジェクトを使用して学習可能なパラメーターと状態パラメーターを初期化する初期化関数を作成しなければなりません (このオブジェクトは関数に渡されます)。ネットワークのデータ レイアウト オブジェクトには、想定される入力データのサイズと形式に関する情報が格納されます。サイズと形式の情報を使用して学習可能なパラメーターと状態パラメーターを正しいサイズで初期化する初期化関数を作成します。
学習可能なパラメーターは、入力観測値の次元と同じ数の次元をもちます。ここで、チャネル次元のサイズは入力データのチャネル次元と同じで、残りの次元はサイズが 1 です。入力の networkDataLayout
オブジェクトからサイズと形式の情報を抽出し、同じ数のチャネルで学習可能なパラメーターを初期化する関数 initialize
を作成します。
function layer = initialize(layer,layout)
% layer = initialize(layer,layout) initializes the layer
% learnable parameters using the specified input layout.
% Find number of channels.
idx = finddim(layout,"C");
numChannels = layout.Size(idx);
% Initialize empty learnable parameters.
sz = ones(1,numel(layout.Size);
sz(idx) = numChannels;
if isempty(layer.LeftSlope)
layer.LeftSlope = rand(sz);
end
if isempty(layer.RightSlope)
layer.RightSlope = rand(sz);
end
if isempty(layer.LeftThreshold)
layer.LeftThreshold = rand(sz);
end
if isempty(layer.RightThreshold)
layer.RightThreshold = rand(sz);
end
end
順方向関数の作成
予測時と学習時に使用する層の順方向関数を作成します。
"予測時" に層経由でデータを順伝播させて結果を出力する、predict
という名前の関数を作成します。
関数 predict
の構文は、層のタイプによって異なります。
Y = predict(layer,X)
は、層を介して入力データX
を転送し、結果Y
を出力します。この場合、layer
は、1 つの入力と 1 つの出力をもちます。[Y,state] = predict(layer,X)
は、更新された状態パラメーターstate
も出力します。この場合、layer
は 1 つの状態パラメーターをもちます。
複数の入力、複数の出力、または複数の状態パラメーターを使用して、層の構文を調整できます。
複数の入力をもつ層の場合、
X
をX1,...,XN
に置き換えます。ここで、N
は入力の数です。NumInputs
プロパティはN
と一致しなければなりません。複数の出力をもつ層の場合、
Y
をY1,...,YM
に置き換えます。ここで、M
は出力の数です。NumOutputs
プロパティはM
と一致しなければなりません。複数の状態パラメーターをもつ層の場合、
state
をstate1,...,stateK
に置き換えます。ここで、K
は状態パラメーターの数です。
ヒント
層への入力の数が変化する可能性がある場合、X1,…,XN
ではなく varargin
を使用します。この場合、varargin
は入力の cell 配列です。ここで、varargin{i}
は Xi
に対応します。
出力の数が変化する可能性がある場合、Y1,…,YM
ではなく varargout
を使用します。この場合、varargout
は出力の cell 配列です。ここで、varargout{j}
は Yj
に対応します。
SReLU 層の入力および出力はそれぞれ 1 つのみであるため、SReLU 層の predict
の構文は Y = predict(layer,X)
になります。
コード生成のサポートでは、層入力すべての次元数およびバッチ サイズは同じでなければなりません。
既定では、層は学習時に predict
を順方向関数として使用します。学習時に別の順方向関数を使用する、またはカスタム逆方向関数に必要な値を保持するには、forward
という名前の関数も作成しなければなりません。ソフトウェアは関数 forward
のコードを生成しませんが、コード生成の互換性がなければなりません。
関数 forward
は "学習時" に層経由でデータを順伝播させ、メモリ値も出力します。
関数 forward
の構文は、層のタイプによって異なります。
Y = forward(layer,X)
は、層を介して入力データX
を転送し、結果Y
を出力します。この場合、layer
は、1 つの入力と 1 つの出力をもちます。[Y,state] = forward(layer,X)
は、更新された状態パラメーターstate
も出力します。この場合、layer
は 1 つの状態パラメーターをもちます。[__,memory] = forward(layer,X)
は、前述の構文のいずれかを使用して、カスタム関数backward
のメモリ値も返します。カスタム関数forward
とカスタム関数backward
の両方が層に存在する場合、順方向関数によってメモリ値が返されなければなりません。
複数の入力、複数の出力、または複数の状態パラメーターを使用して、層の構文を調整できます。
複数の入力をもつ層の場合、
X
をX1,...,XN
に置き換えます。ここで、N
は入力の数です。NumInputs
プロパティはN
と一致しなければなりません。複数の出力をもつ層の場合、
Y
をY1,...,YM
に置き換えます。ここで、M
は出力の数です。NumOutputs
プロパティはM
と一致しなければなりません。複数の状態パラメーターをもつ層の場合、
state
をstate1,...,stateK
に置き換えます。ここで、K
は状態パラメーターの数です。
ヒント
層への入力の数が変化する可能性がある場合、X1,…,XN
ではなく varargin
を使用します。この場合、varargin
は入力の cell 配列です。ここで、varargin{i}
は Xi
に対応します。
出力の数が変化する可能性がある場合、Y1,…,YM
ではなく varargout
を使用します。この場合、varargout
は出力の cell 配列です。ここで、varargout{j}
は Yj
に対応します。
SReLU 演算は次で与えられます。
ここで、xi はチャネル i の入力、tli と tri はそれぞれチャネル i の左と右のしきい値、ali と ari はそれぞれチャネル i の左と右のスケーリング係数です。これらのしきい値とスケーリング係数は学習可能なパラメーターとなり、学習時にその層によって学習されます。
この演算を predict
に実装します。predict
では、入力 X
がこの方程式の x に対応します。出力 Y
は に対応します。
関数の構文を説明するコメントを関数の上部に追加します。
ヒント
zeros
などの関数を使用して配列を事前に割り当てる場合、これらの配列のデータ型が層関数の入力と一致していることを確認しなければなりません。別の配列と同じデータ型のゼロの配列を作成するには、zeros
の "like"
オプションを使用します。たとえば、配列 X
と同じデータ型でサイズが sz
のゼロの配列を初期化するには、Y = zeros(sz,"like",X)
を使用します。
順方向関数が dlarray
入力を完全にサポートしている場合、関数 backward
の実装はオプションです。コード生成のサポートでは、関数 predict
が数値入力もサポートしなければなりません。
function Y = predict(layer, X)
% Y = predict(layer, X) forwards the input data X through the
% layer and outputs the result Y.
tl = layer.LeftThreshold;
al = layer.LeftSlope;
tr = layer.RightThreshold;
ar = layer.RightSlope;
Y = (X <= tl) .* (tl + al.*(X-tl)) ...
+ ((tl < X) & (X < tr)) .* X ...
+ (tr <= X) .* (tr + ar.*(X-tr));
end
関数 predict
は dlarray
オブジェクトを完全にサポートするため、関数 backward
の定義はオプションです。dlarray
オブジェクトをサポートしている関数の一覧については、dlarray をサポートする関数の一覧を参照してください。
完成した層
完成した層のクラス ファイルを表示します。
classdef codegenSReLULayer < nnet.layer.Layer ... & nnet.layer.Acceleratable ... % Example custom SReLU layer with codegen support. %#codegen properties (Learnable) % Layer learnable parameters LeftSlope RightSlope LeftThreshold RightThreshold end methods function layer = codegenSReLULayer(args) % layer = codegenSReLULayer creates a SReLU layer. % layer = codegenSReLULayer(name) also specifies the layer % name. arguments nargin == 0 args.Name = "" end % Set layer name. layer.Name = args.Name; % Set layer description. layer.Description = "SReLU"; end function layer = initialize(layer,layout) % layer = initialize(layer,layout) initializes the layer % learnable parameters using the specified input layout. % Find number of channels. idx = finddim(layout,"C"); numChannels = layout.Size(idx); % Initialize empty learnable parameters. sz = ones(1,numel(layout.Size); sz(idx) = numChannels; if isempty(layer.LeftSlope) layer.LeftSlope = rand(sz); end if isempty(layer.RightSlope) layer.RightSlope = rand(sz); end if isempty(layer.LeftThreshold) layer.LeftThreshold = rand(sz); end if isempty(layer.RightThreshold) layer.RightThreshold = rand(sz); end end function Y = predict(layer, X) % Y = predict(layer, X) forwards the input data X through the % layer and outputs the result Y. tl = layer.LeftThreshold; al = layer.LeftSlope; tr = layer.RightThreshold; ar = layer.RightSlope; Y = (X <= tl) .* (tl + al.*(X-tl)) ... + ((tl < X) & (X < tr)) .* X ... + (tr <= X) .* (tr + ar.*(X-tr)); end end end
コード生成の互換性に関するカスタム層のチェック
カスタム層 codegenSReLULayer
について、コード生成の互換性をチェックします。
この例にサポート ファイルとして添付されているカスタム層 codegenSReLULayer
は、入力データに SReLU 演算を適用します。この層にアクセスするには、この例をライブ スクリプトとして開きます。
層のインスタンスを作成します。
layer = codegenSReLULayer;
層への典型的な入力に要求される入力サイズと形式を指定する networkDataLayout
オブジェクトを作成します。有効な入力サイズとして [24 24 20 128]
を指定します。ここで、各次元は、前の層の出力における高さ、幅、チャネル数、および観測値の数に対応します。形式を "SSCB"
(空間、空間、チャネル、バッチ) として指定します。
validInputSize = [24 24 20 128];
layout = networkDataLayout(validInputSize,"SSCB");
checkLayer を使用して層の有効性をチェックします。コード生成の互換性をチェックするには、CheckCodegenCompatibility
オプションを true
に設定します。関数 checkLayer
は、層がコード生成と互換性のある MATLAB 関数を使用しているかどうかをチェックしません。カスタム層定義がコード生成でサポートされているかどうかをチェックするには、まず "コード生成の準備状態" アプリを使用します。詳細については、コード生成の準備状態ツールを使ったコードのチェック (MATLAB Coder)を参照してください。
checkLayer(layer,layout,CheckCodegenCompatibility=true)
Skipping GPU tests. No compatible GPU device found. Running nnet.checklayer.TestLayerWithoutBackward .......... .......... ..... Done nnet.checklayer.TestLayerWithoutBackward __________ Test Summary: 25 Passed, 0 Failed, 0 Incomplete, 9 Skipped. Time elapsed: 1.0397 seconds.
この関数によって層に関する問題は検出されていません。
参照
[1] Hu, Xiaobin, Peifeng Niu, Jianmei Wang, and Xinxin Zhang. “A Dynamic Rectified Linear Activation Units.” IEEE Access 7 (2019): 180409–16. https://doi.org/10.1109/ACCESS.2019.2959036.
参考
trainnet
| trainingOptions
| dlnetwork
| functionLayer
| checkLayer
| setLearnRateFactor
| setL2Factor
| getLearnRateFactor
| getL2Factor
| findPlaceholderLayers
| replaceLayer
| PlaceholderLayer