バックプロパゲーション

<?php

/****************************/
/* back propagation model   */
/*      coded by Y.Suganuma */
/****************************/

/******************************************************/
/* バックプロパゲーションの制御(クラス BackControl) */
/******************************************************/
class BackControl {
	protected $alpha;   //重み及びバイアス修正パラメータ
	protected $eata;
	protected $eps;   // 許容誤差
	protected $order;   // 入力パターンの与え方(=0:順番,=1:ランダム)
	protected $p_type;   // 出力先・方法の指定
                         //   =0 : 誤って認識した数だけ出力
                         //   =1 : 認識結果を出力
                         //   =2 : 認識結果と重みを出力
                         //        (負の時は,認識結果と重みをファイルへも出力)
	protected $o_file;   // 出力ファイル名

	/*************************************/
	/* クラスBackControlのコンストラクタ */
	/*      name : 入力データファイル名  */
	/*************************************/
    function BackControl($name)
    {
    	$in = fopen($name, "rb");
	
		$str = trim(fgets($in));
		strtok($str, " ");
		$this->eps = floatval(strtok(" "));
		strtok(" ");
		$this->p_type = intval(strtok(" "));
		if ($this->p_type < 0) {
			strtok(" ");
			$this->o_file = strtok(" ");
		}
    	fscanf($in, "%*s %d %*s %lf %*s %lf", $this->order, $this->eata, $this->alpha);
   
		fclose($in);
    }
}

/*****************************************************/
/* バックプロパゲーションのデータ(クラス BackData) */
/*****************************************************/
class BackData {
	public $noiu;   // 入力ユニットの数
	public $noou;   // 出力ユニットの数
	public $noip;   // 入力パターンの数
	public $iptn;   // iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
                    //              入力ユニットの入力値
                    //                i=0,noip-1  j=0,noiu-1
	public $optn;   // optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
                    //              番目の出力ユニットの目標出力値
                    //                i=0,noip-1  j=0,noou-1

	/************************************/
	/* クラスBackDataのコンストラクタ   */
	/*      name : 入力データファイル名 */
	/************************************/
	function BackData($name)
    {
    	$in = fopen($name, "rb");
    /*
        入力パターン数等
	*/
		fscanf($in, "%*s %d %*s %d %*s %d", $this->noip, $this->noiu, $this->noou);
	/*
	     領域の確保
	*/
		$this->iptn = array($this->noip);
    	for ($i1 = 0; $i1 < $this->noip; $i1++)
    		$this->iptn[$i1] = array($this->noiu);
    
    	$this->optn = array($this->noip);
		for ($i1 = 0; $i1 < $this->noip; $i1++)
			$this->optn[$i1] = array($this->noou);
	/*
	     入力パターン及び各入力パターンに対する出力パターンの入力
	*/
		for ($i1 = 0; $i1 < $this->noip; $i1++) {
			$str = trim(fgets($in));
			strtok($str, " ");
    		for ($i2 = 0; $i2 < $this->noiu; $i2++)
 				$this->iptn[$i1][$i2] = intval(strtok(" "));
			$str = trim(fgets($in));
			strtok($str, " ");
			for ($i2 = 0; $i2 < $this->noou; $i2++)
 				$this->optn[$i1][$i2] = intval(strtok(" "));
		}

		fclose($in);
	}
}

/*******************************************/
/* バックプロパゲーション(クラス Backpr) */
/*******************************************/
class Backpr extends BackControl {
	public $con;   // con[i][j] : 各ユニットに対するバイアスの与え方,及び,
                   // 接続方法
                   //   [i][i] : ユニット(i+1)のバイアスの与え方
                   //     =-3 : 入力値で固定
                   //     =-2 : 入力値を初期値として,学習により変更
                   //     =-1 : 乱数で初期値を設定し,学習により変更
                   //   [i][j] : ユニット(i+1)と(j+1)の接続方法(j>i)
                   //     =0 : 接続しない
                   //     =1 : 接続する(重みの初期値を乱数で設定し,学習)
                   //     =2 : 接続する(重みの初期値を入力で与え,学習)
                   //     =3 : 接続する(重みを入力値に固定)
                   //            i=0,nou-1  j=0,nou-1
	public $f_type;   // シグモイド関数のタイプ
                      //   0 : [0,1]
                      //   1 : [-1,1])
	public $noiu;   // 入力ユニットの数
	public $noou;   // 出力ユニットの数
	public $nohu;   // nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
                    //           には下から順に番号が付けられ,出力層はレ
                    //           ベル(nolvl+1)の隠れ層とも見做される)
                    //             i=0,nolvl
	public $nolvl;   // 隠れユニットの階層数
	public $nou;   // 入力,出力,及び,隠れ層の各ユニットの数の和(各ユニ
                   // ットには最も上の出力ユニットから,隠れ層の各ユニット,
                   // 及び,入力ユニットに至る一連のユニット番号が付けられ
                   // る)
	public $dp;   // dp[i] : ユニット(i+1)の誤差  i=0,nou-1
	public $op;   // op[i] : ユニット(i+1)の出力  i=0,nou-1
	public $theta;   //theta[i] : ユニット(i+1)のバイアス  i=0,nou
	public $w;   // w[i][j] : ユニット(i+1)から(j+1)への重み(j>i)
                 // w[j][i] : (i+1)から(j+1)への重みの前回修正量(j>i)
                 // w[i][i] : ユニット(i+1)のバイアスの前回修正量
                 //   i=0,nou-1  j=0,nou-1

