ニューラル ネットワークの学習の概念
このトピックは、ニューラル ネットワーク設計のワークフローで説明されている設計ワークフローの一部です。
このトピックでは、2 つの異なる学習スタイルについて説明します。"インクリメンタル" 学習では、ネットワークに入力が与えられるたびにネットワークの重みとバイアスが更新されます。"バッチ学習" では、すべての入力が与えられた後にのみ、重みとバイアスが更新されます。通常、MATLAB® 環境では、バッチ学習による方法がより効率的であり、Deep Learning Toolbox™ ソフトウェアではバッチ学習が強調されていますが、用途によってはインクリメンタル学習が役に立つため、そのパラダイムも実装されています。
adapt を使用したインクリメンタル学習
インクリメンタル学習は、静的ネットワークと動的ネットワークのどちらにも適用できますが、適応フィルターなどの動的ネットワークでより一般的に使用されています。この節では、静的ネットワークと動的ネットワークの両方についてインクリメンタル学習を実行する方法を説明します。
静的ネットワークのインクリメンタル学習
最初の例で使用した静的ネットワークを再び考えます。各入力が与えられた後に重みとバイアスが更新されるように、インクリメンタルに学習を行います。この場合、関数 adapt
を使用します。入力とターゲットはシーケンスとして与えられます。
次の線形関数を作成するネットワークに学習させるとします。
この場合、次に示す前の入力について、
ターゲットは次のようになります。
インクリメンタル学習の場合、入力とターゲットをシーケンスとして与えます。
P = {[1;2] [2;1] [2;3] [3;1]}; T = {4 5 7 7};
最初に、重みとバイアスの初期値が 0 のネットワークを設定します。また、インクリメンタル学習の効果を示すために、学習率の初期値を 0 に設定します。
net = linearlayer(0,0); net = configure(net,P,T); net.IW{1,1} = [0 0]; net.b{1} = 0;
静的ネットワークでの同時入力によるシミュレーションで説明したように、静的ネットワークの場合、入力が同時ベクトルの行列として与えられても、逐次ベクトルの cell 配列として与えられても、ネットワークのシミュレーションは同じ出力を生成します。ただし、ネットワークの学習時はこのようになりません。関数 adapt
を使用するとき、入力が逐次ベクトルの cell 配列として与えられる場合は、それぞれの入力が与えられるたびに重みが更新されます (インクリメンタル モード)。次の節で示すように、入力が同時ベクトルの行列として与えられる場合は、すべての入力が与えられた後にのみ、重みが更新されます (バッチ モード)。
これでネットワークの学習をインクリメンタルに行う準備が整いました。
[net,a,e,pf] = adapt(net,P,T);
学習率が 0 であるため、ネットワーク出力は 0 のままで、重みは更新されません。誤差はターゲットと等しくなります。
a = [0] [0] [0] [0] e = [4] [5] [7] [7]
次に、学習率を 0.1 に設定した場合、各入力が与えられるたびにネットワークがどのように調整されるかを確認できます。
net.inputWeights{1,1}.learnParam.lr = 0.1; net.biases{1,1}.learnParam.lr = 0.1; [net,a,e,pf] = adapt(net,P,T); a = [0] [2] [6] [5.8] e = [4] [3] [1] [1.2]
最初の入力が与えられるまで更新は行われないため、最初の出力は学習率が 0 の場合と同じです。2 番目の場合、重みが更新されるため、出力が異なります。誤差が計算されるたびに、重みが継続的に変更されます。ネットワークに適切な機能があり、学習率が正しく設定されている場合、誤差は最終的に 0 に近づきます。
動的ネットワークでのインクリメンタル学習
動的ネットワークの学習をインクリメンタルに行うこともできます。実際、これが最も一般的な状況です。
ネットワークにインクリメンタルに学習させる場合、入力とターゲットを cell 配列の要素として与えます。初期入力 Pi
、入力 P
、およびターゲット T
は、cell 配列の要素として次のようになります。
Pi = {1}; P = {2 3 4}; T = {3 5 7};
前述の例でも使用した、入力に 1 つの遅延がある線形ネットワークを考えます。重みを 0 に初期化し、学習率を 0.1 に設定します。
net = linearlayer([0 1],0.1); net = configure(net,P,T); net.IW{1,1} = [0 0]; net.biasConnect = 0;
現在の入力と前の入力を合計して現在の出力を生成するネットワークに学習させるとします。これは、前述の例で使用したものと同じ入力シーケンスですが、シーケンスの最初の項を遅延の初期条件として割り当てる点が異なります。これで、adapt
を使用して、逐次的にネットワークに学習させることができます。
[net,a,e,pf] = adapt(net,P,T,Pi); a = [0] [2.4] [7.98] e = [3] [2.6] [-0.98]
重みがまだ更新されていないため、最初の出力は 0 になります。以降の各タイム ステップで重みが変化します。
バッチ学習
バッチ学習では、すべての入力とターゲットが与えられた後にのみ重みとバイアスが更新され、静的ネットワークと動的ネットワークの両方に適用できます。この節では、両方のタイプのネットワークについて説明します。
静的ネットワークでのバッチ学習
バッチ学習は、adapt
と train
のどちらを使用しても実行できますが、通常はより効率的な学習アルゴリズムにアクセスできる train
が一般的に最適なオプションです。通常、インクリメンタル学習は adapt
を使用して行われ、バッチ学習は train
を使用して行われます。
adapt
を使用した静的ネットワークのバッチ学習では、複数の同時ベクトルから成る 1 つの行列に入力ベクトルを配置しなければなりません。
P = [1 2 2 3; 2 1 3 1]; T = [4 5 7 7];
前述の例で使用した静的ネットワークから始めます。学習率は 0.01 に設定しています。
net = linearlayer(0,0.01); net = configure(net,P,T); net.IW{1,1} = [0 0]; net.b{1} = 0;
adapt
を呼び出すと、trains
(線形ネットワークの既定の適応関数) と learnwh
(重みとバイアスの既定の学習関数) が呼び出されます。trains
は Widrow・Hoff 学習を使用します。
[net,a,e,pf] = adapt(net,P,T); a = 0 0 0 0 e = 4 5 7 7
ネットワークの出力がすべて 0 であることに注意してください。これは、すべての学習セットが与えられるまで、重みが更新されないためです。重みを表示すると、次のようになります。
net.IW{1,1} ans = 0.4900 0.4100 net.b{1} ans = 0.2300
これは、インクリメンタル更新で adapt
を 1 回実行した後に得られる結果と異なります。
次に、train
を使用して同じバッチ学習を実行します。Widrow・Hoff 規則はインクリメンタル モードとバッチ モードのいずれでも使用できるため、adapt
または train
によって呼び出されます (アルゴリズムによってはバッチ モードでしか使用できない (レーベンバーグ・マルカート法など) ため、このようなアルゴリズムは train
によってのみ呼び出されます)。
この場合、入力ベクトルは、同時ベクトルから成る行列または逐次ベクトルから成る cell 配列です。ネットワークが静的であり、また train
は常にバッチ モードで動作するため、train
は、逐次ベクトルから成るすべての cell 配列を同時ベクトルから成る行列に変換します。同時モード演算の方が MATLAB コードでより効率的に実装されるため、可能な限りこちらが使用されます。
P = [1 2 2 3; 2 1 3 1]; T = [4 5 7 7];
ネットワークは同じ方法で設定しています。
net = linearlayer(0,0.01); net = configure(net,P,T); net.IW{1,1} = [0 0]; net.b{1} = 0;
これでネットワークの学習の準備が整いました。adapt
は 1 回しか使用していないため、1 エポックのみ学習させます。線形ネットワークの既定の学習関数は trainb
であり、重みとバイアスの既定の学習関数は learnwh
です。そのため、既定の適応関数が trains
であった前述の例で、adapt
を使用して得られたのと同じ結果が得られます。
net.trainParam.epochs = 1; net = train(net,P,T);
学習を 1 エポック行った後、重みを表示すると次のようになります。
net.IW{1,1} ans = 0.4900 0.4100 net.b{1} ans = 0.2300
これは、adapt
でのバッチ モードの学習と同じ結果です。静的ネットワークでは、入力データの形式に応じて、関数 adapt
はインクリメンタル学習またはバッチ学習を実行できます。データが同時ベクトルの行列として与えられる場合、バッチ学習が実行されます。データがシーケンスとして与えられる場合、インクリメンタル学習が実行されます。train
の場合はこのようにならず、入力の形式に関係なく、常にバッチ学習が実行されます。
動的ネットワークでのバッチ学習
静的ネットワークの学習は比較的簡単です。train
を使用する場合、ネットワークの学習はバッチ モードで行われ、入力は、もとはシーケンス (cell 配列の要素) として渡されていても、同時ベクトル (行列の列) に変換されます。adapt
を使用する場合、入力の形式によって学習の方法が決まります。入力がシーケンスとして渡される場合、ネットワークの学習はインクリメンタル モードで行われます。入力が同時ベクトルとして渡される場合、バッチ モードの学習が使用されます。
通常、動的ネットワークでは、特に学習シーケンスが 1 つだけ存在する場合、train
のみを使用してバッチ モードの学習が行われます。これを説明するために、遅延が 1 つある線形ネットワークを再び考えます。この学習の学習率として 0.02 を使用します (勾配降下アルゴリズムを使用する場合、通常、バッチ モード学習ではインクリメンタル学習の場合よりも小さい学習率を使用します。これは、重みに対するステップ変更が決定される前に、個々の勾配がすべて合計されるためです)。
net = linearlayer([0 1],0.02); net.inputs{1}.size = 1; net.layers{1}.dimensions = 1; net.IW{1,1} = [0 0]; net.biasConnect = 0; net.trainParam.epochs = 1; Pi = {1}; P = {2 3 4}; T = {3 5 6};
前にインクリメンタル学習で使用したのと同じシーケンスでネットワークに学習させますが、今回は、すべての入力が適用された後にのみ、重みを更新するとします (バッチ モード)。入力がシーケンスであるため、ネットワークは逐次モードでシミュレーションされますが、重みはバッチ モードで更新されます。
net = train(net,P,T,Pi);
学習を 1 エポック行った後、重みは次のようになります。
net.IW{1,1} ans = 0.9000 0.6200
これらの重みは、インクリメンタル学習を使用して得られるものと異なります。インクリメンタル学習では、学習セットが 1 回使用される間に、重みが 3 回更新されます。バッチ学習では、重みはエポックごとに 1 回のみ更新されます。
学習のフィードバック
showWindow
パラメーターを使用すると、学習時に学習ウィンドウを表示するかどうかを指定できます。既定では、学習ウィンドウが表示されます。他の 2 つのパラメーター showCommandLine
および show
は、学習中にコマンド ライン出力を生成するかどうか、何エポックごとにコマンド ライン フィードバックを表示するかを決定します。たとえば、次のコードを使用すると、その後に train
を使用してネットワークに学習させるときは、学習ウィンドウがオフになり、学習ステータス情報が 35 エポックごとに表示されます。
net.trainParam.showWindow = false; net.trainParam.showCommandLine = true; net.trainParam.show= 35;
場合によっては、学習の表示をすべて無効にすると便利なことがあります。これを行うには、学習ウィンドウとコマンド ライン フィードバックをオフにします。
net.trainParam.showWindow = false; net.trainParam.showCommandLine = false;
学習時に、学習ウィンドウは自動的に表示されます。