並列分散処理ニューラルネットワーク
Parallel Distributed Processing: PDP
中間層が1層のニューラルネットワーク
並列分散処理ニューラルネットワークPDPのプログラムPDP.exeをVisual C++2008で作成した。プログラムPDP.exeは.NET Framework 3.5対応であるので、.NET Framework 3.5のインストールされているパソコンであれば、プログラム名PDP.exeをクリックすればダウンロード・実行できたが、現在のWindows 10ではブロックされた(2021.09.27)。ソースファイルなどをまとめた圧縮ファイルPDP.zipをダウンロード展開してVisual Studio 2019で開くと、Visual Studioによってアップデートされ、実行できた。.NET C++を利用する場合のVisual Studioのインストールの説明はこのウェブサイトで行っている。
PDPはRumelhartら(1986)にまとめられているモデルであるが、中間層(hidden layer)が1層のニューラルモデルで、学習アルゴリズムはバックプロパゲーションである。中間層が2層以上のものは深層学習(deep artificial Neural Network)と呼ばれている(Raschkaら、2019)。プログラムとPDPについての説明は、このウェブサイトの後半で説明するが、まずプログラムの使い方を以下に説明する。
プログラムを実行すると図1のフォームが表示される。
図1
フォームの小円を左ボタンでクリックする、あるいは、左ボタンを押したまま小円の上でマウスの矢印を動かすと、その小円の色が赤に変わる。右ボタンによるクリック、あるいは右ボタンを押した状態でのマウスの移動のときは、緑色に変わる。パターンの設定後、「Store-1」をクリックすると、そのパターンはカテゴリー1のものとして設定される。
図2 「Store-1」をクリックしてカテゴリー1のパターンとして設定。
以下、同様に「Store-2」ボタン、「Store-3」ボタンをクリックすることにより、そのときのパターンがカテゴリー2、カテゴリー3のパターンとして設定される。
図3 「Store-2」ボタンをクリックしてカテゴリー2のパターンとして設定。
図4 「Store-3」ボタンをクリックしてカテゴリー3のパターンとして設定。
学習用の弁別パターンは、赤い小円が1、緑の小円が0として入力層のニューロンに与えられる。入力層に与えられたパターンは、入力層の赤の小円に対応する部位のニューロンが刺激されて興奮していると解釈する。すなわち、赤の小円で描かれたパターンの学習が行われる。
設定された入力用パターンは、Load-1〜Load-3ボタンのクリックによって表示して確認することができる。
3つの弁別パターンの設定後、Trainingボタンをクリックすると、図5のようなフォームが表示される。
図5 Trainingボタンのクリックで表示されるフォーム
Startボタンをクリックすると学習が始まる。学習は、3つの刺激パターンの学習、および、それに続く弁別テストとその成績の表示の繰り返しである。学習されるべき入力パターンとして与えられている3つのパターンそれぞれについての直近20回分の正答率が、フォームの上部に表示される(図6)。
図6 学習中のフォーム
フォームの下に、3×3の形式で出力ユニットの値が表示されている。i行目のj列目の値は、パターンiに対するj番目の出力ユニットの値である。対角線上の値が1に近く、それ以外の値は0に近くなるまで学習を進める。十分に1、あるいは0に近くなったところで、Stopボタンをクリックして学習を止める。
図7 学習の終了。
図7は、対角線上の値が0.99以上、それ以外の値が0.01以下になったところでStopボタンをクリックしたものである。Exitボタンのクリックでメインフォームに戻る(図8)。
図8 メインフォームに戻る。
図8のフォームの「Discrimi」ボタンをクリックすると、弁別テスト用のフォームが表示される(図9)。
図9 弁別テスト用フォーム。
弁別テスト用パターンを適当に設定して、「What?」ボタンをクリックすると、設定されたパターンに対する出力の一番大きい出力ユニットの番号が、弁別反応としてTextBoxに表示される(図10)。
図10 設定したパターンに対する反応がWhatボタンの下に表示される。
図10のフォームでExitボタンをクリックすると、図11のメインフォームに戻る。
図11 戻ったメインフォーム。
このフォームのExitボタンのクリックで、プログラムは終了する。
PDPの仕組み
ここでの説明は、拙著「岡本安晴『Delphiでエンジョイプログラミング:心と行動の科学がわかる心理学シミュレーション』CQ出版社、1999」の原稿をもとに作成したものであるので、詳しくは拙著を参照されたい。なお、以下の議論は、中間層が2層以上の場合においても成り立つことに注意されたい。
神経細胞の働きを図12のようにモデル化したものを考え、ニューロンあるいはユニットと呼ぶ。
図12 ニューロン(ユニット)のモデル
ニューロンは、いくつかの入力を受けて、それらの重み付き和の値に応じて出力が決まる。入力、および出力は、0以上1以下の値であるとする。0に近いほどニューロンの活動レベルは低く、1に近いほど活動レベルは高いことを表わす。1つのニューロンjへの入力がb個あるとき、それらを で表わし、それらに対する重みを、…、で表わすと、ニューロンjへの入力の重み付き和は次式で与えらる。
入力の重み付き和に対するニューロンjの出力を与える関数を次のようにおく。
はニューロンjの閾値に対応するものである。
関数
は、図13のような形のものである。
図13 関数
Rumelhartら(1986)のニューラルネットPDP(Parallel Distributed Processing)モデルでは、刺激の入力のためのニューロンの集まり(入力層)と、それらに対する反応を表わすニューロンの集まり(出力層)の2つの層の間に、1つ以上のニューロンの集まり(中間層)を置いている。図14は、中間層が1層の場合のモデルである。
図14 PDPモデルの例
入力層に刺激パターンを与えたとき、出力層からの反応が、予め正しい反応パターンとして設定されているものになるように、重みを変化させる。PDPモデルでは、このための方法として誤差逆伝播法(backpropagation)と呼ばれている次のような方法が用いられている。
刺激パターンpを入力層に与えたときの出力層のユニットjの出力をで表わす。このパターンpに対して出力ユニットjが出力するべき反応量をで表わす。このは、ニューラルネットに、入力パターンpに対する反応パターンとして学習させる出力なので、教師信号と呼ばれている。
ニューラルネットの学習は、誤差量として与えられる次の目的関数
が最小になるように、ニューロンiからjへの重みなどを変えていくことによって行われる。の添え字pは、パターンpに対する誤差量であることを表わす。
を最小化するの値は、最急降下法の考え方で求める。すなわち、の値をの方向に変化させる。
まず、
と変形する。ここで、はパターンpに対するニューロンjへの入力の重み付き和
である。上式の記号におけるiは、ニューロンjへの入力ニューロンiとして接続されているすべてのニューロンiについての和であることを表わす。はニューロンiのパターンpに対する出力である。
とおく。
を次のように変形する。
ここで、
なので、
となる。
また、
より、
となる。
ここで、次式
が成り立つので、
となる。
ゆえに、
となる。
式(2)〜(4)より、
ここで、
が成り立つ。上式の記号におけるhは、ニューロンjに接続されている入力ニューロンhにわたる和であることを表わす。
したがって、
となる。
いま、ニューロンjが出力層のもの(図15)であるとすると、
となる。上式の記号におけるkは、出力層のニューロンkすべてにわたる和であることを表わす。
図15 ユニットjが出力層に属するとき
したがって、出力層のニューロンjへの入力の重みについては、次式を得る。
図16 ニューロンjが出力層に属さないとき
ニューロンjが出力層のものでないときは(図16)、ニューロンjの出力は、より上位のニューロンkを経由して出力層の出力に反映される。したがって、
となる。ここで、記号におけるkは、ニューロンjの出力を直接受け取っているニューロンkすべてにわたる和であることを表わす。
また、
である。ここで、記号におけるhは、ニューロンkへの入力ニューロンh全体にわたる和であることを表わす。
式(3)の記法に合わせて、
とおけば、式(6)は次のように書ける。
よって、式(3)、(4)より、
上式において、の値は、より上位のニューロンkのを用いて求められている。すなわち、の値が、信号の流れと逆の方向に伝わっている。このことから、式(7)による方法は誤差逆伝播法(Error Back Propagation)と呼ばれている。
式(7)、および式(2)、(3)、(5)より、
となる。
を小さくするためのの変化量をの方向にとるとき、その変化量を次のようにおく。
の値は、Rumelhartら(1986, p.334)では
となっている。
のpは、パターンpに関する最小化を表わしている。すなわち、式(8)による最小化は、パターンごとに行う。これに対して、学習パターン全てにわたって同時に最小化を行う方法(一括学習法)もある。
式(8)による最小化をより効果的に行うために、慣性法と呼ばれている次式によっての値を変える。
ここで、は、最小化のm番目のステップにおけるの変化量を表わす。式(9)は、ステップn+1における変化量に、直前のステップnにおける変化量をmomentum termとして少し加えておくことを表わしている。の値は、Rumelhartら(1986, p.330)では、0.9がよく用いられたものとなっている。
プログラムでは、PDPモデルをクラス型Subjectとして構成している。クラス型Subjectによって表わされているPDPモデルは、入力層、出力層と1つの中間層からなるニューラルネットである。入力層InputNeuronsは100個のニューロン、中間層HiddenNeuronsは10個のニューロン、出力層OutputNeuronsは3個のニューロンで構成されている(図17)。
図17 Subject型でのニューラルネット
クラス型Subjectの宣言を以下に示す。
======================================================
class Subject {
public:
Pattern
InputNeurons; // 入力層ニューロン
double
HiddenNeurons[10]; // 中間層ニューロン
double OutputNeurons[3], // 出力層ニューロン
Target[3]; // 学習されるべき出力パターン
double WInToHid[10][100], // 入力層から中間層への重み
PrevDWInToHid[10][100]; // WInToHidの前回の変化量
double WHidToOut[3][10], // 中間層から出力層への重み
PrevDWHidToOut[3][10]; // WHidToOutの前回の変化量
double Delta[3];
double eta,
a;
Subject(); // ニューラルネットの初期化
virtual ~Subject(){ }
double f( double net
); // 入力から出力への変換
void StudyPattern( Pattern & pattern, int Response ); // パターンの学習
void Discriminate( Pattern & pattern ); // パターンの弁別
int MaxID(); // 最大出力のOutputニューロンを求める
};
======================================================
Subject型のオブジェクトは、コンストラクタSubject( )で初期化される。刺激パターンの学習はメソッドStudyPattern、弁別はメソッドDiscriminateで行っている。
学習パターンの設定は、プログラムの実行開始時に表示されるフォーム(図1)上で行う。図1のフォームは、プログラムの実行開始時に表示されるものである。
誤差逆伝播法(Error Back Propagation)による学習は、以下のコードで実行されている。
=========================================================
for (int j = 0; j
< 3; j++)
for (int i = 0; i
< 10; i++){
double d = eta * (Target[j] - OutputNeurons[j]) * (1
- OutputNeurons[j])
*
OutputNeurons[j] * HiddenNeurons[i]
+
a * PrevDWHidToOut[j][i];
WHidToOut[j][i]
= WHidToOut[j][i] + d;
PrevDWHidToOut[j][i]
= d; //
変化量の保存
//
// WInToHidの変化量の計算で用いるDeltaの設定
//
if (i == 0) Delta[j] = (Target[j] - OutputNeurons[j])
* (1 - OutputNeurons[j])
*
OutputNeurons[j];
}
for (int j = 0; j
< 10; j++)
for (int i = 0; i
< 100; i++){
double dk = 0.0;
for (int k = 0; k
< 3; k++)
dk
+= Delta[k] * WHidToOut[k][j];
double d = eta * HiddenNeurons[j] * (1 -
HiddenNeurons[j])
*
dk * InputNeurons.arry[i] + a * PrevDWInToHid[j][i];
WInToHid[j][i]
= WInToHid[j][i] + d;
PrevDWInToHid[j][i]
= d; // 変化量の保存
}
=========================================================
なお、Visual C++プログラミングの入門書として<岡本安晴「大学生のための心理学VC++プログラミング入門」勁草書房>を上梓した。フォームアプリケーションを.NETのVC++で作成する方法も説明している。
Raschka, S., & Mirjalili, V. (2019). Python machine learning, third ed. Packt.
Rumelhart,D.E., McClelland,J.L. and the PDP Research Group (1986) Parallel distributed processing: Explorations in the microstructure of cognition. Vol.1,2. The MIT Press.