	/************************************************/
    /* クラスBackprのコンストラクタ                 */
    /*      name_c : 制御データ用入力ファイル名     */
    /*      name_s : ネットワーク記述入力ファイル名 */
    /************************************************/
    function Backpr($name_c, $name_s)
    {
    	parent::BackControl($name_c);
    
    	$in = fopen($name_s, "rb");
    /*
         乱数の初期化
	*/
    	mt_srand();
    /*
	     入力ユニット,出力ユニットの数,関数タイプ
	*/
		fscanf($in, "%*s %d %*s %d %*s %d", $this->noiu, $this->noou, $this->f_type);
    	$this->nou = $this->noiu + $this->noou;   // 入力ユニットと出力ユニットの和
    /*
         隠れユニットの階層数と各階層のユニット数
	*/
		$str = trim(fgets($in));
		strtok($str, " ");
		$this->nolvl = intval(strtok(" "));
   
    	$this->nohu               = array($this->nolvl+1);
    	$this->nohu[$this->nolvl] = $this->noou;   // 出力ユニットの数
	
		if ($this->nolvl > 0) {
			strtok(" ");
			for ($i1 = 0; $i1 < $this->nolvl; $i1++) {
				$this->nohu[$i1] = intval(strtok(" "));
    			$this->nou      += $this->nohu[$i1];
    		}
		}
    /*
         領域の確保
    */
    	$this->con = array($this->nou);
    	for ($i1 = 0; $i1 < $this->nou; $i1++) {
    		$this->con[$i1] = array($this->nou);
    		for ($i2 = 0; $i2 < $this->nou; $i2++)
    			$this->con[$i1][$i2] =  ($i1 == $i2) ? -1 : 0;
    	}
    
    	$this->w = array($this->nou);
		for ($i1 = 0; $i1 < $this->nou; $i1++) {
    		$this->w[$i1] = array($this->nou);
    		for ($i2 = 0; $i2 < $this->nou; $i2++)
				$this->w[$i1][$i2] = 0.0;
		}
	
    	$this->dp    = array($this->nou);
    	$this->op    = array($this->nou);
    	$this->theta = array($this->nou);
	
		for ($i1 = 0; $i1 < $this->nou; $i1++)
    		$this->theta[$i1] = 0.2 * mt_rand() / mt_getrandmax() - 0.1;
    /*
         各ユニットのバイアスとユニット間の接続関係
	*/
						// バイアス
							// バイアスデータの数
		fscanf($in, "%*s %d", $n);
    	fgets($in);
    	fgets($in);
    	fgets($in);
    
    	if ($n > 0) {
							// バイアスデータの処理
    		for ($i0 = 0; $i0 < $n; $i0++) {
 				$str = trim(fgets($in));
   							// ユニット番号
    			$k1 = intval(strtok($str, " "));
   							// 不適当なユニット番号のチェック
    			if ($k1 < 1 || $k1 > ($this->nou-$this->noiu))
    				exit("***error  ユニット番号 ".$k1." が不適当\n");
    							// バイアスの与え方
    			$k1--;
    			$id = intval(strtok(" "));
				$this->con[$k1][$k1] = $id;
    							// バイアスの初期設定
    			switch ($this->con[$k1][$k1]) {
					case -1:
						$x1 = floatval(strtok(" "));
						$x2 = floatval(strtok(" "));
						$this->theta[$k1] = ($x2 - $x1) * mt_rand() / mt_getrandmax() + $x1;
    					break;
    				case -2:
    					$this->theta[$k1] = floatval(strtok(" "));
						break;
					case -3:
    					$this->theta[$k1] = floatval(strtok(" "));
    					break;
    				default:
						exit("***error  バイアスの与え方が不適当\n");
				}
			}
    	}
    					// 接続方法
    						// 接続データの数
		fscanf($in, "%*s %d", $n);
    	fgets($in);
    	fgets($in);
    	fgets($in);
    
    	if ($n > 0) {
    						// 接続データの処理
    		for ($i0 = 0; $i0 < $n; $i0++) {
 				$str = trim(fgets($in));
    							// 接続情報
     			$k1 = intval(strtok($str, " "));
     			$k2 = intval(strtok(" "));
     			$k3 = intval(strtok(" "));
      			$k4 = intval(strtok(" "));
   							// 不適切な接続のチェック
    			$sw = 0;
    			if ($k1 < 1 || $k2 < 1 || $k3 < 1 || $k4 < 1)
    				$sw = 1;
				else {
    				if ($k1 > $this->nou || $k2 > $this->nou || $k3 > $this->nou || $k4 > $this->nou)
    					$sw = 1;
					else {
						if ($k1 > $k2 || $k3 > $k4)
							$sw = 1;
    					else {
    						if ($k4 >= $k1)
    							$sw = 1;
							else {
								$l1 = -1;
    							$k  = 0;
    							for ($i1 = $this->nolvl; $i1 >= 0 && $l1 < 0; $i1--) {
    								$k += $this->nohu[$i1];
									if ($k1 <= $k)
										$l1 = $i1;
								}
								$l2 = -1;
    							$k  = 0;
    							for ($i1 = $this->nolvl; $i1 >= 0 && $l2 < 0; $i1--) {
    								$k += $this->nohu[$i1];
									if ($k4 <= $k)
    									$l2 = $i1;
    							}
    							if ($l2 <= $l1)
    								$sw = 1;
    						}
    					}
    				}
    			}
    
    			if ($sw > 0)
    				exit("***error  ユニット番号が不適当(".$k1." ".$k2." ".$k3." ".$k4."\n");
								// 重みの初期値の与え方
				$k1--;
				$k2--;
    			$k3--;
    			$k4--;
    
      			$id = intval(strtok(" "));
	
    			if ($id == 1) {
					$x1 = floatval(strtok(" "));
					$x2 = floatval(strtok(" "));
				}
    			else {
					if ($id > 1)
						$x1 = floatval(strtok(" "));
					else {
						if ($id != 0)
    						exit("***error  接続方法が不適当\n");
					}
    			}
    							// 重みの初期値の設定
    			for ($i1 = $k3; $i1 <= $k4; $i1++) {
    				for ($i2 = $k1; $i2 <= $k2; $i2++) {
    					$this->con[$i1][$i2] = $id;
    					switch ($id) {
    						case 0:
    							$this->w[$i1][$i2] = 0.0;
 								break;
   						case 1:
    							$this->w[$i1][$i2] = ($x2 - $x1) * mt_rand() / mt_getrandmax() + $x1;
    							break;
							case 2:
    							$this->w[$i1][$i2] = $x1;
    							break;
							case 3:
								$this->w[$i1][$i2] = $x1;
								break;
    					}
    				}
    			}
			}
		}
    
    	fclose($in);
    }
	
