パーセプトロン ニューラル ネットワーク
Rosenblatt [Rose61] は、パーセプトロンの多くのバリエーションを作成しました。最もシンプルなものの 1 つは、対応する入力ベクトルが与えられることにより、正しいターゲット ベクトルを生成するよう重みとバイアスが学習される単層ネットワークです。使用する学習手法はパーセプトロン学習規則と呼ばれます。パーセプトロンは、学習ベクトルから汎化し、最初はランダムに分布している結合から学習する能力により、大いに注目されました。パーセプトロンは、パターン分類の単純な問題に特に適しています。問題を解くことができる場合、高速で信頼できるネットワークです。また、パーセプトロンの動作を理解することは、より複雑なネットワークを理解するための適切な基礎になります。
この節でのパーセプトロンに関する説明は、どうしても簡潔になります。より詳細な説明については、[HDB1996] の第 4 章「Perceptron Learning Rule」を参照してください。単層では解けない難しい問題を多層パーセプトロンを使用して解く方法が説明されています。
ニューロン モデル
ハードリミット伝達関数 hardlim
を使用するパーセプトロン ニューロンを次に示します。
各外部入力は適切な重み w1j で重み付けされ、重み付けされた入力の和がハードリミット伝達関数に送られます。この関数は、バイアスから入力 1 も受け取ります。0 または 1 を返すハードリミット伝達関数を次に示します。
パーセプトロン ニューロンは、伝達関数に渡される正味入力が 0 以上の場合は 1 を生成し、それ以外の場合は 0 を生成します。
ハードリミット伝達関数を使用することで、パーセプトロンは、入力空間を 2 つの領域に分割して入力ベクトルを分類できます。具体的には、正味入力 n が 0 より小さい場合の出力は 0 で、正味入力 n が 0 以上の場合は 1 です。次の図は、重み w1,1 = −1、w1,2 = 1、およびバイアス b = 1 をもつ、2 入力のハードリミット ニューロンの入力空間を示しています。
Wp + b = 0 の "判定境界" 線 L により、2 つの分類領域が形成されます。この線は重み行列 W と垂直で、バイアス b に従ってシフトされます。入力ベクトルが直線 L の左上にある場合、正味入力は 0 より大きくなるため、ハードリミット ニューロンは 1 を出力します。入力ベクトルが直線 L の右下にある場合、ニューロンは 0 を出力します。重みとバイアスの値を選択して境界線の向きを変えたり移動させたりすることで、入力空間を必要に応じて区別できます。
ハードリミット ニューロンにバイアスがない場合、境界線は必ず原点を通過します。バイアスを追加すると、ニューロンは、2 組の入力ベクトルが原点に対して異なる側にない問題を解くことができます。バイアスを使用すると、上のプロットに示したように、判定境界を原点から離れた場所にシフトさせることができます。
パーセプトロン アーキテクチャ
パーセプトロン ネットワークは、一連の重み wi,j を介して R 個の入力に結合された S
個のパーセプトロン ニューロンから成る単層から成り、以下の 2 つの形式で示されます。前と同じように、ネットワーク インデックス i および j は、wi,j が j 番目の入力から i 番目のニューロンへの結合の強度であることを示します。
これから説明するパーセプトロン学習規則では、1 つの単層のみが学習できます。そのため、ここでは単層ネットワークのみを考えます。この制約により、パーセプトロンが実行できる計算が限定されます。パーセプトロンで解ける問題の種類については、制限と注意事項で説明します。
パーセプトロンの作成
パーセプトロンは以下により作成できます。
net = perceptron; net = configure(net,P,T);
ここで、入力引数は以下のとおりです。
P
は R 行 Q 列の行列で、それぞれが R 個の要素をもつ Q 個の入力ベクトルから成ります。T
は S 行 Q 列の行列で、それぞれが S 個の要素をもつ Q 個のターゲット ベクトルから成ります。
通常、パーセプトロンでは関数 hardlim
が使用されるため、これが既定です。
以下のコマンドは、値が 0 および 2 の単一の 1 要素入力ベクトルと、出力が 0 または 1 のいずれかになる 1 つのニューロンを含むパーセプトロン ネットワークを作成します。
P = [0 2]; T = [0 1]; net = perceptron; net = configure(net,P,T);
次のコマンドを実行すると、どのようなネットワークが作成されたか確認できます。
inputweights = net.inputweights{1,1}
以下が得られます。
inputweights = delays: 0 initFcn: 'initzero' learn: true learnFcn: 'learnp' learnParam: (none) size: [1 1] weightFcn: 'dotprod' weightParam: (none) userdata: (your custom info)
既定の学習関数は learnp
です。この関数については、パーセプトロン学習規則 (learnp)で説明します。伝達関数 hardlim
への正味入力は、dotprod
から得られます。この関数は、入力ベクトルと重み行列の積を生成し、バイアスを加算して正味入力を計算します。
既定の初期化関数 initzero
を使用して、重みの初期値が 0 に設定されます。
同様に、
biases = net.biases{1}
により以下が得られます。
biases = initFcn: 'initzero' learn: 1 learnFcn: 'learnp' learnParam: [] size: 1 userdata: [1x1 struct]
バイアスの既定の初期化も 0 であることがわかります。
パーセプトロン学習規則 (learnp)
目的の動作の例についてパーセプトロンに学習させます。目的の動作は、一連の入力と出力のペアにまとめることができます。
ここで、p はネットワークへの入力であり、t は対応する正しい (ターゲット) 出力です。目的は、ニューロンの応答 a とターゲット ベクトル t のと間の差 t − a である誤差 e を小さくすることです。パーセプトロン学習規則 learnp
は、入力ベクトル p および関連する誤差 e が与えられると、パーセプトロンの重みとバイアスに対する望ましい変化を計算します。ターゲット ベクトル t に含まれる値は、0 または 1 のいずれかでなければなりません。これは、(伝達関数 hardlim
を使用する) パーセプトロンでは、これらの値しか出力されないためです。
learnp
が実行されるたびに、パーセプトロンが正しい出力を生成する可能性が高まります。解が存在する場合、パーセプトロン規則は有限の反復回数で解に収束することが証明されています。
バイアスを使用しない場合、learnp
は、重みベクトル w のみを変化させ、重みベクトルが 1 に分類される入力ベクトルの方向を向き、0 に分類される入力ベクトルとは反対の方向を向くようにすることで解を見つけます。この結果、w に対して垂直で、入力ベクトルを適切に分類する判定境界が得られます。
入力ベクトル p が与えられ、ネットワークの応答 a が計算されたときに 1 つのニューロンに生じる条件は 3 通りあります。
ケース 1. 入力ベクトルが与えられ、ニューロンの出力が正しい (a = t および e = t – a = 0) 場合、重みベクトル w は変更されません。
ケース 2. ニューロンの出力が 0 であり、それが 1 である必要がある (a = 0 および t = 1 で e = t – a = 1) 場合は、入力ベクトル p が重みベクトル w に加算されます。これにより、重みベクトルが入力ベクトルに近い方向を向き、この入力ベクトルが今後 1 に分類される可能性が高まります。
ケース 3. ニューロンの出力が 1 であり、それが 0 である必要がある (a = 1 および t = 0 で e = t – a = -1) 場合は、入力ベクトル p が重みベクトル w から減算されます。これにより、重みベクトルが入力ベクトルから離れる方向を向き、この入力ベクトルが今後 0 に分類される可能性が高まります。
パーセプトロン学習規則は、誤差 e = t – a および重みベクトルに対する変化 Δw を使って、より簡潔に書くことができます。
ケース 1. e = 0 の場合、変化 Δw は 0 に等しくなります。
ケース 2. e = 1 の場合、変化 Δw は pT に等しくなります。
ケース 3. e = -1 の場合、変化 Δw は -pT に等しくなります。
ここで、これら 3 つのケースすべては、次の 1 つの式で書くことができます。
ニューロンのバイアスが単に入力が常に 1 である重みであることに注意すると、バイアスの変化についての式が得られます。
ニューロンの層の場合は、次が得られます。
と
パーセプトロン学習規則は、次のようにまとめることができます。
と
ここで、e = t – a です。
それでは、簡単な例を試してみましょう。要素が 2 つだけの 1 つの入力ベクトルを持つ 1 つのニューロンから始めます。
net = perceptron; net = configure(net,[0;0],0);
問題を簡略化するために、バイアスを 0 に、重みを 1 と -0.8 に設定します。
net.b{1} = [0]; w = [1 -0.8]; net.IW{1,1} = w;
入力とターゲットのペアは、次で与えられます。
p = [1; 2]; t = [1];
次により出力と誤差を計算できます。
a = net(p) a = 0 e = t-a e = 1
関数 learnp
を使用して重みの変化を求めます。
dw = learnp(w,p,[],[],[],[],e,[],[],[],[],[]) dw = 1 2
これにより、次のようにして新しい重みが得られます。
w = w + dw w = 2.0000 1.2000
新しい重み (およびバイアス) を求めるプロセスは、誤差がなくなるまで繰り返すことができます。パーセプトロン学習規則は、パーセプトロンで解けるすべての問題について有限のステップ数で収束することが約束されていることを思い出してください。これには、線形分離可能なすべての分類問題が含まれます。このような場合に分類対象のオブジェクトは 1 本の直線で区切ることができます。
学習 (train)
sim
と learnp
を繰り返し使用して、入力をパーセプトロンに与え、誤差に従ってパーセプトロンの重みとバイアスを変化させると、パーセプトロンで "解ける" 問題の場合、最終的にその問題を解く重みとバイアスが求まります。学習の入力およびターゲット ベクトルすべてを一通り経由することを、"パス" と呼びます。
関数 train
は、そのような計算のループを実行します。それぞれのパスで、関数 train
は、指定された入力シーケンスを一通り実施します。つまり、入力が与えられると、シーケンス内の各入力ベクトルについて出力、誤差、およびネットワーク調整を計算します。
train
は、結果として得られるネットワークが正しく機能することを保証しないことに注意してください。すべてのターゲットが到達されているかどうかを確認するため各入力ベクトルのネットワーク出力を計算することで、W および b の新しい値を確認しなければなりません。ネットワークが正常に機能しない場合、より多くの学習パス用の新しい重みとバイアスで train
を再度呼び出して更に学習させたり、問題を解析してパーセプトロンに適した問題かどうかを確認したりできます。パーセプトロンで解けない問題については、制限と注意事項で説明します。
学習手順を説明するために、簡単な問題を解いてみます。2 つの要素から成る 1 つのベクトル入力を持つ 1 ニューロン パーセプトロンを考えます。
このネットワークと今から考える問題はとてもシンプルであるため、必要に応じて手計算を行い、何が行われているかを把握することができます。以下で説明する問題は、[HDB1996] の問題を参考にしています。
次の分類問題があり、単一ベクトル入力、2 要素のパーセプトロン ネットワークによってこの問題を解くとします。
初期の重みとバイアスを使用します。この計算の各ステップの変数を、変数の後のかっこ内の数字で表します。つまり、上記の初期値は W(0) および b(0) です。
まず、初期の重みとバイアスを使用して、最初の入力ベクトル p1 に対するパーセプトロンの出力 a を計算します。
出力 a はターゲット値 t1 に等しくないので、パーセプトロン規則を使用し、誤差に基づいて重みとバイアスの増分変化を求めます。
新しい重みとバイアスは、パーセプトロンの更新規則を使用して計算できます。
ここで、次の入力ベクトル p2 を与えます。出力は以下のように計算されます。
この場合、ターゲットは 1 であるため、誤差は 0 です。したがって、重みとバイアスには変化がなく、W(2) = W(1) = [−2 −2] および b(2) = b(1) = −1 となります。
このやり方で続け、次に p3 の提供、出力と誤差の計算、重みとバイアスの変更などを行います。4 つの入力すべてを一通り処理した後、値 W(4) = [−3 −1] および b(4) = 0 が得られます。満足な解が得られたかどうかを判断するために、すべての入力ベクトルを一通り処理し、そのすべてが目的のターゲット値を生成するかどうかを確認します。4 番目の入力ではそのようにはなりませんが、このアルゴリズムは 6 回目の入力の提供で収束します。最終的な値は次のようになります。
W(6) = [−2 −3] および b(6) = 1。
これで手計算は終わりです。関数 train
を使用して、これを行うにはどうすればよいでしょうか。
次のコードはパーセプトロンを定義します。
net = perceptron;
次の単一入力の適用を考え、
p = [2; 2];
ターゲットは次のとおりです。
t = [0];
epochs
を 1 に設定し、train
を入力ベクトル (ここでは 1 つのみ) について 1 回だけ実行します。
net.trainParam.epochs = 1; net = train(net,p,t);
新しい重みとバイアスは次になります。
w = net.iw{1,1}, b = net.b{1} w = -2 -2 b = -1
このように、重みとバイアスの初期値は 0 であり、最初のベクトルのみの学習後の値は、手計算の結果と同じ [−2 −2] と −1 になります。
次に、2 番目の入力ベクトル p2 を適用します。出力は 1 で、これは重みとバイアスが変更されるまでそのままですが、ここで、ターゲットは 1 であるため、誤差は 0、変化は 0 になります。このように、前の結果から始め、新しい入力ベクトルを繰り返し適用することで進めることができます。ただし、train
を使用すると、この作業を自動的に行うことができます。
1 エポック、つまり、4 つの入力ベクトルすべてから成るシーケンスを経由する単一のパスに train
を適用します。ネットワークの定義から始めます。
net = perceptron; net.trainParam.epochs = 1;
入力ベクトルおよびターゲットは次になります。
p = [[2;2] [1;-2] [-2;2] [-1;1]] t = [0 1 0 1]
ここで、次によりネットワークに学習させます。
net = train(net,p,t);
新しい重みとバイアスは次になります。
w = net.iw{1,1}, b = net.b{1} w = -3 -1 b = 0
これは、前に手作業で得られたものと同じ結果です。
最後に、それぞれの入力について学習済みネットワークのシミュレーションを行います。
a = net(p) a = 0 0 1 1
出力がターゲットとまだ一致しないため、ネットワークに 2 パス以上学習させる必要があります。さらに数エポック試します。この場合、2 エポック後に平均絶対誤差性能が 0 になります。
net.trainParam.epochs = 1000; net = train(net,p,t);
したがって、ネットワークの学習は第 3 エポックで入力が与えられるまで行われました (手計算からわかるように、6 回目の入力ベクトルの提供でこのネットワークは収束します。この収束は 2 回目のエポックの途中で発生しますが、3 回目のエポックでネットワークの収束が検出されます)。最終的な重みとバイアスは次になります。
w = net.iw{1,1}, b = net.b{1} w = -2 -3 b = 1
さまざまな入力に対するシミュレーションで次の出力および誤差が得られます。
a = net(p) a = 0 1 0 1 error = a-t error = 0 0 0 0
学習手順がうまく機能したことを確認できます。ネットワークが収束し、4 つの入力ベクトルに対して正しいターゲット出力を生成しています。
perceptron
で作成されるネットワークの既定の学習関数は trainc
です (これは、net.trainFcn
を実行して確認できます)。この学習関数は、パーセプトロン学習規則をその純粋な形式で適用します。つまり、各入力ベクトルが個別に逐次適用され、入力ベクトルが与えられるたびに重みとバイアスが修正されます。したがって、与えられた問題がシンプルなパーセプトロンでは解けない場合を除き、train
を使用するパーセプトロン学習は有限のステップ数で収束します。
関数 train
は、他のネットワークでもさまざまな方法で使用できます。この基本的な関数の詳細を確認するには、help train
と入力してください。
さまざまなサンプル プログラムを試してみることをお勧めします。たとえば、2 入力パーセプトロンによる分類では、シンプルなパーセプトロンの分類と学習について説明しています。
制限と注意事項
パーセプトロン ネットワークは adapt
によって学習する必要があります。この関数は、入力ベクトルを 1 つずつネットワークに与え、各提供の結果に基づいてネットワークを修正します。adapt
をこの方法で使用することにより、線形分離可能な任意の問題は有限の学習提供回数で解かれることが約束されます。
前述のように、パーセプトロンは関数 train
を使用して学習させることもできます。通常、train
をパーセプトロンに使用する場合、この関数は、入力を一括してネットワークに与え、個々の修正の総和に基づいてネットワークを修正します。残念ながら、このような学習アルゴリズムでパーセプトロンが収束するという証明はありません。そのため、パーセプトロンに train
を使用することは推奨されません。
パーセプトロン ネットワークにはいくつかの制限があります。まず、ハードリミット伝達関数を使用するため、パーセプトロンの出力値は、2 つの値 (0 または 1) のうち 1 つのみです。さらに、パーセプトロンが分類できるのは、線形分離可能な一連のベクトルのみです。直線または平面を描いて入力ベクトルを正しいカテゴリに分けることができる場合、それらの入力ベクトルは線形分離可能です。ベクトルが線形分離不可能な場合、学習を続けても、すべてのベクトルが適切に分類されることはありません。ただし、ベクトルが線形分離可能な場合は、パーセプトロンに適応的に学習させることで、必ず有限時間で解が求められることが証明されています。線形分離不可能なベクトルを試してみることをお勧めします。線形分離不可能な入力ベクトルを分類しようとしても難しいことがわかります。
ただし、複数のパーセプトロンを含むネットワークを使用すると、より難しい問題を解けることを指摘しておく必要があります。たとえば、一連の 4 つのベクトルを異なるグループに分類する場合に、2 本の線を描いてそれらを分けることができるとします。2 つの判定境界で入力を 4 つのカテゴリに分類する、2 ニューロンのネットワークを求めることができます。パーセプトロンに関する他の説明や、より複雑なパーセプトロン問題の考察については、[HDB1996] を参照してください。
外れ値および正規化パーセプトロン規則
長さが他の入力ベクトルよりはるかに大きいまたは小さい "外れ値" 入力ベクトルの存在が原因で、学習に長い時間がかかる場合があります。パーセプトロン学習規則を適用すると、誤差に応じて、現在の重みとバイアスに対して入力ベクトルが加算または減算されます。そのため、大きな要素を持つ入力ベクトルが重みとバイアスに変化を引き起こすと、はるかに小さい入力ベクトルがその変化に打ち勝つのに長時間かかってしまう場合があります。外れ値の入力ベクトルを試し、外れ値が学習にどのような影響を与えるか確認することをお勧めします。
パーセプトロン学習規則を多少変更することで、極端に大きいまたは小さい外れ値の入力ベクトルが学習時間に与える影響を避けることができます。
重みを更新する元の規則は、次のとおりです。
上に示したように、入力ベクトル p が大きいほど、重みベクトル w への影響が大きくなります。そのため、ある入力ベクトルが他の入力ベクトルよりはるかに大きい場合、小さい入力ベクトルはその効果を得るために何度も与えられなければなりません。
これを解決するには、規則を正規化し、重みに対する各入力ベクトルの効果を同じ大きさにします。
正規化パーセプトロン規則は、関数 learnpn
で実装されています。この関数は learnp
とまったく同じように呼び出されます。正規化パーセプトロン規則関数 learnpn
では、実行にかかる時間が多少増えますが、外れ値の入力ベクトルがある場合、エポック数が大幅に減ります。正規化パーセプトロン規則を試し、この正規化学習規則の動作を確認することをお勧めします。