このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
コード生成用のカスタム深層学習層の定義
目的の分類または回帰問題に必要な層が Deep Learning Toolbox™ に用意されていない場合、この例を指針として使用して独自のカスタム層を定義できます。組み込み層の一覧については、深層学習層の一覧を参照してください。
カスタム深層学習層を定義するために、この例で提供するテンプレートを使用できます。この例では、次のステップで説明を進めます。
層の命名 — MATLAB® で使用できるように層に名前を付けます。
層のプロパティの宣言 — 層のプロパティ (学習可能なパラメーターや状態パラメーターなど) を指定します。
コンストラクター関数の作成 (オプション) — 層の構築とそのプロパティ初期化の方法を指定します。コンストラクター関数を指定しない場合、作成時に
Name
、Description
、およびType
の各プロパティは[]
で初期化され、層の入力および出力の数は 1 に設定されます。初期化関数の作成 (オプション) — ネットワークの初期化時に学習可能なパラメーターと状態パラメーターを初期化する方法を指定します。初期化関数を指定しない場合、ネットワークの初期化時にパラメーターは初期化されません。
順方向関数の作成 — 予測時および学習時に層経由でデータを順方向にパス (順伝播) する方法を指定します。
リセット ステート関数の作成 (オプション) — 状態パラメーターをリセットする方法を指定します。
逆方向関数の作成 (オプション) — 入力データおよび学習可能なパラメーターにおける損失の微分を指定します (逆伝播)。逆方向関数を指定しない場合、順方向関数は
dlarray
オブジェクトをサポートしなければなりません。
コード生成をサポートするカスタム層を作成するには、次のことが必要です。
層は層の定義でプラグマ
%#codegen
を指定しなければなりません。predict
の入力は次のようになっていなければなりません。次元が一致している。各入力の次元の数が同じでなければなりません。
バッチ サイズが一致している。各入力のバッチ サイズが同じでなければなりません。
predict
の出力の次元とバッチ サイズが層の入力と一致していなければなりません。非スカラーのプロパティは、single 配列、double 配列、または文字配列でなければなりません。
スカラーのプロパティは、数値型、logical 型、または string 型でなければなりません。
コード生成では、2 次元イメージ入力または特徴入力のみで中間層がサポートされます。コード生成は、状態プロパティ (属性が State
であるプロパティ) をもつ層をサポートしません。
この例では、学習可能なパラメーターを含む層である PReLU 層[1]を作成し、畳み込みニューラル ネットワークで使用する方法を説明します。PReLU 層はしきい値処理を実行します。各チャネルについて、入力値がゼロよりも小さい場合は、学習時に得られたスカラーによって乗算されます。0 より小さい値の場合、PReLU 層は入力の各チャネルにスケーリング係数 を適用します。これらの係数は学習可能なパラメーターとなり、学習時にその層によって学習されます。
[1] から抜粋した次の図は、ReLU 層の関数と PReLU 層の関数を比較したものです。
中間層テンプレート
中間層のテンプレートを 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 [Z,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: % Z - 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 Z with % Z1,...,ZM, 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 [Z,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: % Z - 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 Z with % Z1,...,ZM, 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,Z,dLdZ,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 % Z - Layer output data % dLdZ - 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 Z and dlZ with % Z1,...,ZM and dLdZ,...,dLdZM, 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
を codegenPreluLayer
に置き換え、層を説明するコメントを追加します。
classdef codegenPreluLayer < nnet.layer.Layer & nnet.layer.Formattable % Example custom PReLU layer with codegen support. ... end
逆方向関数を指定しない場合、既定では、層関数は "書式化されていない" dlarray
オブジェクトを入力として受け取ります。層が、"書式化された" dlarray
オブジェクトを入力として受け取り、さらに書式化された dlarray
オブジェクトを出力するように指定するには、カスタム層の定義時に nnet.layer.Formattable
クラスから継承します。
この層には書式設定可能な入力が必要ないため、オプションの nnet.layer.Formattable
スーパークラスを削除します。
classdef codegenPreluLayer < nnet.layer.Layer % Example custom PReLU layer with codegen support. ... end
次に、コンストラクター関数 myLayer
(methods
セクションの最初の関数) の名前を層と同じ名前に変更します。
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)
セクションにリストすることによって宣言します。
既定では、カスタム中間層に次のプロパティがあります。これらのプロパティを properties
セクションで宣言しないでください。
Property | 説明 |
---|---|
Name | 層の名前。文字ベクトルまたは string スカラーとして指定します。Layer 配列入力の場合、関数 trainnet 、trainNetwork 、assembleNetwork 、layerGraph 、および 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 型でなければなりません。
PReLU 層には追加のプロパティが必要ないため、properties
セクションは削除できます。
PReLU 層には、唯一の学習可能なパラメーターとしてスケーリング係数 a があります。この学習可能なパラメーターを properties (Learnable)
セクションで宣言し、パラメーター Alpha
を呼び出します。
properties (Learnable)
% Layer learnable parameters
% Scaling coefficient
Alpha
end
コンストラクター関数の作成
層を構築する関数を作成し、層のプロパティを初期化します。層を作成するために必要な変数をコンストラクター関数への入力として指定します。
PReLU 層のコンストラクター関数に必要な 2 つの入力引数は、想定される入力データのチャネル数と層の名前です。チャネルの数は学習可能なパラメーター Alpha
のサイズを指定します。numChannels
および name
という名前の 2 つの入力引数を関数 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
プロパティを設定して、層に 1 行の説明を指定します。層のタイプとサイズの説明を設定します。
% Set layer description. layer.Description = "PReLU with " + numChannels + " channels";
PReLU 層の場合、入力値が負であれば、層は入力の各チャネルに Alpha
の対応するチャネルを乗算します。学習可能なパラメーター Alpha
をサイズ 1 x 1 x numChannels
のランダム ベクトルとして初期化します。3 つ目の次元をサイズ 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')
により 3 つのチャネルを持ち、名前が 'prelu'
の PReLU 層が作成されます。
順方向関数の作成
予測時と学習時に使用する層の順方向関数を作成します。
"予測時" に層経由でデータを順伝播させて結果を出力する、predict
という名前の関数を作成します。
関数 predict
の構文は、層のタイプによって異なります。
Z = predict(layer,X)
は、層を介して入力データX
を転送し、結果Z
を出力します。この場合、layer
は、1 つの入力と 1 つの出力をもちます。[Z,state] = predict(layer,X)
は、更新された状態パラメーターstate
も出力します。この場合、layer
は 1 つの状態パラメーターをもちます。
複数の入力、複数の出力、または複数の状態パラメーターを使用して、層の構文を調整できます。
複数の入力をもつ層の場合、
X
をX1,...,XN
に置き換えます。ここで、N
は入力の数です。NumInputs
プロパティはN
と一致しなければなりません。複数の出力をもつ層の場合、
Z
をZ1,...,ZM
に置き換えます。ここで、M
は出力の数です。NumOutputs
プロパティはM
と一致しなければなりません。複数の状態パラメーターをもつ層の場合、
state
をstate1,...,stateK
に置き換えます。ここで、K
は状態パラメーターの数です。
ヒント
層への入力の数が変化する可能性がある場合、X1,…,XN
ではなく varargin
を使用します。この場合、varargin
は入力の cell 配列です。ここで、varargin{i}
は Xi
に対応します。
出力の数が変化する可能性がある場合、Z1,…,ZN
ではなく varargout
を使用します。この場合、varargout
は出力の cell 配列です。ここで、varargout{j}
は Zj
に対応します。
PReLU 層の入力および出力はそれぞれ 1 つのみであるため、PReLU 層の predict
の構文は Z = predict(layer,X)
になります。
コード生成では、2 次元イメージ入力のみでカスタム中間層がサポートされます。入力は、h x w x c x N の配列です。ここで、h、w、および c は、それぞれイメージの高さ、幅、およびチャネル数に対応します。N は観測値の数です。観測値の次元は 4 です。
コード生成のサポートでは、層入力すべての次元数およびバッチ サイズは同じでなければなりません。
既定では、層は学習時に predict
を順方向関数として使用します。学習時に別の順方向関数を使用する、またはカスタム逆方向関数に必要な値を保持するには、forward
という名前の関数も作成しなければなりません。ソフトウェアは関数 forward
のコードを生成しませんが、コード生成の互換性がなければなりません。
関数 forward
は "学習時" に層経由でデータを順伝播させ、メモリ値も出力します。
関数 forward
の構文は、層のタイプによって異なります。
Z = forward(layer,X)
は、層を介して入力データX
を転送し、結果Z
を出力します。この場合、layer
は、1 つの入力と 1 つの出力をもちます。[Z,state] = forward(layer,X)
は、更新された状態パラメーターstate
も出力します。この場合、layer
は 1 つの状態パラメーターをもちます。[__,memory] = forward(layer,X)
は、前述の構文のいずれかを使用して、カスタム関数backward
のメモリ値も返します。カスタム関数forward
とカスタム関数backward
の両方が層に存在する場合、順方向関数によってメモリ値が返されなければなりません。
複数の入力、複数の出力、または複数の状態パラメーターを使用して、層の構文を調整できます。
複数の入力をもつ層の場合、
X
をX1,...,XN
に置き換えます。ここで、N
は入力の数です。NumInputs
プロパティはN
と一致しなければなりません。複数の出力をもつ層の場合、
Z
をZ1,...,ZM
に置き換えます。ここで、M
は出力の数です。NumOutputs
プロパティはM
と一致しなければなりません。複数の状態パラメーターをもつ層の場合、
state
をstate1,...,stateK
に置き換えます。ここで、K
は状態パラメーターの数です。
ヒント
層への入力の数が変化する可能性がある場合、X1,…,XN
ではなく varargin
を使用します。この場合、varargin
は入力の cell 配列です。ここで、varargin{i}
は Xi
に対応します。
出力の数が変化する可能性がある場合、Z1,…,ZN
ではなく varargout
を使用します。この場合、varargout
は出力の cell 配列です。ここで、varargout{j}
は Zj
に対応します。
PReLU 演算は次の式で表されます。
ここで、 はチャネル i の非線形活性化 f の入力、 は負の部分の勾配を制御する係数です。 の添字 i は、別のチャネルでは非線形活性化が変わる場合があることを示しています。
この演算を predict
に実装します。predict
では、入力 X
がこの方程式の x に対応します。出力 Z
は に対応します。
関数の構文を説明するコメントを関数の上部に追加します。
ヒント
zeros
のような関数を使用して配列を事前に割り当てる場合、これらの配列のデータ型が層関数の入力と一致していることを確認しなければなりません。別の配列と同じデータ型のゼロの配列を作成するには、zeros
の "like"
オプションを使用します。たとえば、配列 X
と同じデータ型でサイズが sz
のゼロの配列を初期化するには、Z = zeros(sz,"like",X)
を使用します。
順方向関数が dlarray
入力を完全にサポートしている場合、関数 backward
の実装はオプションです。コード生成のサポートでは、関数 predict
が数値入力もサポートしなければなりません。
PReLU 演算の出力を計算する 1 つの方法は、次のコードを使用することです。
Z = max(X,0) + layer.Alpha .* min(0,X);
.*
演算を使用した暗黙的な拡張がサポートされないため、代わりに関数 bsxfun
を使用できます。Z = max(X,0) + bsxfun(@times, layer.Alpha, min(0,X));
bsxfun
では dlarray
入力がサポートされません。コード生成と dlarray
入力の両方をサポートする関数 predict
を実装するには、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
について、コード生成の互換性をチェックします。
この例にサポート ファイルとして添付されているカスタム層 codegenPreluLayer
は、入力データに PReLU 演算を適用します。この層にアクセスするには、この例をライブ スクリプトとして開きます。
層のインスタンスを作成し、checkLayer
を使用してその有効性をチェックします。層への典型的な入力における 1 つの観測値のサイズとして、有効な入力サイズを指定します。層には 4 次元配列を入力する必要があり、最初の 3 つの次元は前の層の出力における高さ、幅、およびチャネル数に対応し、4 番目の次元は観測値に対応します。
観測値の入力の典型的なサイズを指定し、'ObservationDimension'
オプションを 4 に設定します。有効な入力サイズの代わりに networkDataLayout
オブジェクトを指定する場合は、観測次元を指定する必要はありません。コード生成の互換性をチェックするには、CheckCodegenCompatibility
オプションを true
に設定します。関数 checkLayer
は、関数がコード生成と互換性があるかどうかをチェックしません。カスタム層定義がコード生成でサポートされているかどうかをチェックするには、まず "コード生成の準備状態" アプリを使用します。詳細については、コード生成の準備状態ツールを使ったコードのチェック (MATLAB Coder)を参照してください。
layer = codegenPreluLayer(20,"prelu");
validInputSize = [24 24 20];
checkLayer(layer,validInputSize,ObservationDimension=4,CheckCodegenCompatibility=true)
Skipping initialization tests. The layer does not have an initialize function. Skipping GPU tests. No compatible GPU device found. Running nnet.checklayer.TestLayerWithoutBackward .......... .......... ... Done nnet.checklayer.TestLayerWithoutBackward __________ Test Summary: 23 Passed, 0 Failed, 0 Incomplete, 11 Skipped. Time elapsed: 0.90077 seconds.
この関数によって層に関する問題は検出されていません。
参照
[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.
参考
functionLayer
| checkLayer
| setLearnRateFactor
| setL2Factor
| getLearnRateFactor
| getL2Factor
| findPlaceholderLayers
| replaceLayer
| assembleNetwork
| PlaceholderLayer