	/******************************************/
	/* 誤差の計算,及び,重みとバイアスの修正 */
	/*      ptn[$i1] : 出力パターン            */
    /******************************************/
    function Err_back($k0, $ptn)
    {
		for ($i1 = 0; $i1 < $this->nou-$this->noiu; $i1++) {
    					// 誤差の計算
    		if ($i1 < $this->noou) {
    			if ($this->f_type == 0)
    				$this->dp[$i1] = ($ptn[$i1] - $this->op[$i1]) * $this->op[$i1] * (1.0 - $this->op[$i1]);
    			else
    				$this->dp[$i1] = 0.5 * ($ptn[$i1] - $this->op[$i1]) * ($this->op[$i1] - 1.0) * ($this->op[$i1] + 1.0);
    		}
    		else {
    			$x1 = 0.0;
    			for ($i2 = 0; $i2 < $i1; $i2++) {
					if ($this->con[$i2][$i1] > 0)
    					$x1 += $this->dp[$i2] * $this->w[$i2][$i1];
    			}
				if ($this->f_type == 0)
					$this->dp[$i1] = $this->op[$i1] * (1.0 - $this->op[$i1]) * $x1;
				else
    				$this->dp[$i1] = 0.5 * ($this->op[$i1] - 1.0) * ($this->op[$i1] + 1.0) * $x1;
    		}
    					// 重みの修正
			for ($i2 = $i1+1; $i2 < $this->nou; $i2++) {
				if ($this->con[$i1][$i2] == 1 || $this->con[$i1][$i2] == 2) {
    				$x1                 = $this->eata * $this->dp[$i1] * $this->op[$i2] + $this->alpha * $this->w[$i2][$i1];
    				$this->w[$i2][$i1]  = $x1;
    				$this->w[$i1][$i2] += $x1;
				}
			}
						// バイアスの修正
			if ($this->con[$i1][$i1] >= -2) {
    			$x1                = $this->eata * $this->dp[$i1] + $this->alpha * $this->w[$i1][$i1];
    			$this->w[$i1][$i1] = $x1;
    			$this->theta[$i1] += $x1;
			}
    	}
    }
    
    /********************************************************/
    /* 与えられた入力パターンに対する各ユニットの出力の計算 */
    /********************************************************/
    function Forward()
    {
    	for ($i1 = $this->nou-$this->noiu-1; $i1 >= 0; $i1--) {
    
    		$sum = -$this->theta[$i1];
	
    		for ($i2 = $i1+1; $i2 < $this->nou; $i2++) {
    			if ($this->con[$i1][$i2] > 0)
					$sum -= $this->w[$i1][$i2] * $this->op[$i2];
			}
	
    		$this->op[$i1] = ($this->f_type == 0) ? 1.0 / (1.0 + exp($sum)) : 1.0 - 2.0 / (1.0 + exp($sum));
    	}
	}
	
    /*****************************/
    /* 学習の実行                */
    /*      p : 認識パターン     */
	/*      m_tri : 最大学習回数 */
	/*****************************/
	function Learn($p, $m_tri)
	{
    	$k0 = -1;
    /*
         エラーチェック
	*/
    	if ($this->noiu != $p->noiu || $this->noou != $p->noou)
    		exit("***error  入力または出力ユニットの数が違います\n");
    
    	for ($i1 = 0; $i1 < $m_tri; $i1++) {
    /*
         パターンを与える順番の決定
    */
    		if ($this->order == 0) {       // 順番
    			$k0 += 1;
				if ($k0 >= $p->noip)
    				$k0 = 0;
    		}
			else {                  // ランダム
				$k0 = intval(mt_rand() / mt_getrandmax() * $p->noip);
				if ($k0 >= $p->noip)
    				$k0 = $p->noip - 1;
    		}
   /*
	     出力ユニットの結果を計算
	*/
    		$k1 = $this->nou - $this->noiu;
    		for ($i2 = 0; $i2 < $this->noiu; $i2++)
    			$this->op[$k1+$i2] = $p->iptn[$k0][$i2];
	
			$this->Forward();
	/*
	     重みとバイアスの修正
    */
    		$this->Err_back($k0, $p->optn[$k0]);
    	}
	}
    
    /***********************************************/
    /* 与えられた対象の認識と出力                  */
    /*      p : 認識パターン                       */
    /*      pr : =0 : 出力を行わない               */
    /*           =1 : 出力を行う                   */
    /*           =2 : 出力を行う(未学習パターン) */
    /*      tri : 現在の学習回数                   */
    /*      return : 誤って認識したパターンの数    */
    /***********************************************/
    function Recog($p, $pr, $tri)
	{
    	$No = 0;
    /*
	     ファイルのオープン
	*/
		if ($this->p_type < 0 && $pr > 0) {
    		if ($pr == 1) {
    			$out = fopen($this->o_file, "wb");
    			fwrite($out, "***学習パターン***\n\n");
			}
			else {
    			$out = fopen($this->o_file, "ab");
    			fwrite($out, "\n***未学習パターン***\n\n");
    		}
		}
	/*
	     各パターンに対する出力
	*/
    	for ($i1 = 0; $i1 < $p->noip; $i1++) {
    					// 入力パターンの設定
    		$k1 = $this->nou - $this->noiu;
			for ($i2 = 0; $i2 < $this->noiu; $i2++)
    			$this->op[$k1+$i2] = $p->iptn[$i1][$i2];
    					// 出力の計算
    		$this->Forward();
    					// 結果の表示
    		if ($this->p_type != 0 && $pr > 0) {
    
    			printf("入力パターン%4d    ", $i1+1);
    			for ($i2 = 0; $i2 < $this->noiu; $i2++) {
    				printf("%5.2f", $this->op[$k1+$i2]);
    				if ($i2 == $this->noiu-1)
    					printf("\n");
					else {
    					if((($i2+1) % 10) == 0)
    						printf("\n                    ");
					}
				}
	
    			printf("\n    出力パターン(理想)   ");
    			for ($i2 = 0; $i2 < $this->noou; $i2++) {
    				printf("%10.3f", $p->optn[$i1][$i2]);
					if ($i2 == $this->noou-1)
						printf("\n");
    				else {
    					if((($i2+1) % 5) == 0)
    						printf("\n                         ");
					}
				}
			}
	
    		$sw = 0;
    		if ($this->p_type != 0 && $pr > 0)
    			printf("                (実際)   ");
			for ($i2 = 0; $i2 < $this->noou; $i2++) {
    			if ($this->p_type != 0 && $pr > 0) {
    				printf("%10.3f", $this->op[$i2]);
    				if ($i2 == $this->noou-1)
    					printf("\n");
    				else {
    					if((($i2+1) % 5) == 0)
    						printf("\n                         ");
    				}
    			}
    			if (abs($this->op[$i2]-$p->optn[$i1][$i2]) > $this->eps)
    				$sw = 1;
			}
    
    		if ($sw > 0)
				$No++;
	
			if ($this->p_type < 0 && $pr > 0) {
    
    			$str = "入力パターン".($i1+1)."    ";
    			for ($i2 = 0; $i2 < $this->noiu; $i2++) {
					$str = $str." ".$this->op[$k1+$i2];
					if ($i2 == $this->noiu-1)
    					$str = $str."\n";
    				else {
    					if((($i2+1) % 10) == 0)
							$str = $str."\n                    ";
					}
				}
				fwrite($out, $str);
	
    			$str = "\n    出力パターン(理想)   ";
    			for ($i2 = 0; $i2 < $this->noou; $i2++) {
    				$str = $str." ".$p->optn[$i1][$i2];
					if ($i2 == $this->noou-1)
    					$str = $str."\n";
    				else {
    					if((($i2+1) % 5) == 0)
    						$str = $str."\n                         ";
    				}
    			}
				fwrite($out, $str);
    
    			$str = "                (実際)   ";
    			for ($i2 = 0; $i2 < $this->noou; $i2++) {
    				$str = $str." ".$this->op[$i2];
    				if ($i2 == $this->noou-1)
						$str = $str."\n";
    				else {
    					if((($i2+1) % 5) == 0)
							$str = $str."\n                         ";
					}
				}
				fwrite($out, $str);
    		}
    
    		if ($this->p_type != 0 && $pr > 0) {
				fgets(STDIN);
				if ($i1 == 0)
    				fgets(STDIN);
    		}
    	}
	/*
	     重みの出力
	*/
		if (($this->p_type < -1 || $this->p_type > 1) && $pr == 1) {
    
    		printf("    重み\n");
    		for ($i1 = 0; $i1 < $this->nou-$this->noiu; $i1++) {
				printf("      to%4d from   ", $i1+1);
    			$ln = -1;
    			for ($i2 = 0; $i2 < $this->nou; $i2++) {
    				if ($this->con[$i1][$i2] > 0) {
    					if ($ln <= 0) {
    						if ($ln < 0)
    							$ln = 0;
    						else
    							printf("\n                    ");
    					}
    					printf("%4d%11.3f", $i2+1, $this->w[$i1][$i2]);
    					$ln += 1;
						if ($ln == 4)
    						$ln = 0;
    				}
				}
	
				printf("\n");
    		}
    
    		printf("\n    バイアス   ");
			$ln = 0;
			for ($i1 = 0; $i1 < $this->nou-$this->noiu; $i1++) {
    			printf("%4d%11.3f", $i1+1, $this->theta[$i1]);
    			$ln += 1;
    			if ($ln == 4 && $i1 != $this->nou-$this->noiu-1) {
					$ln = 0;
					printf("\n               ");
				}
			}
    
    		if ($ln != 0)
    			printf("\n");
	
    		fgets(STDIN);
    	}
    
    	if ($this->p_type < 0 && $pr == 1) {
    
    		$str = "    重み\n";
    		for ($i1 = 0; $i1 < $this->nou-$this->noiu; $i1++) {
    			$str = $str."      to ".( $i1+1)." from   ";
    			$ln = -1;
    			for ($i2 = 0; $i2 < $this->nou; $i2++) {
    				if ($this->con[$i1][$i2] > 0) {
						if ($ln <= 0) {
    						if ($ln < 0)
    							$ln = 0;
							else
								$str = $str."\n                    ";
						}
    					$str = $str.($i2+1)." ".$this->w[$i1][$i2];
    					$ln += 1;
    					if ($ln == 4)
							$ln = 0;
					}
    			}
    			$str = $str."\n";
			}
			fwrite($out, $str);
	
			$str = "\n    バイアス   ";
			$ln = 0;
    		for ($i1 = 0; $i1 < $this->nou-$this->noiu; $i1++) {
    			$str = $str.($i1+1)." ".$this->theta[$i1];
    			$ln += 1;
				if ($ln == 4 && $i1 != $this->nou-$this->noiu-1) {
    				$ln = 0;
    				$str = $str."\n               ";
    			}
    		}
    
    		if ($ln != 0)
    			$str = $str."\n";
  			fwrite($out, $str);
  	}
    
    	if ($this->p_type < 0 && $pr > 0)
    		fclose($out);
	
    	return $No;
    }
}
	
/****************/
/* main program */
/****************/

	$max = 0;
	$no  = 1;
					// エラー
	if (count($argv) != 3)
		exit("***error   入力データファイル名を指定して下さい\n");

   	else {
					// ネットワークの定義
  		$net = new Backpr($argv[1], $argv[2]);
   					// 学習パターン等の入力
   		printf("学習回数は? ");
   		fscanf(STDIN, "%d", $m_tri);   // 最大学習回数
   		printf("何回毎に収束を確認しますか? ");
   		fscanf(STDIN, "%d", $conv);   // 収束確認回数

   		printf("学習パターンのファイル名は? ");
   		fscanf(STDIN, "%s", $f_name);

   		$dt1 = new BackData($f_name);
					// 学習
   		while ($max < $m_tri && $no > 0) {

			$tri  = (($max + $conv) < $m_tri) ? $conv : $m_tri - $max;
			$max += $tri;

   			$net->Learn($dt1, $tri);   // 学習

   			$no = $net->Recog($dt1, 0, $max);   // 学習対象の認識

			printf("   回数 %d 誤って認識したパターン数 %d\n", $max, $no);
   		}

   		$no = $net->Recog($dt1, 1, $max);   // 学習対象の認識と出力
					// 未学習パターンの認識
		printf("未学習パターンの認識を行いますか?(=1:行う,=0:行わない) ");
		fscanf(STDIN, "%d", $sw);

   		if ($sw > 0) {
    
   			printf("未学習パターンのファイル名は? ");
			fscanf(STDIN, "%s", $f_name);

			$dt2 = new BackData($f_name);

			$no = $net->Recog($dt2, 2, $max);   // 未学習対象の認識と出力
		}
	}

/*
------------------------制御データ----------------
誤差 0.1 出力 -2 出力ファイル kekka
順番 0 η 0.5 α 0.8

------------------------構造データ----------------
入力ユニット数 2 出力ユニット数 1 関数タイプ 0
隠れ層の数 1 各隠れ層のユニット数(下から) 1
バイアス入力ユニット数 1
 ユニット番号:出力ユニットから順に番号付け
 入力方法:=-3:固定,=-2:入力後学習,=-1:乱数(default,[-0.1,0.1]))
 値:バイアス値(ー2またはー3の時)または一様乱数の範囲(下限,上限)
1 -1 -0.05 0.05
接続方法の数 2
 ユニット番号:ユニットk1からk2を,k3からk4に接続
 接続方法:=0:接続なし,=1:乱数,=2:重み入力後学習,=3:重み固定
 値:重み(2または3の時)または一様乱数の範囲(1の時:下限,上限)
3 4 1 2 1 -0.1 0.1
2 2 1 1 1 -0.1 0.1

------------------------学習データ----------------
パターンの数 4 入力ユニット数 2 出力ユニット数 1
入力1 0 0
 出力1 0
入力2 0 1
 出力2 1
入力3 1 0
 出力3 1
入力4 1 1
 出力4 0

------------------------認識データ----------------
パターンの数 4 入力ユニット数 2 出力ユニット数 1
入力1 0 0
 出力1 0
入力2 0 1
 出力2 1
入力3 1 0
 出力3 1
入力4 1 1
 出力4 0
*/

?>