静岡理工科大学 菅沼ホーム 目次 索引

バックプロパゲーション

    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

  プログラム(使用方法)は,任意の構造のネットワークをバックプロパゲーション法によって学習するためのものです.なお,このプログラムでは,クラスを使用しています.

  1. C++

      C++11 においては,「メルセンヌ・ツイスター法による擬似乱数生成エンジン」を使用することができます.
    /****************************/
    /* back propagation model   */
    /*      coded by Y.Suganuma */
    /****************************/
    #include 
    #include 
    #include 
    #include 
    #include "MT.h"
    
    /******************************************************/
    /* バックプロパゲーションの制御(クラス BackControl) */
    /******************************************************/
    class BackControl {
    	protected:
    		double alpha, eata;   //重み及びバイアス修正パラメータ
    		double eps;   // 許容誤差
    		unsigned long seed;   // 乱数の初期値;
    		int order;   // 入力パターンの与え方(=0:順番,=1:ランダム)
    		int p_type;   // 出力先・方法の指定
                          //   =0 : 誤って認識した数だけ出力
                          //   =1 : 認識結果を出力
                          //   =2 : 認識結果と重みを出力
                          //        (負の時は,認識結果と重みをファイルへも出力)
    		char o_file[100];   // 出力ファイル名
    	public:
    		BackControl(char *);   // コンストラクタ
    };
    
    /*****************************************************/
    /* バックプロパゲーションのデータ(クラス BackData) */
    /*****************************************************/
    class BackData {
    		int noiu;   // 入力ユニットの数
    		int noou;   // 出力ユニットの数
    		int noip;   // 入力パターンの数
    		double **iptn;   // iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
                             //              入力ユニットの入力値
                             //                i=0,noip-1  j=0,noiu-1
    		double **optn;   // optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
                             //              番目の出力ユニットの目標出力値
                             //                i=0,noip-1  j=0,noou-1
    	public:
    		BackData(char *);   // コンストラクタ
    		~BackData();   // デストラクタ
    	friend class Backpr;
    };
    
    /*******************************************/
    /* バックプロパゲーション(クラス Backpr) */
    /*******************************************/
    class Backpr : BackControl {
    		char **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
    		int f_type;   // シグモイド関数のタイプ
                          //   0 : [0,1]
                          //   1 : [-1,1])
    		int noiu;   // 入力ユニットの数
    		int noou;   // 出力ユニットの数
    		int *nohu;   // nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
                         //           には下から順に番号が付けられ,出力層はレ
                         //           ベル(nolvl+1)の隠れ層とも見做される)
                         //             i=0,nolvl
    		int nolvl;   // 隠れユニットの階層数
    		int nou;   // 入力,出力,及び,隠れ層の各ユニットの数の和(各ユニ
                       // ットには最も上の出力ユニットから,隠れ層の各ユニット,
                       // 及び,入力ユニットに至る一連のユニット番号が付けられ
                       // る)
    		double *dp;   // dp[i] : ユニット(i+1)の誤差  i=0,nou-1
    		double *op;   // op[i] : ユニット(i+1)の出力  i=0,nou-1
    		double *theta;   //theta[i] : ユニット(i+1)のバイアス  i=0,nou
    		double **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
    	public:
    		Backpr(char *, char *);   // コンストラクタ
    		~Backpr();   // デストラクタ
    		void Err_back(double *);   // 重みの修正
    		void Forward();   // 誤差の計算
    		void Learn(BackData &, int);   // 学習
    		int Recog(BackData &, int, int);   // 認識と学習
    };
    
    /*************************************/
    /* クラスBackControlのコンストラクタ */
    /*      name : 入力データファイル名  */
    /*************************************/
    BackControl::BackControl(char *name)
    {
    	FILE *in;
    
    	in = fopen(name, "r");
    
    	fscanf(in, "%*s %lf %*s %d", &eps, &p_type);
    	if (p_type < 0)
    		fscanf(in, "%*s %s", o_file);
    	fscanf(in, "%*s %d %*s %lf %*s %lf", &order, &eata, &alpha);
    
    	fclose(in);
    	seed = (unsigned long)time(NULL);
    }
    
    /************************************/
    /* クラスBackDataのコンストラクタ   */
    /*      name : 入力データファイル名 */
    /************************************/
    BackData::BackData(char *name)
    {
    	int i1, i2;
    	FILE *in;
    
    	in = fopen(name, "r");
    /*
        入力パターン数等
    */
    	fscanf(in, "%*s %d %*s %d %*s %d", &noip, &noiu, &noou);
    /*
         領域の確保
    */
    	iptn = new double * [noip];
    	for (i1 = 0; i1 < noip; i1++)
    		iptn[i1] = new double [noiu];
    
    	optn = new double * [noip];
    	for (i1 = 0; i1 < noip; i1++)
    		optn[i1] = new double [noou];
    /*
         入力パターン及び各入力パターンに対する出力パターンの入力
    */
    	for (i1 = 0; i1 < noip; i1++) {
    		fscanf(in, "%*s");
    		for (i2 = 0; i2 < noiu; i2++)
    			fscanf(in, "%lf", &(iptn[i1][i2]));
    		fscanf(in, "%*s");
    		for (i2 = 0; i2 < noou; i2++)
    			fscanf(in, "%lf", &(optn[i1][i2]));
    	}
    
    	fclose(in);
    }
    
    /**************************/
    /* BackDataのデストラクタ */
    /**************************/
    BackData::~BackData()
    {
    	int i1;
    
    	for (i1 = 0; i1 < noip; i1++)
    		delete [] iptn[i1];
    	delete [] iptn;
    
    	for (i1 = 0; i1 < noip; i1++)
    		delete [] optn[i1];
    	delete [] optn;
    }
    
    /************************************************/
    /* クラスBackprのコンストラクタ                 */
    /*      name_c : 制御データ用入力ファイル名     */
    /*      name_s : ネットワーク記述入力ファイル名 */
    /************************************************/
    Backpr::Backpr(char *name_c, char *name_s) : BackControl(name_c)
    {
    	double x1, x2;
    	int i0, i1, i2, id, k, k1, k2, k3, k4, l1, l2, n, sw;
    	FILE *in;
    
    	in = fopen(name_s, "r");
    /*
         乱数の初期化
    */
    	init_genrand(seed);
    /*
         入力ユニット,出力ユニットの数,関数タイプ
    */
    	fscanf(in, "%*s %d %*s %d %*s %d", &noiu, &noou, &f_type);
    	nou = noiu + noou;   // 入力ユニットと出力ユニットの和
    /*
         隠れユニットの階層数と各階層のユニット数
    */
    	fscanf(in, "%*s %d", &nolvl);
    
    	nohu        = new int [nolvl+1];
    	nohu[nolvl] = noou;   // 出力ユニットの数
    
    	if (nolvl > 0) {
    		fscanf(in, "%*s");
    		for (i1 = 0; i1 < nolvl; i1++) {
    			fscanf(in, "%d", &(nohu[i1]));
    			nou += nohu[i1];
    		}
    	}
    /*
         領域の確保
    */
    	con = new char * [nou];
    	for (i1 = 0; i1 < nou; i1++) {
    		con[i1] = new char [nou];
    		for (i2 = 0; i2 < nou; i2++)
    			con[i1][i2] =  (i1 == i2) ? -1 : 0;
    	}
    
    	w = new double * [nou];
    	for (i1 = 0; i1 < nou; i1++) {
    		w[i1]     = new double [nou];
    		for (i2 = 0; i2 < nou; i2++)
    			w[i1][i2] = 0.0;
    	}
    
    	dp    = new double [nou];
    	op    = new double [nou];
    	theta = new double [nou];
    
    	for (i1 = 0; i1 < nou; i1++)
    		theta[i1] = 0.2 * genrand_real3() - 0.1;
    /*
         各ユニットのバイアスとユニット間の接続関係
    */
    					// バイアス
    						// バイアスデータの数
    	fscanf(in, "%*s %d", &n);
    	fscanf(in, "%*s %*s %*s");
    
    	if (n > 0) {
    						// バイアスデータの処理
    		for (i0 = 0; i0 < n; i0++) {
    							// ユニット番号
    			fscanf(in, "%d", &k1);
    							// 不適当なユニット番号のチェック
    			if (k1 < 1 || k1 > (nou-noiu)) {
    				printf("***error  ユニット番号 %d が不適当\n", k1);
    				exit(1);
    			}
    							// バイアスの与え方
    			k1--;
    			fscanf(in, "%d", &id);
    			con[k1][k1] = id;
    							// バイアスの初期設定
    			switch (con[k1][k1]) {
    				case -1:
    					fscanf(in, "%lf %lf", &x1, &x2);
    					theta[k1] = (x2 - x1) * genrand_real3() + x1;
    					break;
    				case -2:
    					fscanf(in, "%lf", &(theta[k1]));
    					break;
    				case -3:
    					fscanf(in, "%lf", &(theta[k1]));
    					break;
    				default:
    					printf("***error  バイアスの与え方が不適当\n");
    					exit(1);
    			}
    		}
    	}
    					// 接続方法
    						// 接続データの数
    	fscanf(in, "%*s %d", &n);
    	fscanf(in, "%*s %*s %*s");
    
    	if (n > 0) {
    						// 接続データの処理
    		for (i0 = 0; i0 < n; i0++) {
    							// 接続情報
    			fscanf(in, "%d %d %d %d", &k1, &k2, &k3, &k4);
    							// 不適切な接続のチェック
    			sw = 0;
    			if (k1 < 1 || k2 < 1 || k3 < 1 || k4 < 1)
    				sw = 1;
    			else {
    				if (k1 > nou || k2 > nou || k3 > nou || k4 > nou)
    					sw = 1;
    				else {
    					if (k1 > k2 || k3 > k4)
    						sw = 1;
    					else {
    						if (k4 >= k1)
    							sw = 1;
    						else {
    							l1 = -1;
    							k  = 0;
    							for (i1 = nolvl; i1 >= 0 && l1 < 0; i1--) {
    								k += nohu[i1];
    								if (k1 <= k)
    									l1 = i1;
    							}
    							l2 = -1;
    							k  = 0;
    							for (i1 = nolvl; i1 >= 0 && l2 < 0; i1--) {
    								k += nohu[i1];
    								if (k4 <= k)
    									l2 = i1;
    							}
    							if (l2 <= l1)
    								sw = 1;
    						}
    					}
    				}
    			}
    
    			if (sw > 0) {
    				printf("***error  ユニット番号が不適当(%d %d %d %d)\n",
                           k1, k2, k3, k4);
    				exit(1);
    			}
    							// 重みの初期値の与え方
    			k1--;
    			k2--;
    			k3--;
    			k4--;
    
    			fscanf(in, "%d", &id);
    
    			if (id == 1)
    				fscanf(in, "%lf %lf", &x1, &x2);
    			else {
    				if (id > 1)
    					fscanf(in, "%lf", &x1);
    				else {
    					if (id != 0) {
    						printf("***error  接続方法が不適当\n");
    						exit(1);
    					}
    				}
    			}
    							// 重みの初期値の設定
    			for (i1 = k3; i1 <= k4; i1++) {
    				for (i2 = k1; i2 <= k2; i2++) {
    					con[i1][i2] = id;
    					switch (id) {
    						case 0:
    							w[i1][i2] = 0.0;
    							break;
    						case 1:
    							w[i1][i2] = (x2 - x1) * genrand_real3() + x1;
    							break;
    						case 2:
    							w[i1][i2] = x1;
    							break;
    						case 3:
    							w[i1][i2] = x1;
    							break;
    					}
    				}
    			}
    		}
    	}
    
    	fclose(in);
    }
    
    /************************/
    /* Backprのデストラクタ */
    /************************/
    Backpr::~Backpr()
    {
    	int i1;
    
    	for (i1 = 0; i1 < nou; i1++)
    		delete [] con[i1];
    	delete [] con;
    
    	for (i1 = 0; i1 < nou; i1++)
    		delete [] w[i1];
    	delete [] w;
    
    	delete [] nohu;
    	delete [] dp;
    	delete [] op;
    	delete [] theta;
    }
    
    /******************************************/
    /* 誤差の計算,及び,重みとバイアスの修正 */
    /*      ptn[i1] : 出力パターン            */
    /******************************************/
    void Backpr::Err_back(double *ptn)
    {
    	double x1;
    	int i1, i2;
    
    	for (i1 = 0; i1 < nou-noiu; i1++) {
    					// 誤差の計算
    		if (i1 < noou) {
    			if (f_type == 0)
    				dp[i1] = (ptn[i1] - op[i1]) * op[i1] * (1.0 - op[i1]);
    			else
    				dp[i1] = 0.5 * (ptn[i1] - op[i1]) * 
                             (op[i1] - 1.0) * (op[i1] + 1.0);
    		}
    		else {
    			x1 = 0.0;
    			for (i2 = 0; i2 < i1; i2++) {
    				if (con[i2][i1] > 0)
    					x1 += dp[i2] * w[i2][i1];
    			}
    			if (f_type == 0)
    				dp[i1] = op[i1] * (1.0 - op[i1]) * x1;
    			else
    				dp[i1] = 0.5 * (op[i1] - 1.0) * (op[i1] + 1.0) * x1;
    		}
    					// 重みの修正
    		for (i2 = i1+1; i2 < nou; i2++) {
    			if (con[i1][i2] == 1 || con[i1][i2] == 2) {
    				x1         = eata * dp[i1] * op[i2] + alpha * w[i2][i1];
    				w[i2][i1]  = x1;
    				w[i1][i2] += x1;
    			}
    		}
    					// バイアスの修正
    		if (con[i1][i1] >= -2) {
    			x1         = eata * dp[i1] + alpha * w[i1][i1];
    			w[i1][i1]  = x1;
    			theta[i1] += x1;
    		}
    	}
    }
    
    /********************************************************/
    /* 与えられた入力パターンに対する各ユニットの出力の計算 */
    /********************************************************/
    void Backpr::Forward()
    {
    	double sum;
    	int i1, i2;
    
    	for (i1 = nou-noiu-1; i1 >= 0; i1--) {
    
    		sum = -theta[i1];
    
    		for (i2 = i1+1; i2 < nou; i2++) {
    			if (con[i1][i2] > 0)
    				sum -= w[i1][i2] * op[i2];
    		}
    
    		op[i1] = (f_type == 0) ? 1.0 / (1.0 + exp(sum)) :
                                     1.0 - 2.0 / (1.0 + exp(sum));
    	}
    }
    
    /*****************************/
    /* 学習の実行                */
    /*      p : 認識パターン     */
    /*      m_tri : 最大学習回数 */
    /*****************************/
    void Backpr::Learn(BackData &p, int m_tri)
    {
    	int i1, i2, k0 = -1, k1;
    /*
         エラーチェック
    */
    	if (noiu != p.noiu || noou != p.noou) {
    		printf("***error  入力または出力ユニットの数が違います\n");
    		exit(1);
    	}
    
    	for (i1 = 0; i1 < m_tri; i1++) {
    /*
         パターンを与える順番の決定
    */
    		if (order == 0) {       // 順番
    			k0++;
    			if (k0 >= p.noip)
    				k0 = 0;
    		}
    		else {                  // ランダム
    			k0 = (int)(genrand_real3() * p.noip);
    			if (k0 >= p.noip)
    				k0 = p.noip - 1;
    		}
    /*
         出力ユニットの結果を計算
    */
    		k1 = nou - noiu;
    		for (i2 = 0; i2 < noiu; i2++)
    			op[k1+i2] = p.iptn[k0][i2];
    
    		Forward();
    /*
         重みとバイアスの修正
    */
    		Err_back(&(p.optn[k0][0]));
    	}
    }
    
    /***********************************************/
    /* 与えられた対象の認識と出力                  */
    /*      p : 認識パターン                       */
    /*      pr : =0 : 出力を行わない               */
    /*           =1 : 出力を行う                   */
    /*           =2 : 出力を行う(未学習パターン) */
    /*      tri : 現在の学習回数                   */
    /*      return : 誤って認識したパターンの数    */
    /***********************************************/
    int Backpr::Recog(BackData &p, int pr, int tri)
    {
    	int i1, i2, k1, No = 0, ln, sw;
    	FILE *out = NULL;
    /*
         ファイルのオープン
    */
    	if (p_type < 0 && pr > 0) {
    		if (pr == 1) {
    			out = fopen(o_file, "w");
    			fprintf(out, "***学習パターン***\n\n");
    		}
    		else {
    			out = fopen(o_file, "a");
    			fprintf(out, "\n***未学習パターン***\n\n");
    		}
    	}
    /*
         各パターンに対する出力
    */
    	for (i1 = 0; i1 < p.noip; i1++) {
    					// 入力パターンの設定
    		k1 = nou - noiu;
    		for (i2 = 0; i2 < noiu; i2++)
    			op[k1+i2] = p.iptn[i1][i2];
    					// 出力の計算
    		Forward();
    					// 結果の表示
    		if (p_type != 0 && pr > 0) {
    
    			printf("入力パターン%4d    ", i1+1);
    			for (i2 = 0; i2 < noiu; i2++) {
    				printf("%5.2f", op[k1+i2]);
    				if (i2 == noiu-1)
    					printf("\n");
    				else {
    					if(((i2+1) % 10) == 0)
    						printf("\n                    ");
    				}
    			}
    
    			printf("\n    出力パターン(理想)   ");
    			for (i2 = 0; i2 < noou; i2++) {
    				printf("%10.3f", p.optn[i1][i2]);
    				if (i2 == noou-1)
    					printf("\n");
    				else {
    					if(((i2+1) % 5) == 0)
    						printf("\n                         ");
    				}
    			}
    		}
    
    		sw = 0;
    		if (p_type != 0 && pr > 0)
    			printf("                (実際)   ");
    		for (i2 = 0; i2 < noou; i2++) {
    			if (p_type != 0 && pr > 0) {
    				printf("%10.3f", op[i2]);
    				if (i2 == noou-1)
    					printf("\n");
    				else {
    					if(((i2+1) % 5) == 0)
    						printf("\n                         ");
    				}
    			}
    			if (fabs(op[i2]-p.optn[i1][i2]) > eps)
    				sw = 1;
    		}
    
    		if (sw > 0)
    			No++;
    
    		if (p_type < 0 && pr > 0) {
    
    			fprintf(out, "入力パターン%4d    ", i1+1);
    			for (i2 = 0; i2 < noiu; i2++) {
    				fprintf(out, "%5.2f", op[k1+i2]);
    				if (i2 == noiu-1)
    					fprintf(out, "\n");
    				else {
    					if(((i2+1) % 10) == 0)
    						fprintf(out, "\n                    ");
    				}
    			}
    
    			fprintf(out, "\n    出力パターン(理想)   ");
    			for (i2 = 0; i2 < noou; i2++) {
    				fprintf(out, "%10.3f", p.optn[i1][i2]);
    				if (i2 == noou-1)
    					fprintf(out, "\n");
    				else {
    					if(((i2+1) % 5) == 0)
    						fprintf(out, "\n                         ");
    				}
    			}
    
    			fprintf(out, "                (実際)   ");
    			for (i2 = 0; i2 < noou; i2++) {
    				fprintf(out, "%10.3f", op[i2]);
    				if (i2 == noou-1)
    					fprintf(out, "\n");
    				else {
    					if(((i2+1) % 5) == 0)
    						fprintf(out, "\n                         ");
    				}
    			}
    		}
    
    		if (p_type != 0 && pr > 0) {
    			getchar();
    			if (i1 == 0)
    				getchar();
    		}
    	}
    /*
         重みの出力
    */
    	if ((p_type < -1 || p_type > 1) && pr == 1) {
    
    		printf("    重み\n");
    		for (i1 = 0; i1 < nou-noiu; i1++) {
    			printf("      to%4d from   ", i1+1);
    			ln = -1;
    			for (i2 = 0; i2 < nou; i2++) {
    				if (con[i1][i2] > 0) {
    					if (ln <= 0) {
    						if (ln < 0)
    							ln = 0;
    						else
    							printf("\n                    ");
    					}
    					printf("%4d%11.3f", i2+1, w[i1][i2]);
    					ln += 1;
    					if (ln == 4)
    						ln = 0;
    				}
    			}
    
    			printf("\n");
    		}
    
    		printf("\n    バイアス   ");
    		ln = 0;
    		for (i1 = 0; i1 < nou-noiu; i1++) {
    			printf("%4d%11.3f", i1+1, theta[i1]);
    			ln += 1;
    			if (ln == 4 && i1 != nou-noiu-1) {
    				ln = 0;
    				printf("\n               ");
    			}
    		}
    
    		if (ln != 0)
    			printf("\n");
    
    		getchar();
    	}
    
    	if (p_type < 0 && pr == 1) {
    
    		fprintf(out, "    重み\n");
    		for (i1 = 0; i1 < nou-noiu; i1++) {
    			fprintf(out, "      to%4d from   ", i1+1);
    			ln = -1;
    			for (i2 = 0; i2 < nou; i2++) {
    				if (con[i1][i2] > 0) {
    					if (ln <= 0) {
    						if (ln < 0)
    							ln = 0;
    						else
    							fprintf(out, "\n                    ");
    					}
    					fprintf(out, "%4d%11.3f", i2+1, w[i1][i2]);
    					ln += 1;
    					if (ln == 4)
    						ln = 0;
    				}
    			}
    
    			fprintf(out, "\n");
    		}
    
    		fprintf(out, "\n    バイアス   ");
    		ln = 0;
    		for (i1 = 0; i1 < nou-noiu; i1++) {
    			fprintf(out, "%4d%11.3f", i1+1, theta[i1]);
    			ln += 1;
    			if (ln == 4 && i1 != nou-noiu-1) {
    				ln = 0;
    				fprintf(out, "\n               ");
    			}
    		}
    
    		if (ln != 0)
    			fprintf(out, "\n");
    	}
    
    	if (p_type < 0 && pr > 0)
    		fclose(out);
    
    	return No;
    }
    
    /****************/
    /* main program */
    /****************/
    int main(int argc, char *argv[])
    {
    	int conv;   // 収束確認回数
    	int m_tri;   // 最大学習回数
    	int max = 0, no = 1, sw, tri;
    	char f_name[100];
    					// エラー
    	if (argc != 3) {
    		printf("***error   入力データファイル名を指定して下さい\n");
    		exit(1);
    	}
    
    	else {
    					// ネットワークの定義
    		Backpr net(argv[1], argv[2]);
    					// 学習パターン等の入力
    		printf("学習回数は? ");
    		scanf("%d", &m_tri);
    		printf("何回毎に収束を確認しますか? ");
    		scanf("%d", &conv);
    
    		printf("学習パターンのファイル名は? ");
    		scanf("%s", f_name);
    
    		BackData dt1(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:行わない) ");
    		scanf("%d", &sw);
    
    		if (sw > 0) {
    
    			printf("未学習パターンのファイル名は? ");
    			scanf("%s", f_name);
    
    			BackData dt2(f_name);
    
    			no = net.Recog(dt2, 2, max);   // 未学習対象の認識と出力
    		}
    	}
    
    	return 0;
    }
    
    /*
    ------------------------制御データ----------------
    誤差 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
    
    //---------------------MT.h---------------------------
    //   A C-program for MT19937, with initialization improved 2002/1/26.
    //   Coded by Takuji Nishimura and Makoto Matsumoto.
    //
    //   Before using, initialize the state by using init_genrand(seed)  
    //   or init_by_array(init_key, key_length).
    //
    //   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
    //   All rights reserved.                          
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //     1. Redistributions of source code must retain the above copyright
    //        notice, this list of conditions and the following disclaimer.
    //
    //     2. Redistributions in binary form must reproduce the above copyright
    //        notice, this list of conditions and the following disclaimer in the
    //        documentation and/or other materials provided with the distribution.
    //
    //     3. The names of its contributors may not be used to endorse or promote 
    //        products derived from this software without specific prior written 
    //        permission.
    //
    //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    //   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    //   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    //   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    //   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    //   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    //   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    //   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    //   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    //
    //   Any feedback is very welcome.
    //   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
    //   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
    
    
    //   The original version of http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c was modified by Takahiro Omi as
    //   - delete line 47 "#include"
    //   - delete line 174 int main(void){...}
    //   - change N -> MT_N
    //   - change N -> MT_N
    //   - change the file name "mt19937ar.c" -> "MT.h"
    
    
    // Period parameters
    #define MT_N 624
    #define MT_M 397
    #define MATRIX_A 0x9908b0dfUL   // constant vector a
    #define UPPER_MASK 0x80000000UL // most significant w-r bits
    #define LOWER_MASK 0x7fffffffUL // least significant r bits
    
    static unsigned long mt[MT_N]; // the array for the state vector
    static int mti=MT_N+1; // mti==MT_N+1 means mt[MT_N] is not initialized
    
    // initializes mt[MT_N] with a seed
    void init_genrand(unsigned long s)
    {
        mt[0]= s & 0xffffffffUL;
        for (mti=1; mti> 30)) + mti); 
            // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
            // In the previous versions, MSBs of the seed affect
            // only MSBs of the array mt[].
            // 2002/01/09 modified by Makoto Matsumoto
            mt[mti] &= 0xffffffffUL;
            // for >32 bit machines
        }
    }
    
    // initialize by an array with array-length
    // init_key is the array for initializing keys
    // key_length is its length
    // slight change for C++, 2004/2/26
    void init_by_array(unsigned long init_key[], int key_length)
    {
        int i, j, k;
        init_genrand(19650218UL);
        i=1; j=0;
        k = (MT_N>key_length ? MT_N : key_length);
        for (; k; k--) {
            mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
              + init_key[j] + j; // non linear
            mt[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines
            i++; j++;
            if (i>=MT_N) { mt[0] = mt[MT_N-1]; i=1; }
            if (j>=key_length) j=0;
        }
        for (k=MT_N-1; k; k--) {
            mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
              - i; // non linear
            mt[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines
            i++;
            if (i>=MT_N) { mt[0] = mt[MT_N-1]; i=1; }
        }
    
        mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
    }
    
    // generates a random number on [0,0xffffffff]-interval
    unsigned long genrand_int32(void)
    {
        unsigned long y;
        static unsigned long mag01[2]={0x0UL, MATRIX_A};
        // mag01[x] = x * MATRIX_A  for x=0,1
    
        if (mti >= MT_N) { // generate N words at one time
            int kk;
    
            if (mti == MT_N+1)   // if init_genrand() has not been called,
                init_genrand(5489UL); // a default initial seed is used
    
            for (kk=0;kk> 1) ^ mag01[y & 0x1UL];
            }
            for (;kk> 1) ^ mag01[y & 0x1UL];
            }
            y = (mt[MT_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
            mt[MT_N-1] = mt[MT_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
    
            mti = 0;
        }
      
        y = mt[mti++];
    
        // Tempering
        y ^= (y >> 11);
        y ^= (y << 7) & 0x9d2c5680UL;
        y ^= (y << 15) & 0xefc60000UL;
        y ^= (y >> 18);
    
        return y;
    }
    
    // generates a random number on [0,0x7fffffff]-interval
    long genrand_int31(void)
    {
        return (long)(genrand_int32()>>1);
    }
    
    // generates a random number on [0,1]-real-interval
    double genrand_real1(void)
    {
        return genrand_int32()*(1.0/4294967295.0); 
        // divided by 2^32-1
    }
    
    // generates a random number on [0,1)-real-interval
    double genrand_real2(void)
    {
        return genrand_int32()*(1.0/4294967296.0); 
        // divided by 2^32
    }
    
    // generates a random number on (0,1)-real-interval
    double genrand_real3(void)
    {
        return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 
        // divided by 2^32
    }
    
    // generates a random number on [0,1) with 53-bit resolution
    double genrand_res53(void) 
    { 
        unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
        return(a*67108864.0+b)*(1.0/9007199254740992.0); 
    } 
    // These real versions are due to Isaku Wada, 2002/01/09 added
    */
    			

  2. Java

      このプログラムでは,ネットワークの接続状況を図示することが可能です.
    /****************************/
    /* back propagation model   */
    /*      coded by Y.Suganuma */
    /****************************/
    import java.io.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Random;
    import java.util.StringTokenizer;
    
    class Test {
    	/****************/
    	/* main program */
    	/****************/
    	public static void main(String args[]) throws IOException, FileNotFoundException
    	{
    		int conv;   // 収束確認回数
    		int m_tri;   // 最大学習回数
    		int max = 0, no = 1, sw, tri;
    		String f_name;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    					// エラー
    		if (args.length != 2) {
    			System.out.print("***error   入力データファイル名を指定して下さい\n");
    			System.exit(1);
    		}
    
    		else {
    					// ネットワークの定義
    			Backpr net = new Backpr (args[0], args[1]);
    					// 学習パターン等の入力
    			System.out.print("学習回数は? ");
    			m_tri = Integer.parseInt(in.readLine());
    			System.out.print("何回毎に収束を確認しますか? ");
    			conv = Integer.parseInt(in.readLine());
    
    			System.out.print("学習パターンのファイル名は? ");
    			f_name = in.readLine();
    
    			BackData 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);   // 学習対象の認識
    
    				System.out.println("   回数 " + max + " 誤って認識したパターン数 " + no);
    			}
    
    			no = net.Recog(dt1, 1, max);   // 学習対象の認識と出力
    					// 未学習パターンの認識
    			System.out.print("未学習パターンの認識を行いますか?(=1:行う,=0:行わない) ");
    			sw = Integer.parseInt(in.readLine());
    
    			if (sw > 0) {
    
    				System.out.print("未学習パターンのファイル名は? ");
    				f_name = in.readLine();
    
    				BackData dt2 = new BackData(f_name);
    
    				no = net.Recog(dt2, 2, max);   // 未学習対象の認識と出力
    			}
    		}
    
    		in.close();
    	}
    }
    
    /******************************************************/
    /* バックプロパゲーションの制御(クラス BackControl) */
    /******************************************************/
    class BackControl {
    	protected double alpha, eata;   //重み及びバイアス修正パラメータ
    	protected double eps;   // 許容誤差
    	protected int order;   // 入力パターンの与え方(=0:順番,=1:ランダム)
    	protected int p_type;   // 出力先・方法の指定
                                //   =0 : 誤って認識した数だけ出力
                                //   =1 : 認識結果を出力
                                //   =2 : 認識結果と重みを出力
                                //        (負の時は,認識結果と重みをファイルへも出力)
    	protected int c_size;   // 円の大きさ(直径,0のときは画面を表示しない)
    	protected int f_size;   // フォントサイズ(0のときはユニット番号を表示しない)
    	protected int width;   // 画面の幅
    	protected int hight;   // 画面の高さ
    	protected String o_file;   // 出力ファイル名
    
    	/*************************************/
    	/* クラスBackControlのコンストラクタ */
    	/*      name : 入力データファイル名  */
    	/*************************************/
    	BackControl(String name) throws IOException, FileNotFoundException
    	{
    		StringTokenizer str;
    
    		BufferedReader in = new BufferedReader(new FileReader(name));
    
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		eps = Double.parseDouble(str.nextToken());
    		str.nextToken();
    		p_type = Integer.parseInt(str.nextToken());
    		if (p_type < 0) {
    			str.nextToken();
    			o_file = str.nextToken();
    		}
    
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		order = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		eata = Double.parseDouble(str.nextToken());
    		str.nextToken();
    		alpha = Double.parseDouble(str.nextToken());
    
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		c_size = Integer.parseInt(str.nextToken());
    		if (c_size > 0) {
    			f_size = Integer.parseInt(str.nextToken());
    			width  = Integer.parseInt(str.nextToken());
    			hight  = Integer.parseInt(str.nextToken());
    		}
    
    		in.close();
    	}
    }
    
    /*****************************************************/
    /* バックプロパゲーションのデータ(クラス BackData) */
    /*****************************************************/
    class BackData {
    	int noiu;   // 入力ユニットの数
    	int noou;   // 出力ユニットの数
    	int noip;   // 入力パターンの数
    	double iptn[][];   // iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
                           //              入力ユニットの入力値
                           //                i=0,noip-1  j=0,noiu-1
    	double optn[][];   // optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
                           //              番目の出力ユニットの目標出力値
                           //                i=0,noip-1  j=0,noou-1
    
    	/************************************/
    	/* クラスBackDataのコンストラクタ   */
    	/*      name : 入力データファイル名 */
    	/************************************/
    	BackData(String name) throws IOException, FileNotFoundException
    	{
    		int i1, i2;
    		StringTokenizer str;
    
    		BufferedReader in = new BufferedReader(new FileReader(name));
    	/*
    	    入力パターン数等
    	*/
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		noip = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		noiu = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		noou = Integer.parseInt(str.nextToken());
    	/*
    	     領域の確保
    	*/
    		iptn = new double [noip][noiu];
    		optn = new double [noip][noou];
    	/*
    	     入力パターン及び各入力パターンに対する出力パターンの入力
    	*/
    		for (i1 = 0; i1 < noip; i1++) {
    			str = new StringTokenizer(in.readLine(), " ");
    			str.nextToken();
    			for (i2 = 0; i2 < noiu; i2++)
    				iptn[i1][i2] = Double.parseDouble(str.nextToken());
    			str = new StringTokenizer(in.readLine(), " ");
    			str.nextToken();
    			for (i2 = 0; i2 < noou; i2++)
    				optn[i1][i2] = Double.parseDouble(str.nextToken());
    		}
    
    		in.close();
    	}
    }
    
    /*******************************************/
    /* バックプロパゲーション(クラス Backpr) */
    /*******************************************/
    class Backpr extends BackControl {
    	private byte 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
    	private int f_type;   // シグモイド関数のタイプ
                              //   0 : [0,1]
                              //   1 : [-1,1])
    	private int noiu;   // 入力ユニットの数
    	private int noou;   // 出力ユニットの数
    	private int nohu[];   // nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
                              //           には下から順に番号が付けられ,出力層はレ
                              //           ベル(nolvl+1)の隠れ層とも見做される)
                              //             i=0,nolvl
    	private int nolvl;   // 隠れユニットの階層数
    	private int nou;   // 入力,出力,及び,隠れ層の各ユニットの数の和(各ユニ
                           // ットには最も上の出力ユニットから,隠れ層の各ユニット,
                           // 及び,入力ユニットに至る一連のユニット番号が付けられ
                           // る)
    	private double dp[];   // dp[i] : ユニット(i+1)の誤差  i=0,nou-1
    	private double op[];   // op[i] : ユニット(i+1)の出力  i=0,nou-1
    	private double theta[];   //theta[i] : ユニット(i+1)のバイアス  i=0,nou
    	private double 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
    	private Random rn;   // 乱数
    
    	/************************************************/
    	/* クラスBackprのコンストラクタ                 */
    	/*      name_c : 制御データ用入力ファイル名     */
    	/*      name_s : ネットワーク記述入力ファイル名 */
    	/************************************************/
    	Backpr(String name_c, String name_s) throws IOException, FileNotFoundException
    	{
    		super(name_c);
    
    		double x1, x2;
    		int i0, i1, i2, id, k, k1, k2, k3, k4, l1, l2, n, sw;
    		StringTokenizer str;
    
    		BufferedReader in = new BufferedReader(new FileReader(name_s));
    	/*
    	     乱数の初期化
    	*/
    		rn  = new Random();   // 乱数の初期設定
    	/*
    	     入力ユニット,出力ユニットの数,関数タイプ
    	*/
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		noiu = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		noou = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		f_type = Integer.parseInt(str.nextToken());
    		nou = noiu + noou;   // 入力ユニットと出力ユニットの和
    	/*
    	     隠れユニットの階層数と各階層のユニット数
    	*/
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		nolvl = Integer.parseInt(str.nextToken());
    
    		nohu        = new int [nolvl+1];
    		nohu[nolvl] = noou;   // 出力ユニットの数
    
    		if (nolvl > 0) {
    			str.nextToken();
    			for (i1 = 0; i1 < nolvl; i1++) {
    				nohu[i1]  = Integer.parseInt(str.nextToken());
    				nou      += nohu[i1];
    			}
    		}
    	/*
    	     領域の確保
    	*/
    		con = new byte [nou][nou];
    		for (i1 = 0; i1 < nou; i1++) {
    			for (i2 = 0; i2 < nou; i2++)
    				con[i1][i2] =  (i1 == i2) ? (byte)-1 : (byte)0;
    		}
    
    		w = new double [nou][nou];
    		for (i1 = 0; i1 < nou; i1++) {
    			for (i2 = 0; i2 < nou; i2++)
    				w[i1][i2] = 0.0;
    		}
    
    		dp    = new double [nou];
    		op    = new double [nou];
    		theta = new double [nou];
    
    		for (i1 = 0; i1 < nou; i1++)
    			theta[i1] = 0.2 * rn.nextDouble() - 0.1;
    	/*
    	     各ユニットのバイアスとユニット間の接続関係
    	*/
    					// バイアス
    						// バイアスデータの数
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		n = Integer.parseInt(str.nextToken());
    		in.readLine();
    		in.readLine();
    		in.readLine();
    
    		if (n > 0) {
    						// バイアスデータの処理
    			for (i0 = 0; i0 < n; i0++) {
    							// ユニット番号
    				str = new StringTokenizer(in.readLine(), " ");
    				k1 = Integer.parseInt(str.nextToken());
    							// 不適当なユニット番号のチェック
    				if (k1 < 1 || k1 > (nou-noiu)) {
    					System.out.print("***error  ユニット番号 " + k1 + " が不適当\n");
    					System.exit(1);
    				}
    							// バイアスの与え方
    				k1--;
    				id = Integer.parseInt(str.nextToken());
    				con[k1][k1] = (byte)id;
    							// バイアスの初期設定
    				switch (con[k1][k1]) {
    					case -1:
    						x1 = Double.parseDouble(str.nextToken());
    						x2 = Double.parseDouble(str.nextToken());
    						theta[k1] = (x2 - x1) * rn.nextDouble() + x1;
    						break;
    					case -2:
    						theta[k1] = Double.parseDouble(str.nextToken());
    						break;
    					case -3:
    						theta[k1] = Double.parseDouble(str.nextToken());
    						break;
    					default:
    						System.out.print("***error  バイアスの与え方が不適当\n");
    						System.exit(1);
    				}
    			}
    		}
    					// 接続方法
    						// 接続データの数
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		n = Integer.parseInt(str.nextToken());
    		in.readLine();
    		in.readLine();
    		in.readLine();
    
    		if (n > 0) {
    						// 接続データの処理
    			for (i0 = 0; i0 < n; i0++) {
    							// 接続情報
    				str = new StringTokenizer(in.readLine(), " ");
    				k1 = Integer.parseInt(str.nextToken());
    				k2 = Integer.parseInt(str.nextToken());
    				k3 = Integer.parseInt(str.nextToken());
    				k4 = Integer.parseInt(str.nextToken());
    							// 不適切な接続のチェック
    				sw = 0;
    				if (k1 < 1 || k2 < 1 || k3 < 1 || k4 < 1)
    					sw = 1;
    				else {
    					if (k1 > nou || k2 > nou || k3 > nou || k4 > nou)
    						sw = 1;
    					else {
    						if (k1 > k2 || k3 > k4)
    							sw = 1;
    						else {
    							if (k4 >= k1)
    								sw = 1;
    							else {
    								l1 = -1;
    								k  = 0;
    								for (i1 = nolvl; i1 >= 0 && l1 < 0; i1--) {
    									k += nohu[i1];
    									if (k1 <= k)
    										l1 = i1;
    								}
    								l2 = -1;
    								k  = 0;
    								for (i1 = nolvl; i1 >= 0 && l2 < 0; i1--) {
    									k += nohu[i1];
    									if (k4 <= k)
    										l2 = i1;
    								}
    								if (l2 <= l1)
    									sw = 1;
    							}
    						}
    					}
    				}
    
    				if (sw > 0) {
    					System.out.print("***error  ユニット番号が不適当("
                                           + k1 + " " + k2 + " " + k3 + " " + k4 + ")\n");
    					System.exit(1);
    				}
    							// 重みの初期値の与え方
    				k1--;
    				k2--;
    				k3--;
    				k4--;
    
    				id = Integer.parseInt(str.nextToken());
    				x1 = 0.0;
    				x2 = 0.0;
    
    				if (id == 1) {
    					x1 = Double.parseDouble(str.nextToken());
    					x2 = Double.parseDouble(str.nextToken());
    				}
    				else {
    					if (id > 1)
    						x1 = Double.parseDouble(str.nextToken());
    					else {
    						if (id != 0) {
    							System.out.print("***error  接続方法が不適当\n");
    							System.exit(1);
    						}
    					}
    				}
    							// 重みの初期値の設定
    				for (i1 = k3; i1 <= k4; i1++) {
    					for (i2 = k1; i2 <= k2; i2++) {
    						con[i1][i2] = (byte)id;
    						switch (id) {
    							case 0:
    								w[i1][i2] = 0.0;
    								break;
    							case 1:
    								w[i1][i2] = (x2 - x1) * rn.nextDouble() + x1;
    								break;
    							case 2:
    								w[i1][i2] = x1;
    								break;
    							case 3:
    								w[i1][i2] = x1;
    								break;
    						}
    					}
    				}
    			}
    		}
    
    		in.close();
    	/*
    	     画面表示
    	*/
    		Win win;
    		if (c_size > 0)
    			win = new Win("Network Structure", c_size, f_size, width, hight,
                              noiu, nohu, nolvl, con);
    	}
    
    	/******************************************/
    	/* 誤差の計算,及び,重みとバイアスの修正 */
    	/*      ptn[i1] : 出力パターン            */
    	/******************************************/
    	void Err_back(double ptn[])
    	{
    		double x1;
    		int i1, i2;
    
    		for (i1 = 0; i1 < nou-noiu; i1++) {
    					// 誤差の計算
    			if (i1 < noou) {
    				if (f_type == 0)
    					dp[i1] = (ptn[i1] - op[i1]) * op[i1] * (1.0 - op[i1]);
    				else
    					dp[i1] = 0.5 * (ptn[i1] - op[i1]) * 
                                 (op[i1] - 1.0) * (op[i1] + 1.0);
    			}
    			else {
    				x1 = 0.0;
    				for (i2 = 0; i2 < i1; i2++) {
    					if (con[i2][i1] > 0)
    						x1 += dp[i2] * w[i2][i1];
    				}
    				if (f_type == 0)
    					dp[i1] = op[i1] * (1.0 - op[i1]) * x1;
    				else
    					dp[i1] = 0.5 * (op[i1] - 1.0) * (op[i1] + 1.0) * x1;
    			}
    					// 重みの修正
    			for (i2 = i1+1; i2 < nou; i2++) {
    				if (con[i1][i2] == 1 || con[i1][i2] == 2) {
    					x1         = eata * dp[i1] * op[i2] + alpha * w[i2][i1];
    					w[i2][i1]  = x1;
    					w[i1][i2] += x1;
    				}
    			}
    					// バイアスの修正
    			if (con[i1][i1] >= -2) {
    				x1         = eata * dp[i1] + alpha * w[i1][i1];
    				w[i1][i1]  = x1;
    				theta[i1] += x1;
    			}
    		}
    	}
    
    	/********************************************************/
    	/* 与えられた入力パターンに対する各ユニットの出力の計算 */
    	/********************************************************/
    	void Forward()
    	{
    		double sum;
    		int i1, i2;
    
    		for (i1 = nou-noiu-1; i1 >= 0; i1--) {
    
    			sum = -theta[i1];
    
    			for (i2 = i1+1; i2 < nou; i2++) {
    				if (con[i1][i2] > 0)
    					sum -= w[i1][i2] * op[i2];
    			}
    
    			op[i1] = (f_type == 0) ? 1.0 / (1.0 + Math.exp(sum)) :
                                         1.0 - 2.0 / (1.0 + Math.exp(sum));
    		}
    	}
    
    	/*****************************/
    	/* 学習の実行                */
    	/*      p : 認識パターン     */
    	/*      m_tri : 最大学習回数 */
    	/*****************************/
    	void Learn(BackData p, int m_tri)
    	{
    		int i1, i2, k0 = -1, k1;
    	/*
    	     エラーチェック
    	*/
    		if (noiu != p.noiu || noou != p.noou) {
    			System.out.print("***error  入力または出力ユニットの数が違います\n");
    			System.exit(1);
    		}
    
    		for (i1 = 0; i1 < m_tri; i1++) {
    	/*
    	     パターンを与える順番の決定
    	*/
    			if (order == 0) {       // 順番
    				k0++;
    				if (k0 >= p.noip)
    					k0 = 0;
    			}
    			else {                  // ランダム
    				k0 = (int)(rn.nextDouble() * p.noip);
    				if (k0 >= p.noip)
    					k0 = p.noip - 1;
    			}
    	/*
    	     出力ユニットの結果を計算
    	*/
    			k1 = nou - noiu;
    			for (i2 = 0; i2 < noiu; i2++)
    				op[k1+i2] = p.iptn[k0][i2];
    
    			Forward();
    	/*
    	     重みとバイアスの修正
    	*/
    			Err_back(p.optn[k0]);
    		}
    	}
    
    	/***********************************************/
    	/* 与えられた対象の認識と出力                  */
    	/*      p : 認識パターン                       */
    	/*      pr : =0 : 出力を行わない               */
    	/*           =1 : 出力を行う                   */
    	/*           =2 : 出力を行う(未学習パターン) */
    	/*      tri : 現在の学習回数                   */
    	/*      return : 誤って認識したパターンの数    */
    	/***********************************************/
    	int Recog(BackData p, int pr, int tri) throws IOException, FileNotFoundException
    	{
    		int i1, i2, k1, No = 0, ln, sw;
    		String next;
    
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    	/*
    	     ファイルのオープン
    	*/
    		PrintStream out = null;
    		if (p_type < 0 && pr > 0) {
    			if (pr == 1) {
    				out = new PrintStream(new FileOutputStream(o_file));
    				out.print("***学習パターン***\n\n");
    			}
    			else {
    				out = new PrintStream(new FileOutputStream(o_file, true));
    				out.print("\n***未学習パターン***\n\n");
    			}
    		}
    	/*
    	     各パターンに対する出力
    	*/
    		for (i1 = 0; i1 < p.noip; i1++) {
    					// 入力パターンの設定
    			k1 = nou - noiu;
    			for (i2 = 0; i2 < noiu; i2++)
    				op[k1+i2] = p.iptn[i1][i2];
    					// 出力の計算
    			Forward();
    					// 結果の表示
    			if (p_type != 0 && pr > 0) {
    
    				System.out.print("入力パターン" + (i1+1) + "   ");
    				for (i2 = 0; i2 < noiu; i2++) {
    					System.out.print(" " + op[k1+i2]);
    					if (i2 == noiu-1)
    						System.out.print("\n");
    					else {
    						if(((i2+1) % 10) == 0)
    							System.out.print("\n                   ");
    					}
    				}
    
    				System.out.print("\n    出力パターン(理想)  ");
    				for (i2 = 0; i2 < noou; i2++) {
    					System.out.print(" " + p.optn[i1][i2]);
    					if (i2 == noou-1)
    						System.out.print("\n");
    					else {
    						if(((i2+1) % 5) == 0)
    							System.out.print("\n                        ");
    					}
    				}
    			}
    
    			sw = 0;
    			if (p_type != 0 && pr > 0)
    				System.out.print("                (実際)  ");
    			for (i2 = 0; i2 < noou; i2++) {
    				if (p_type != 0 && pr > 0) {
    					System.out.print(" " + op[i2]);
    					if (i2 == noou-1)
    						System.out.print("\n");
    					else {
    						if(((i2+1) % 5) == 0)
    							System.out.print("\n                        ");
    					}
    				}
    				if (Math.abs(op[i2]-p.optn[i1][i2]) > eps)
    					sw = 1;
    			}
    
    			if (sw > 0)
    				No++;
    
    			if (p_type < 0 && pr > 0) {
    
    				out.print("入力パターン" + (i1+1) + "   ");
    				for (i2 = 0; i2 < noiu; i2++) {
    					out.print(" " + op[k1+i2]);
    					if (i2 == noiu-1)
    						out.print("\n");
    					else {
    						if(((i2+1) % 10) == 0)
    							out.print("\n                   ");
    					}
    				}
    
    				out.print("\n    出力パターン(理想)  ");
    				for (i2 = 0; i2 < noou; i2++) {
    					out.print(" " + p.optn[i1][i2]);
    					if (i2 == noou-1)
    						out.print("\n");
    					else {
    						if(((i2+1) % 5) == 0)
    							out.print("\n                        ");
    					}
    				}
    
    				out.print("                (実際)  ");
    				for (i2 = 0; i2 < noou; i2++) {
    					out.print(" " + op[i2]);
    					if (i2 == noou-1)
    						out.print("\n");
    					else {
    						if(((i2+1) % 5) == 0)
    							out.print("\n                        ");
    					}
    				}
    			}
    
    			if (p_type != 0 && pr > 0)
    				next = in.readLine();
    		}
    	/*
    	     重みの出力
    	*/
    		if ((p_type < -1 || p_type > 1) && pr == 1) {
    
    			System.out.print("    重み\n");
    			for (i1 = 0; i1 < nou-noiu; i1++) {
    				System.out.print("      to " + (i1+1) + " from  ");
    				ln = -1;
    				for (i2 = 0; i2 < nou; i2++) {
    					if (con[i1][i2] > 0) {
    						if (ln <= 0) {
    							if (ln < 0)
    								ln = 0;
    							else
    								System.out.print("\n                   ");
    						}
    						System.out.print(" " + (i2+1) + " " + w[i1][i2]);
    						ln += 1;
    						if (ln == 4)
    							ln = 0;
    					}
    				}
    
    				System.out.print("\n");
    			}
    
    			System.out.print("\n    バイアス  ");
    			ln = 0;
    			for (i1 = 0; i1 < nou-noiu; i1++) {
    				System.out.print(" " + (i1+1) + " " + theta[i1]);
    				ln += 1;
    				if (ln == 4 && i1 != nou-noiu-1) {
    					ln = 0;
    					System.out.print("\n              ");
    				}
    			}
    
    			if (ln != 0)
    				System.out.print("\n");
    
    			next = in.readLine();
    		}
    
    		if (p_type < 0 && pr == 1) {
    
    			out.print("    重み\n");
    			for (i1 = 0; i1 < nou-noiu; i1++) {
    				out.print("      to " + (i1+1) + " from  ");
    				ln = -1;
    				for (i2 = 0; i2 < nou; i2++) {
    					if (con[i1][i2] > 0) {
    						if (ln <= 0) {
    							if (ln < 0)
    								ln = 0;
    							else
    								out.print("\n                   ");
    						}
    						out.print(" " + (i2+1) + " " + w[i1][i2]);
    						ln += 1;
    						if (ln == 4)
    							ln = 0;
    					}
    				}
    
    				out.print("\n");
    			}
    
    			out.print("\n    バイアス  ");
    			ln = 0;
    			for (i1 = 0; i1 < nou-noiu; i1++) {
    				out.print(" " + (i1+1) + " " + theta[i1]);
    				ln += 1;
    				if (ln == 4 && i1 != nou-noiu-1) {
    					ln = 0;
    					out.print("\n              ");
    				}
    			}
    
    			if (ln != 0)
    				out.print("\n");
    		}
    
    		if (p_type < 0 && pr > 0)
    			out.close();
    
    		return No;
    	}
    }
    
    /*******************/
    /* クラスWinの定義 */
    /*******************/
    class Win extends Frame {
    
    	byte con[][];   // 接続関係
    	int nohu[];   // 各層のユニット数(入力層から出力層)
    	int nolvl;   // 層の数
    	int nou;   // ユニット数
    	int c_size;   // 円の大きさ(直径)
    	int f_size;   // フォントサイズ
    	int width;   // 画面の幅
    	int height;   // 画面の高さ
    	int x[], y[];   // ユニットの位置
    
    	/**************************************************/
    	/* コンストラクタ                                 */
    	/*      name : Windowのタイトル                   */
    	/*      c_size_i : 円の大きさ(直径)             */
    	/*      f_size_i : フォントサイズ                 */
    	/*      width_i : 画面の幅                        */
    	/*      height_i : 画面の高さ                     */
    	/*      noiu_i : 入力層のユニット数               */
    	/*      nohu_i : 各層のユニット数(入力層を除く) */
    	/*      nolvl_i : 層の数(入力層を除く)          */
    	/*      con_i : 接続関係                          */
    	/**************************************************/
    	Win (String name, int c_size_i, int f_size_i, int width_i, int height_i,
             int noiu_i, int nohu_i[], int nolvl_i, byte con_i[][])
    	{
    					// Frameクラスのコンストラクタ(Windowのタイトルを引き渡す)
    		super(name);
    					// データの設定
    		int i1, i2;
    
    		c_size = c_size_i;
    		f_size = f_size_i;
    		width  = width_i;
    		height = height_i;
    
    		nou = noiu_i;
    		for (i1 = 0; i1 <= nolvl_i; i1++)
    			nou += nohu_i[i1];
    
    		nolvl = nolvl_i + 2;
    		nohu  = new int [nolvl];
    		for (i1 = 0; i1 <= nolvl_i; i1++)
    			nohu[i1+1] = nohu_i[i1];
    		nohu[0] = noiu_i;
    
    		con = new byte [nou][nou];
    		for (i1 = 0; i1 < nou; i1++) {
    			for (i2 = 0; i2 < nou; i2++)
    				con[i1][i2] = con_i[i1][i2];
    		}
    
    		x = new int [nou];
    		y = new int [nou];
    					// Windowの大きさ
    		setSize(width, height);
    					// ウィンドウを表示
    		setVisible(true);
    					// イベントアダプタ
    		addWindowListener(new WinEnd());
    	}
    
    	/********/
    	/* 描画 */
    	/********/
    	public void paint (Graphics g)
    	{
    						// 初期設定
    		int y_s = (f_size > 25) ? 25 + f_size : 50;
    		int y_e = (c_size > 20 ) ? height - c_size - 10 : height - 30;
    		int c_x, c_y = y_s;
    		int i1, i2, k = 0;
    		int x_step, y_step = (y_e - y_s) / (nolvl - 1);
    		Font f;
    						// フォントサイズ
    		if (f_size > 0) {
    			f = new Font("TimesRoman", Font.PLAIN, f_size);
    			g.setFont(f);
    		}
    						// 各ユニットを描く
    		for (i1 = nolvl-1; i1 >= 0; i1--) {
    			x_step = width / nohu[i1];
    			c_x    = x_step / 2;
    			for (i2 = 0; i2 < nohu[i1]; i2++) {
    				x[k] = c_x;
    				y[k] = c_y;
    				g.fillOval(x[k], y[k], c_size, c_size);
    				if (f_size > 0)
    					g.drawString(Integer.toString(k+1), x[k]-f_size/2, y[k]);
    				c_x += x_step;
    				k++;
    			}
    			c_y += y_step;
    		}
    						// 接続関係を描く
    		k = c_size / 2;
    		for (i1 = 0; i1 < nou-nohu[0]; i1++) {
    			for (i2 = i1+1; i2 < nou; i2++ ) {
    				if (con[i1][i2] != 0)
    					g.drawLine(x[i1]+k, y[i1]+k, x[i2]+k, y[i2]+k);
    			}
    		}
    	}
    
    	/************/
    	/* 終了処理 */
    	/************/
    	class WinEnd extends WindowAdapter
    	{
    		public void windowClosing(WindowEvent e) {
    			System.exit(0);
    		}
    	}
    }
    
    /*
    ------------------------制御データ----------------
    誤差 0.1 出力 -2 出力ファイル kekka
    順番 0 η 0.5 α 0.8
    画面表示(円の大きさ,フォントサイズ,幅,高さ) 20 20 400 300
    
    ------------------------構造データ----------------
    入力ユニット数 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
    */
    			

  3. JavaScript

      ここをクリックして表示された画面においてデータを設定し,「実行」ボタンをクリックすれば画面上で実行可能です.

    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>back propagation model</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<SCRIPT TYPE="text/javascript">
    		res = "";
    		net = null;
    		dt1 = null;
    		dt2 = null;
    		/****************/
    		/* main program */
    		/****************/
    		function main()
    		{
    			let m_tri = parseInt(document.getElementById("m_tri").value);
    					// ネットワークの定義
    			net = new Backpr();
    					// 学習パターンの入力
    			dt1 = new BackData("ptn1");
    					// 学習
    			net.Learn(dt1, m_tri);   // 学習
    			let no = net.Recog(dt1, 1, m_tri);   // 学習対象の認識
    			res += ("\n+++学習終了 回数 " + m_tri + " 誤って認識したパターン数 " + no + "\n\n");
    					// 未学習パターンの認識
    			dt2 = new BackData("ptn2");
    			no  = net.Recog(dt2, 2, m_tri);   // 未学習対象の認識と出力
    
    			document.getElementById("result").value = res;
    		}
    
    		/********************************/
    		/* BackDataオブジェクト         */
    		/*      name : テキストエリア名 */
    		/********************************/
    		function BackData(name)
    		{
    			let lines = (document.getElementById(name).value).split('\n');
    					//
    					// 入力パターン数等
    					//
    			let str   = lines[0].split(' ').filter(function(e){return e.length > 0;});
    			this.noip = parseInt(str[1]);   // 入力ユニットの数
    			this.noiu = parseInt(str[3]);   // 出力ユニットの数
    			this.noou = parseInt(str[5]);   // 入力パターンの数
    					//
    					// 領域の確保
    					//
    			this.iptn = new Array(this.noip);
                             // iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
                             //              入力ユニットの入力値
                             //                i=0,noip-1  j=0,noiu-1
    			this.optn = new Array(this.noip);
                             // optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
                             //              番目の出力ユニットの目標出力値
                             //                i=0,noip-1  j=0,noou-1
    			for (let i1 = 0; i1 < this.noip; i1++) {
    				this.iptn[i1] = new Array(this.noiu);
    				this.optn[i1] = new Array(this.noou);
    			}
    					//
    					// 入力パターン及び各入力パターンに対する出力パターンの入力
    					//
    			for (let i1 = 0; i1 < this.noip; i1++) {
    				let k = 2 * i1 + 1;
    				str   = lines[k].split(' ').filter(function(e){return e.length > 0;});
    				for (let i2 = 0; i2 < this.noiu; i2++)
    					this.iptn[i1][i2] = parseFloat(str[i2+1]);
    				str = lines[k+1].split(' ').filter(function(e){return e.length > 0;});
    				for (let i2 = 0; i2 < this.noou; i2++)
    					this.optn[i1][i2] = parseFloat(str[i2+1]);
    			}
    		}
    
    		/**********************/
    		/* Backprオブジェクト */
    		/**********************/
    		function Backpr()
    		{
    					//
    					// 制御用データ
    					//
    			let lines = (document.getElementById("data1").value).split('\n');
    						// 1 行目
    			let str     = lines[0].split(' ').filter(function(e){return e.length > 0;});
    			this.eps    = parseFloat(str[1]);   // 許容誤差
    			this.p_type = parseInt(str[3]);   // 出力先・方法の指定
                                                  //   =0 : 誤って認識した数だけ出力
                                                  //   =1 : 認識結果を出力
                                                  //   =2 : 認識結果と重みを出力
    						// 2 行目
    			str        = lines[1].split(' ').filter(function(e){return e.length > 0;});
    			this.order = parseInt(str[1]);   // 入力パターンの与え方(=0:順番,=1:ランダム)
    			this.eata  = parseFloat(str[3]);   //重み及びバイアス修正パラメータ
    			this.alpha = parseFloat(str[5]);   //重み及びバイアス修正パラメータ
    					//
    					// 入力ユニット,出力ユニットの数,関数タイプ
    					//
    			lines = (document.getElementById("data2").value).split('\n');
    
    			str         = lines[0].split(' ').filter(function(e){return e.length > 0;});
    			this.noiu   = parseInt(str[1]);   // 入力ユニットの数
    			this.noou   = parseInt(str[3]);   // 出力ユニットの数
    			this.f_type = parseInt(str[5]);   // シグモイド関数のタイプ
                                                  //   0 : [0,1]
                                                  //   1 : [-1,1])
    			this.nou    = this.noiu + this.noou;   // 入力ユニットと出力ユニットの和
    					//
    					// 隠れユニットの階層数と各階層のユニット数
    					//
    			str         = lines[1].split(' ').filter(function(e){return e.length > 0;});
    			this.nolvl  = parseInt(str[1]);   // 隠れユニットの階層数
    			this.nohu   = new Array(this.nolvl+1);
                                 // nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
                                 //           には下から順に番号が付けられ,出力層はレ
                                 //           ベル(nolvl+1)の隠れ層とも見做される)
                                 //             i=0,nolvl
    			this.nohu[this.nolvl] = this.noou;   // 出力ユニットの数
    		
    			if (this.nolvl > 0) {
    				for (let i1 = 0; i1 < this.nolvl; i1++) {
    					this.nohu[i1]  = parseInt(str[i1+3]);
    					this.nou      += this.nohu[i1];
    				}
    			}
    					//
    					// 領域の確保
    					//
    			this.con = new Array(this.nou);
                         // 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
    			for (let i1 = 0; i1 < this.nou; i1++) {
    				this.con[i1] = new Array(this.nou);
    				for (let i2 = 0; i2 < this.nou; i2++)
    					this.con[i1][i2] =  (i1 == i2) ? -1 : 0;
    			}
    		
    			this.w = new Array(this.nou);
                        // 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
    			for (let i1 = 0; i1 < this.nou; i1++) {
    				this.w[i1] = new Array(this.nou);
    				for (let i2 = 0; i2 < this.nou; i2++)
    					this.w[i1][i2] = 0.0;
    			}
    		
    			this.dp    = new Array(this.nou);   // dp[i] : ユニット(i+1)の誤差  i=0,nou-1
    			this.op    = new Array(this.nou);   // op[i] : ユニット(i+1)の出力  i=0,nou-1
    			this.theta = new Array(this.nou);   //theta[i] : ユニット(i+1)のバイアス  i=0,nou
    		
    			for (let i1 = 0; i1 < this.nou; i1++)
    				this.theta[i1] = 0.2 * Math.random() - 0.1;
    					//
    					// 各ユニットのバイアスとユニット間の接続関係
    					//
    						// バイアス
    							// バイアスデータの数
    			str    = lines[2].split(' ').filter(function(e){return e.length > 0;});
    			let nb = parseInt(str[1]);
    			if (nb > 0) {
    							// バイアスデータの処理
    				for (let i0 = 0; i0 < nb; i0++) {
    								// ユニット番号
    					str    = lines[i0+6].split(' ').filter(function(e){return e.length > 0;});
    					let k1 = parseInt(str[0]);
    								// 不適当なユニット番号のチェック
    					if (k1 < 1 || k1 > (this.nou-this.noiu))
    						alert("***error  ユニット番号 " + k1 + " が不適当");
    								// バイアスの与え方
    					k1--;
    					let id           = parseInt(str[1]);
    					this.con[k1][k1] = id;
    								// バイアスの初期設定
    					switch (this.con[k1][k1]) {
    						case -1:
    							let x1 = parseFloat(str[2]);
    							let x2 = parseFloat(str[3]);
    							this.theta[k1] = (x2 - x1) * Math.random() + x1;
    							break;
    						case -2:
    							this.theta[k1] = parseFloat(str[2]);
    							break;
    						case -3:
    							this.theta[k1] = parseFloat(str[2]);
    							break;
    						default:
    							alert("***error  バイアスの与え方が不適当");
    							break;
    					}
    				}
    			}
    						// 接続方法
    							// 接続データの数
    			str   = lines[nb+6].split(' ').filter(function(e){return e.length > 0;});
    			let n = parseInt(str[1]);
    		
    			if (n > 0) {
    							// 接続データの処理
    				for (let i0 = 0; i0 < n; i0++) {
    								// 接続情報
    					str    = lines[nb+10+i0].split(' ').filter(function(e){return e.length > 0;});
    					let k1 = parseInt(str[0]);
    					let k2 = parseInt(str[1]);
    					let k3 = parseInt(str[2]);
    					let k4 = parseInt(str[3]);
    								// 不適切な接続のチェック
    					let 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 {
    									let l1 = -1;
    									let k  = 0;
    									for (let i1 = this.nolvl; i1 >= 0 && l1 < 0; i1--) {
    										k += this.nohu[i1];
    										if (k1 <= k)
    											l1 = i1;
    									}
    									let l2 = -1;
    									k      = 0;
    									for (let 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)
    						alert("***error  ユニット番号が不適当("
                                   + k1 + " " + k2 + " " + k3 + " " + k4 + ")");
    								// 重みの初期値の与え方
    					k1--;
    					k2--;
    					k3--;
    					k4--;
    		
    					let id = parseInt(str[4]);
    					let x1 = 0.0;
    					let x2 = 0.0;
    		
    					if (id == 1) {
    						x1 = parseFloat(str[5]);
    						x2 = parseFloat(str[6]);
    					}
    					else {
    						if (id > 1)
    							x1 = parseFloat(str[5]);
    						else {
    							if (id != 0)
    								alert("***error  接続方法が不適当");
    						}
    					}
    								// 重みの初期値の設定
    					for (let i1 = k3; i1 <= k4; i1++) {
    						for (let 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) * Math.random() + x1;
    									break;
    								case 2:
    									this.w[i1][i2] = x1;
    									break;
    								case 3:
    									this.w[i1][i2] = x1;
    									break;
    							}
    						}
    					}
    				}
    			}
    		}
    
    		/******************************************/
    		/* 誤差の計算,及び,重みとバイアスの修正 */
    		/*      ptn[i1] : 出力パターン            */
    		/******************************************/
    		Backpr.prototype.Err_back = function(ptn)
    		{
    			for (let i1 = 0; i1 < net.nou-net.noiu; i1++) {
    						// 誤差の計算
    				if (i1 < net.noou) {
    					if (net.f_type == 0)
    						net.dp[i1] = (ptn[i1] - net.op[i1]) * net.op[i1] * (1.0 - net.op[i1]);
    					else
    						net.dp[i1] = 0.5 * (ptn[i1] - net.op[i1]) * (net.op[i1] - 1.0) * (net.op[i1] + 1.0);
    				}
    				else {
    					let x1 = 0.0;
    					for (let i2 = 0; i2 < i1; i2++) {
    						if (net.con[i2][i1] > 0)
    							x1 += net.dp[i2] * net.w[i2][i1];
    					}
    					if (net.f_type == 0)
    						net.dp[i1] = net.op[i1] * (1.0 - net.op[i1]) * x1;
    					else
    						net.dp[i1] = 0.5 * (net.op[i1] - 1.0) * (net.op[i1] + 1.0) * x1;
    				}
    						// 重みの修正
    				for (let i2 = i1+1; i2 < net.nou; i2++) {
    					if (net.con[i1][i2] == 1 || net.con[i1][i2] == 2) {
    						let x1  = net.eata * net.dp[i1] * net.op[i2] + net.alpha * net.w[i2][i1];
    						net.w[i2][i1]  = x1;
    						net.w[i1][i2] += x1;
    					}
    				}
    						// バイアスの修正
    				if (net.con[i1][i1] >= -2) {
    					let x1  = net.eata * net.dp[i1] + net.alpha * net.w[i1][i1];
    					net.w[i1][i1]  = x1;
    					net.theta[i1] += x1;
    				}
    			}
    		}
    
    		/********************************************************/
    		/* 与えられた入力パターンに対する各ユニットの出力の計算 */
    		/********************************************************/
    		Backpr.prototype.Forward = function()
    		{
    			for (let i1 = net.nou-net.noiu-1; i1 >= 0; i1--) {
    
    				let sum = -net.theta[i1];
    
    				for (let i2 = i1+1; i2 < net.nou; i2++) {
    					if (net.con[i1][i2] > 0)
    						sum -= net.w[i1][i2] * net.op[i2];
    				}
    
    				net.op[i1] = (net.f_type == 0) ? 1.0 / (1.0 + Math.exp(sum)) :
                                                     1.0 - 2.0 / (1.0 + Math.exp(sum));
    			}
    		}
    
    		/*****************************/
    		/* 学習の実行                */
    		/*      p : 認識パターン     */
    		/*      m_tri : 最大学習回数 */
    		/*****************************/
    		Backpr.prototype.Learn = function(p, m_tri)
    		{
    					//
    					// エラーチェック
    					//
    			if (net.noiu != p.noiu || net.noou != p.noou)
    				alert("***error  入力または出力ユニットの数が違います");
    
    			let k0 = -1;
    			for (let i1 = 0; i1 < m_tri; i1++) {
    					//
    					// パターンを与える順番の決定
    					//
    				if (net.order == 0) {       // 順番
    					k0++;
    					if (k0 >= p.noip)
    						k0 = 0;
    				}
    				else {                  // ランダム
    					k0 = Math.floor(Math.random() * p.noip);
    					if (k0 >= p.noip)
    						k0 = p.noip - 1;
    				}
    					//
    					// 出力ユニットの結果を計算
    					//
    				let k1 = net.nou - net.noiu;
    				for (let i2 = 0; i2 < net.noiu; i2++)
    					net.op[k1+i2] = p.iptn[k0][i2];
    
    				net.Forward();
    					//
    					// 重みとバイアスの修正
    					//
    				net.Err_back(p.optn[k0]);
    			}
    		}
    
    		/********************************************/
    		/* 与えられた対象の認識と出力               */
    		/*      p : 認識パターン                    */
    		/*      pr : =1 : 学習パターン              */
    		/*           =2 : 未学習パターン            */
    		/*      tri : 現在の学習回数                */
    		/*      return : 誤って認識したパターンの数 */
    		/********************************************/
    		Backpr.prototype.Recog = function(p, pr, tri)
    		{
    			if (pr == 1)
    				res = "***学習パターン***\n";
    			else
    				res += "***未学習パターン***\n";
    					//
    					// 各パターンに対する出力
    					//
    			let No = 0;
    
    			for (let i1 = 0; i1 < p.noip; i1++) {
    						// 入力パターンの設定
    				let k1 = net.nou - net.noiu;
    				for (let i2 = 0; i2 < net.noiu; i2++)
    					net.op[k1+i2] = p.iptn[i1][i2];
    						// 出力の計算
    				net.Forward();
    						// 結果の表示
    				if (net.p_type != 0 && pr > 0) {
    
    					res += ("入力パターン" + (i1+1) + "   ");
    					for (let i2 = 0; i2 < net.noiu; i2++) {
    						res += (" " + net.op[k1+i2]);
    						if (i2 == net.noiu-1)
    							res += "\n";
    						else {
    							if(((i2+1) % 10) == 0) {
    								res += "\n";
    								res += "                   ";
    							}
    						}
    					}
    
    					res += "\n";
    					res += ("    出力パターン(理想)  ");
    					for (let i2 = 0; i2 < net.noou; i2++) {
    						res += (" " + p.optn[i1][i2]);
    						if (i2 == net.noou-1)
    							res += "\n";
    						else {
    							if(((i2+1) % 5) == 0) {
    								res += "\n";
    								res += "                        ";
    							}
    						}
    					}
    				}
    
    				let sw = 0;
    				if (net.p_type != 0 && pr > 0)
    					res += ("                (実際)  ");
    				for (let i2 = 0; i2 < net.noou; i2++) {
    					if (net.p_type != 0 && pr > 0) {
    						res += (" " + net.op[i2]);
    						if (i2 == net.noou-1)
    							res += "\n";
    						else {
    							if(((i2+1) % 5) == 0) {
    								res += "\n";
    								res += "                        ";
    							}
    						}
    					}
    					if (Math.abs(net.op[i2]-p.optn[i1][i2]) > net.eps)
    						sw = 1;
    				}
    
    				if (sw > 0)
    					No++;
    			}
    					//
    					// 重みの出力
    					//
    			let ln;
    			if ((net.p_type < -1 || net.p_type > 1) && pr == 1) {
    
    				res += ("    重み");
    				for (let i1 = 0; i1 < net.nou-net.noiu; i1++) {
    					res += ("      to " + (i1+1) + " from  ");
    					ln   = -1;
    					for (let i2 = 0; i2 < net.nou; i2++) {
    						if (net.con[i1][i2] > 0) {
    							if (ln <= 0) {
    								if (ln < 0)
    									ln = 0;
    								else {
    									res += "\n";
    									res += ("                   ");
    								}
    							}
    							res += (" " + (i2+1) + " " + net.w[i1][i2]);
    							ln += 1;
    							if (ln == 4)
    								ln = 0;
    						}
    					}
    
    					res += "\n";
    				}
    
    				res += "\n";
    				res += ("    バイアス  ");
    				ln   = 0;
    				for (let i1 = 0; i1 < net.nou-net.noiu; i1++) {
    					res += (" " + (i1+1) + " " + net.theta[i1]);
    					ln  += 1;
    					if (ln == 4 && i1 != net.nou-net.noiu-1) {
    						ln = 0;
    						res += "\n";
    						res += ("              ");
    					}
    				}
    
    				if (ln != 0)
    					res += "\n";
    			}
    
    			return No;
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY STYLE="font-size: 130%; text-align:center; background-color: #eeffee;">
    
    	<H2><B>back propagation model</B></H2>
    
    	学習回数:<INPUT ID="m_tri" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="5000"> 
    	<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="return main()">実行</BUTTON><BR>
    	<DIV STYLE="width: 800px; margin-right: auto; margin-left: auto">
    		<DIV STYLE="text-align:center; float: right; width: 400px">
    			<DIV STYLE="text-align:center">構造データ</DIV>
    			<TEXTAREA ID="data2" COLS="35" ROWS="10" STYLE="font-size: 100%; width: 380px">
    入力ユニット数 2 出力ユニット数 1 関数タイプ 0
    隠れ層の数 1 各隠れ層のユニット数(下から) 1
    バイアス入力ユニット数 1
     ユニット番号:出力ユニットから順に番号付け
     入力方法:=-3:固定,=-2:入力後学習,=-1:乱数(default,[-0.1,0.1]))
     値:バイアス値(ー2またはー3の時)または一様乱数の範囲(下限,上限)
    1 -1 -0.1 0.1
    接続方法の数 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
    			</TEXTAREA>
    		</DIV>
    		<DIV STYLE="text-align:center; width: 400px">
    			<DIV STYLE="text-align:center">制御データ</DIV>
    			<TEXTAREA ID="data1" COLS="35" ROWS="10" STYLE="font-size: 100%; width: 380px">
    誤差 0.1 出力 2 出力ファイル kekka
    順番 0 η 0.5 α 0.8
    			</TEXTAREA>
    		</DIV>
    		<DIV STYLE="text-align:center; float: right; width: 400px">
    			<DIV STYLE="text-align:center">未学習パターン</DIV>
    			<TEXTAREA ID="ptn2" COLS="35" ROWS="10" STYLE="font-size: 100%; width: 380px">
    パターンの数 4 入力ユニット数 2 出力ユニット数 1
    入力1 0 0
     出力1 0
    入力2 0 1
     出力2 1
    入力3 1 0
     出力3 1
    入力4 1 1
     出力4 0
    			</TEXTAREA>
    		</DIV>
    		<DIV STYLE="text-align:center; width: 400px">
    			<DIV STYLE="text-align:center">学習パターン</DIV>
    			<TEXTAREA ID="ptn1" COLS="35" ROWS="10" STYLE="font-size: 100%; width: 380px">
    パターンの数 4 入力ユニット数 2 出力ユニット数 1
    入力1 0 0
     出力1 0
    入力2 0 1
     出力2 1
    入力3 1 0
     出力3 1
    入力4 1 1
     出力4 0
    			</TEXTAREA>
    		</DIV>
    		<DIV STYLE="text-align:center">結果</DIV>
    		<TEXTAREA ID="result" COLS="70" ROWS="10" STYLE="font-size: 100%;">
    		</TEXTAREA>
    	</DIV>
    </BODY>
    
    </HTML>
    			

  4. PHP

    <?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
    */
    
    ?>
    			

  5. Ruby

    ##########################
    # back propagation model
    #      coded by Y.Suganuma
    ##########################
    
    ######################################################
    # バックプロパゲーションの制御(クラス BackControl)
    ######################################################
    
    class BackControl
    	
    	####################################
    	# クラスBackControlのコンストラクタ
    	#      name : 入力データファイル名
    	####################################
    	
    	def initialize(name)
    	
    		f        = open(name, "r")
    		s        = f.gets().split(" ")
    		@_eps    = Float(s[1])   # 許容誤差
    		@_p_type = Integer(s[3])   # 出力先・方法の指定
    	                               #   =0 : 誤って認識した数だけ出力
    	                               #   =1 : 認識結果を出力
    	                               #   =2 : 認識結果と重みを出力
    	                               #        (負の時は,認識結果と重みをファイルへも出力)
    		if @_p_type < 0
    			@_o_file = s[5]   # 出力ファイル名
    		end
    		s       = f.gets().split(" ")
    		@_order = Integer(s[1])   # 入力パターンの与え方(=0:順番,=1:ランダム)
    		@_eata  = Float(s[3])   # 重み及びバイアス修正パラメータ
    		@_alpha = Float(s[5])   # 重み及びバイアス修正パラメータ
    		f.close()
    		srand()
    	end
    end
    	
    ######################################################
    # バックプロパゲーションのデータ(クラス BackData)
    ######################################################
    
    class BackData
    	
    	####################################
    	# クラスBackDataのコンストラクタ
    	#      name : 入力データファイル名
    	####################################
    	
    	def initialize(name)
    				# 入力パターン数等
    		f      = open(name, "r")
    		s      = f.gets().split(" ")
    		@_noip = Integer(s[1])   # 入力パターンの数
    		@_noiu = Integer(s[3])   # 入力ユニットの数
    		@_noou = Integer(s[5])   # 出力ユニットの数
    				# 領域の確保
    		@_iptn = Array.new(@_noip)
    		for i1 in 0 ... @_noip
    			@_iptn[i1] = Array.new(@_noiu)
    		end
    	                      # iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
    	                      #              入力ユニットの入力値
    	                      #                i=0,noip-1  j=0,noiu-1
    		@_optn = Array.new(@_noip)
    		for i1 in 0 ... @_noip
    			@_optn[i1] = Array.new(@_noou)
    		end
    	                      # optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
    	                      #              番目の出力ユニットの目標出力値
    	                      #                i=0,noip-1  j=0,noou-1
    				# 入力パターン及び各入力パターンに対する出力パターンの入力
    		for i1 in 0 ... @_noip
    			s = f.gets().split(" ")
    			for i2 in 0 ... @_noiu
    				@_iptn[i1][i2] = Float(s[i2+1])
    			end
    			s = f.gets().split(" ")
    			for i2 in 0 ... @_noou
    				@_optn[i1][i2] = Float(s[i2+1])
    			end
    		end
    		f.close()
    	end
    
    	attr_accessor("_noip", "_noiu", "_noou", "_iptn", "_optn")
    end
    
    ###########################################
    # バックプロパゲーション(クラス Backpr)
    ###########################################
    
    class Backpr < BackControl
    	
    	################################################
    	# クラスBackprのコンストラクタ
    	#      name_c : 制御データ用入力ファイル名
    	#      name_s : ネットワーク記述入力ファイル名
    	################################################
    	
    	def initialize(name_c, name_s)
    	
    		super(name_c)   # 親のコンストラクタ
    		f = open(name_s, "r")
    				# 入力ユニット,出力ユニットの数,関数タイプ
    		s        = f.gets().split(" ")
    		@_noiu   = Integer(s[1])   # 入力ユニットの数
    		@_noou   = Integer(s[3])   # 出力ユニットの数
    		@_f_type = Integer(s[5])   # シグモイド関数のタイプ,0 : [0,1],1 : [-1,1]
    		@_nou    = @_noiu + @_noou   # 入力ユニットと出力ユニットの和
    	                                 # 各ユニットには最も上の出力ユニットから,
    	                                 # 隠れ層の各ユニット,及び,入力ユニットに至る
    	                                 # 一連のユニット番号が付けられる
    				# 隠れユニットの階層数と各階層のユニット数
    		s       = f.gets().split(" ")
    		@_nolvl = Integer(s[1])   # 隠れユニットの階層数
    		@_nohu  = Array.new(@_nolvl+1)
    	                 # nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
    	                 #           には下から順に番号が付けられ,出力層はレ
    	                 #           ベル(nolvl+1)の隠れ層とも見做される)
    	                 #             i=0,nolvl
    		@_nohu[@_nolvl] = @_noou
    	
    		if @_nolvl > 0
    			for i1 in 0 ... @_nolvl
    				@_nohu[i1]  = Integer(s[i1+3])
    				@_nou      += @_nohu[i1]
    			end
    		end
    				# 領域の確保
    		@_con = Array.new(@_nou)
    		for i1 in 0 ... @_nou
    			@_con[i1] = Array.new(@_nou)
    		end
    		for i1 in 0 ... @_nou
    			for i2 in 0 ... @_nou
    				if i1 == i2
    					@_con[i1][i2] = -1
    				else
    					@_con[i1][i2] = 0
    	              # 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
    				end
    			end
    		end
    	
    		@_w = Array.new(@_nou)
    		for i1 in 0 ... @_nou
    			@_w[i1] = Array.new(@_nou)
    		end
    		for i1 in 0 ... @_nou
    			for i2 in 0 ... @_nou
    				@_w[i1][i2] = 0.0
    	              # 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
    			end
    		end
    	
    		@_dp    = Array.new(@_nou)   # ユニット(i+1)の誤差  i=0,nou-1
    		@_op    = Array.new(@_nou)   # ユニット(i+1)の出力  i=0,nou-1
    		@_theta = Array.new(@_nou)   # ユニット(i+1)のバイアス  i=0,nou
    		for i1 in 0 ... @_nou
    			@_theta[i1] = 0.2 * rand(0) - 0.1
    		end
    				# 各ユニットのバイアスとユニット間の接続関係
    						# バイアス
    							# バイアスデータの数
    		s = f.gets().split(" ")
    		n = Integer(s[1])
    		f.gets()
    		f.gets()
    		f.gets()
    	
    		if n > 0
    							# バイアスデータの処理
    			for i0 in 0 ... n
    				s = f.gets().split(" ")
    								# ユニット番号
    				k1 = Integer(s[0])
    								# 不適当なユニット番号のチェック
    				if k1 < 1 or k1 > (@_nou-@_noiu)
    					print("***error  ユニット番号 " + String(k1) + " が不適当" + "\n")
    				end
    								# バイアスの与え方
    				k1            -= 1
    				id             = Integer(s[1])
    				@_con[k1][k1]  = id
    								# バイアスの初期設定
    				if @_con[k1][k1] == -1
    					x1          = Float(s[2])
    					x2          = Float(s[3])
    					@_theta[k1] = (x2 - x1) * rand(0) + x1
    				elsif @_con[k1][k1] == -2 or @_con[k1][k1] == -3
    					@_theta[k1] = Float(s[2])
    				else
    					print("***error  バイアスの与え方が不適当\n")
    				end
    			end
    		end
    						# 接続方法
    							# 接続データの数
    		s = f.gets().split(" ")
    		n = Integer(s[1])
    		f.gets()
    		f.gets()
    		f.gets()
    	
    		if n > 0
    							# 接続データの処理
    			for i0 in 0 ... n
    				s  = f.gets().split(" ")
    								# 接続情報
    				k1 = Integer(s[0])
    				k2 = Integer(s[1])
    				k3 = Integer(s[2])
    				k4 = Integer(s[3])
    								# 不適切な接続のチェック
    				sw = 0
    				if k1 < 1 or k2 < 1 or k3 < 1 or k4 < 1
    					sw = 1
    				else
    					if k1 > @_nou or k2 > @_nou or k3 > @_nou or k4 > @_nou
    						sw = 1
    					else
    						if k1 > k2 or k3 > k4
    							sw = 1
    						else
    							if k4 >= k1
    								sw = 1
    							else
    								l1 = -1
    								k  = 0
    								i1 = @_nolvl
    								while i1 > -1
    									k += @_nohu[i1]
    									if k1 <= k
    										l1 = i1
    										break
    									end
    									i1 -= 1
    								end
    								l2 = -1
    								k  = 0
    								i1 = @_nolvl
    								while i1 > -1
    									k += @_nohu[i1]
    									if k4 <= k
    										l2 = i1
    										break
    									end
    									i1 -= 1
    								end
    								if l2 <= l1
    									sw = 1
    								end
    							end
    						end
    					end
    				end
    	
    				if sw > 0
    					print("***error  ユニット番号が不適当(" + String(k1) + " " + String(k2) + " " + String(k3) + " " + String(k4) + ")\n")
    				end
    								# 重みの初期値の与え方
    				k1 -= 1
    				k2 -= 1
    				k3 -= 1
    				k4 -= 1
    	
    				id = Integer(s[4])
    	
    				if id == 1
    					x1  = Float(s[5])
    					x2  = Float(s[6])
    				else
    					if id > 1
    						x1  = Float(s[5])
    					else
    						if id != 0
    							print("***error  接続方法が不適当\n")
    						end
    					end
    				end
    								# 重みの初期値の設定
    				for i1 in k3 ... k4+1
    					for i2 in k1 ... k2+1
    						@_con[i1][i2] = id
    						if id == 0
    							@_w[i1][i2] = 0.0
    						elsif id == 1
    							@_w[i1][i2] = (x2 - x1) * rand(0) + x1
    						elsif id == 2
    							@_w[i1][i2] = x1
    						elsif id == 3
    							@_w[i1][i2] = x1
    						end
    					end
    				end
    			end
    		end
    	
    		f.close()
    	end
    	
    	##########################################
    	# 誤差の計算,及び,重みとバイアスの修正
    	#      ptn[i1] : 出力パターン
    	##########################################
    	
    	def Err_back(ptn)
    	
    		for i1 in 0 ... @_nou-@_noiu
    						# 誤差の計算
    			if i1 < @_noou
    				if @_f_type == 0
    					@_dp[i1] = (ptn[i1] - @_op[i1]) * @_op[i1] * (1.0 - @_op[i1])
    				else
    					@_dp[i1] = 0.5 * (ptn[i1] - @_op[i1]) * (@_op[i1] - 1.0) * (@_op[i1] + 1.0)
    				end
    			else
    				x1 = 0.0
    				for i2 in 0 ... i1
    					if @_con[i2][i1] > 0
    						x1 += @_dp[i2] * @_w[i2][i1]
    					end
    				end
    				if @_f_type == 0
    					@_dp[i1] = @_op[i1] * (1.0 - @_op[i1]) * x1
    				else
    					@_dp[i1] = 0.5 * (@_op[i1] - 1.0) * (@_op[i1] + 1.0) * x1
    				end
    			end
    						# 重みの修正
    			for i2 in i1+1 ... @_nou
    				if @_con[i1][i2] == 1 or @_con[i1][i2] == 2
    					x1           = @_eata * @_dp[i1] * @_op[i2] + @_alpha * @_w[i2][i1]
    					@_w[i2][i1]  = x1
    					@_w[i1][i2] += x1
    				end
    			end
    						# バイアスの修正
    			if @_con[i1][i1] >= -2
    				x1           = @_eata * @_dp[i1] + @_alpha * @_w[i1][i1]
    				@_w[i1][i1]  = x1
    				@_theta[i1] += x1
    			end
    		end
    	end
    	
    	########################################################
    	# 与えられた入力パターンに対する各ユニットの出力の計算
    	########################################################
    	
    	def Forward()
    	
    		i1 = @_nou - @_noiu - 1
    		while i1 > -1
    	
    			sum = -@_theta[i1]
    	
    			for i2 in i1+1 ... @_nou
    				if @_con[i1][i2] > 0
    					sum -= @_w[i1][i2] * @_op[i2]
    				end
    			end
    	
    			if @_f_type == 0
    				@_op[i1] = 1.0 / (1.0 + Math.exp(sum))
    			else
    				@_op[i1] = 1.0 - 2.0 / (1.0 + Math.exp(sum))
    			end
    			i1 -= 1
    		end
    	end
    	
    	#############################
    	# 学習の実行
    	#      p : 認識パターン
    	#      m_tri : 最大学習回数
    	#############################
    	
    	def Learn(p, m_tri)
    	
    		k0 = -1
    				# エラーチェック
    		if @_noiu != p._noiu or @_noou != p._noou
    			print("***error  入力または出力ユニットの数が違います\n")
    		end
    	
    		for i1 in 0 ... m_tri
    				# パターンを与える順番の決定
    			if @_order == 0   # 順番
    				k0 += 1
    				if k0 >= p._noip
    					k0 = 0
    				end
    			else   # ランダム
    				k0 = Integer(rand(0) * p._noip)
    				if k0 >= p._noip
    					k0 = p._noip - 1
    				end
    			end
    				# 出力ユニットの結果を計算
    			k1 = @_nou - @_noiu
    			for i2 in 0 ... @_noiu
    				@_op[k1+i2] = p._iptn[k0][i2]
    			end
    	
    			Forward()
    				# 重みとバイアスの修正
    			Err_back(p._optn[k0])
    		end
    	end
    	
    	################################################
    	# 与えられた対象の認識と出力
    	#      p : 認識パターン
    	#      pr : =0 : 出力を行わない
    	#           =1 : 出力を行う
    	#           =2 : 出力を行う(未学習パターン)
    	#      tri : 現在の学習回数
    	#      return : 誤って認識したパターンの数
    	################################################
    	
    	def Recog(p, pr, tri)
    	
    		no = 0
    				# ファイルのオープン
    		if @_p_type < 0 and pr > 0
    			if pr == 1
    				out = open(@_o_file, "w")
    				out.print("***学習パターン***\n\n")
    			else
    				out = open(@_o_file, "a")
    				out.print("\n***未学習パターン***\n\n")
    			end
    		end
    				# 各パターンに対する出力
    		for i1 in 0 ... p._noip
    						# 入力パターンの設定
    			k1 = @_nou - @_noiu
    			for i2 in 0 ... @_noiu
    				@_op[k1+i2] = p._iptn[i1][i2]
    			end
    						# 出力の計算
    			Forward()
    						# 結果の表示
    			if @_p_type != 0 and pr > 0
    	
    				printf("入力パターン%4d    ", (i1+1))
    				for i2 in 0 ... @_noiu
    					printf("%5.2f", @_op[k1+i2])
    					if i2 == @_noiu-1
    						print("\n")
    					else
    						if ((i2+1) % 10) == 0
    							print("\n                    ")
    						end
    					end
    				end
    	
    				print("\n    出力パターン(理想)   ")
    				for i2 in 0 ... @_noou
    					printf("%10.3f", p._optn[i1][i2])
    					if i2 == @_noou-1
    						print("\n")
    					else
    						if ((i2+1) % 5) == 0
    							print("\n                         ")
    						end
    					end
    				end
    			end
    	
    			sw = 0
    			if @_p_type != 0 and pr > 0
    				print("                (実際)   ")
    			end
    			for i2 in 0 ... @_noou
    				if @_p_type != 0 and pr > 0
    					printf("%10.3f", @_op[i2])
    					if i2 == @_noou-1
    						print("\n")
    					else
    						if ((i2+1) % 5) == 0
    							print("\n                         ")
    						end
    					end
    				end
    				if (@_op[i2]-p._optn[i1][i2]).abs() > @_eps
    					sw = 1
    				end
    			end
    	
    			if sw > 0
    				no += 1
    			end
    	
    			if @_p_type < 0 and pr > 0
    	
    				out.printf("入力パターン%4d    ", (i1+1))
    				for i2 in 0 ... @_noiu
    					out.printf("%5.2f", @_op[k1+i2])
    					if i2 == @_noiu-1
    						out.print("\n")
    					else
    						if ((i2+1) % 10) == 0
    							out.print("\n                    ")
    						end
    					end
    				end
    	
    				out.print("\n    出力パターン(理想)   ")
    				for i2 in 0 ... @_noou
    					out.printf("%10.3f", p._optn[i1][i2])
    					if i2 == @_noou-1
    						out.print("\n")
    					else
    						if ((i2+1) % 5) == 0
    							out.print("\n                         ")
    						end
    					end
    				end
    	
    				out.print("                (実際)   ")
    				for i2 in 0 ... @_noou
    					out.printf("%10.3f", @_op[i2])
    					if i2 == @_noou-1
    						out.print("\n")
    					else
    						if ((i2+1) % 5) == 0
    							out.print("\n                         ")
    						end
    					end
    				end
    			end
    	
    			if @_p_type != 0 and pr > 0
    				$stdin.gets()
    			end
    		end
    				# 重みの出力
    		if (@_p_type < -1 or @_p_type > 1) and pr == 1
    	
    			print("    重み")
    			for i1 in 0 ... @_nou-@_noiu
    				printf("      to%4d from   ", (i1+1))
    				ln = -1
    				for i2 in 0 ... @_nou
    					if @_con[i1][i2] > 0
    						if ln <= 0
    							if ln < 0
    								ln = 0
    							else
    								print("\n                    ")
    							end
    						end
    						printf("%4d%11.3f", i2+1, @_w[i1][i2])
    						ln += 1
    						if ln == 4
    							ln = 0
    						end
    					end
    				end
    	
    				print("\n")
    			end
    	
    			print("\n    バイアス   ")
    			ln = 0
    			for i1 in 0 ... @_nou-@_noiu
    				printf("%4d%11.3f", i1+1, @_theta[i1])
    				ln += 1
    				if ln == 4 and i1 != @_nou-@_noiu-1
    					ln = 0
    					print("\n               ")
    				end
    			end
    			print("\n")
    	
    			$stdin.gets()
    		end
    	
    		if @_p_type < 0 and pr == 1
    	
    			out.print("    重み\n")
    			for i1 in 0 ... @_nou-@_noiu
    				out.printf("      to%4d from   ", (i1+1))
    				ln = -1
    				for i2 in 0 ... @_nou
    					if @_con[i1][i2] > 0
    						if ln <= 0
    							if ln < 0
    								ln = 0
    							else
    								out.print("\n                    ")
    							end
    						end
    						out.printf("%4d%11.3f", i2+1, @_w[i1][i2])
    						ln += 1
    						if ln == 4
    							ln = 0
    						end
    					end
    				end
    	
    				out.print("\n")
    			end
    	
    			out.print("\n    バイアス   ")
    			ln = 0
    			for i1 in 0 ... @_nou-@_noiu
    				out.printf("%4d%11.3f", i1+1, @_theta[i1])
    				ln += 1
    				if ln == 4 and i1 != @_nou-@_noiu-1
    					ln = 0
    					out.print("\n               ")
    				end
    			end
    	
    			if ln != 0
    				out.print("\n")
    			end
    		end
    	
    		if @_p_type < 0 and pr > 0
    			out.close()
    		end
    	
    		return no
    	end
    end
    
    ct = 0
    no = 1
    				# エラー
    if ARGV.length != 2
    	print("***error   入力データファイル名を指定して下さい\n")
    
    else
    				# ネットワークの定義
    	net   = Backpr.new(ARGV[0], ARGV[1])
    				# 学習パターン等の入力
    	print("学習回数は? ")
    	m_tri = Integer($stdin.gets())
    	print("何回毎に収束を確認しますか? ")
    	conv = Integer($stdin.gets())
    	print("学習パターンのファイル名は? ")
    	f_name = $stdin.gets().strip()
    	dt1    = BackData.new(f_name)
    				# 学習
    	while ct < m_tri and no > 0
    
    		if (ct + conv) < m_tri
    			tri = conv
    		else
    			tri = m_tri - ct
    		end
    		ct += tri
    
    		net.Learn(dt1, tri)   # 学習
    
    		no = net.Recog(dt1, 0, ct)   # 学習対象の認識
    
    		print("   回数 " + String(ct) + " 誤って認識したパターン数 " + String(no) + "\n")
    	end
    
    	no = net.Recog(dt1, 1, ct)   # 学習対象の認識と出力
    				# 未学習パターンの認識
    	print("未学習パターンの認識を行いますか?(=1:行う,=0:行わない) ")
    	sw = Integer($stdin.gets())
    
    	if sw > 0
    		print("未学習パターンのファイル名は? ")
    		f_name = $stdin.gets().strip()
    		dt2    = BackData.new(f_name)
    		no     = net.Recog(dt2, 2, ct)   # 未学習対象の認識と出力
    	end
    end
    
    =begin
    ------------------------制御データ----------------
    誤差 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
    =end
    			

  6. Python

    # -*- coding: UTF-8 -*-
    import numpy as np
    import sys
    from math import *
    from random import *
    
    ######################################################
    # バックプロパゲーションの制御(クラス BackControl)
    ######################################################
    
    class BackControl :
    	
    	####################################
    	# クラスBackControlのコンストラクタ
    	#      name : 入力データファイル名
    	####################################
    	
    	def __init__(self, name) :
    	
    		f           = open(name, "r")
    		s           = f.readline().split()
    		self.eps    = float(s[1])   # 許容誤差
    		self.p_type = int(s[3])   # 出力先・方法の指定
    	                  #   =0 : 誤って認識した数だけ出力
    	                  #   =1 : 認識結果を出力
    	                  #   =2 : 認識結果と重みを出力
    	                  #        (負の時は,認識結果と重みをファイルへも出力)
    		if self.p_type < 0 :
    			self.o_file = s[5]   # 出力ファイル名
    		s          = f.readline().split()
    		self.order = int(s[1])   # 入力パターンの与え方(=0:順番,=1:ランダム)
    		self.eata  = float(s[3])   # 重み及びバイアス修正パラメータ
    		self.alpha = float(s[5])   # 重み及びバイアス修正パラメータ
    		f.close()
    		seed()
    	
    ######################################################
    # バックプロパゲーションのデータ(クラス BackData)
    ######################################################
    
    class BackData :
    	
    	####################################
    	# クラスBackDataのコンストラクタ
    	#      name : 入力データファイル名
    	####################################
    	
    	def __init__(self, name) :
    				# 入力パターン数等
    		f         = open(name, "r")
    		s         = f.readline().split()
    		self.noip = int(s[1])   # 入力パターンの数
    		self.noiu = int(s[3])   # 入力ユニットの数
    		self.noou = int(s[5])   # 出力ユニットの数
    				# 領域の確保
    		self.iptn = np.empty((self.noip, self.noiu), np.float)
    	                      # iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
    	                      #              入力ユニットの入力値
    	                      #                i=0,noip-1  j=0,noiu-1
    		self.optn = np.empty((self.noip, self.noou), np.float)
    	                      # optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
    	                      #              番目の出力ユニットの目標出力値
    	                      #                i=0,noip-1  j=0,noou-1
    				# 入力パターン及び各入力パターンに対する出力パターンの入力
    		for i1 in range(0, self.noip) :
    			s = f.readline().split()
    			for i2 in range(0, self.noiu) :
    				self.iptn[i1][i2] = float(s[i2+1])
    			s = f.readline().split()
    			for i2 in range(0, self.noou) :
    				self.optn[i1][i2] = float(s[i2+1])
    		f.close()
    
    ###########################################
    # バックプロパゲーション(クラス Backpr)
    ###########################################
    
    class Backpr(BackControl) :
    	
    	################################################
    	# クラスBackprのコンストラクタ
    	#      name_c : 制御データ用入力ファイル名
    	#      name_s : ネットワーク記述入力ファイル名
    	################################################
    	
    	def __init__(self, name_c, name_s) :
    	
    		BackControl.__init__(self, name_c)   # 親のコンストラクタ
    		f = open(name_s, "r")
    				# 入力ユニット,出力ユニットの数,関数タイプ
    		s           = f.readline().split()
    		self.noiu   = int(s[1])   # 入力ユニットの数
    		self.noou   = int(s[3])   # 出力ユニットの数
    		self.f_type = int(s[5])   # シグモイド関数のタイプ,0 : [0,1],1 : [-1,1]
    		self.nou    = self.noiu + self.noou   # 入力ユニットと出力ユニットの和
    	                  # 各ユニットには最も上の出力ユニットから,
    	                  # 隠れ層の各ユニット,及び,入力ユニットに至る
    	                  # 一連のユニット番号が付けられる
    				# 隠れユニットの階層数と各階層のユニット数
    		s          = f.readline().split()
    		self.nolvl = int(s[1])   # 隠れユニットの階層数
    		self.nohu  = np.empty(self.nolvl+1, np.int)
    	                 # nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
    	                 #           には下から順に番号が付けられ,出力層はレ
    	                 #           ベル(nolvl+1)の隠れ層とも見做される)
    	                 #             i=0,nolvl
    		self.nohu[self.nolvl] = self.noou
    	
    		if self.nolvl > 0 :
    			for i1 in range(0, self.nolvl) :
    				self.nohu[i1]  = int(s[i1+3])
    				self.nou      += self.nohu[i1]
    				# 領域の確保
    		self.con = np.empty((self.nou, self.nou), np.int)
    		for i1 in range(0, self.nou) :
    			for i2 in range(0, self.nou) :
    				if i1 == i2 :
    					self.con[i1][i2] = -1
    				else :
    					self.con[i1][i2] = 0
    	              # 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
    	
    		self.w = np.empty((self.nou, self.nou), np.float)
    		for i1 in range(0, self.nou) :
    			for i2 in range(0, self.nou) :
    				self.w[i1][i2] = 0.0
    	              # 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
    	
    		self.dp    = np.empty(self.nou, np.float)   # ユニット(i+1)の誤差  i=0,nou-1
    		self.op    = np.empty(self.nou, np.float)   # ユニット(i+1)の出力  i=0,nou-1
    		self.theta = np.empty(self.nou, np.float)   # ユニット(i+1)のバイアス  i=0,nou
    		for i1 in range(0, self.nou) :
    			self.theta[i1] = 0.2 * random() - 0.1
    				# 各ユニットのバイアスとユニット間の接続関係
    						# バイアス
    							# バイアスデータの数
    		s = f.readline().split()
    		n = int(s[1])
    		f.readline()
    		f.readline()
    		f.readline()
    	
    		if n > 0 :
    							# バイアスデータの処理
    			for i0 in range(0, n) :
    				s = f.readline().split()
    								# ユニット番号
    				k1 = int(s[0])
    								# 不適当なユニット番号のチェック
    				if k1 < 1 or k1 > (self.nou-self.noiu) :
    					print("***error  ユニット番号 " + str(k1) + " が不適当")
    								# バイアスの与え方
    				k1 -= 1
    				id  = int(s[1])
    				self.con[k1][k1] = id
    								# バイアスの初期設定
    				if self.con[k1][k1] == -1 :
    					x1  = float(s[2])
    					x2  = float(s[3])
    					self.theta[k1] = (x2 - x1) * random() + x1
    				elif self.con[k1][k1] == -2 or self.con[k1][k1] == -3 :
    					self.theta[k1] = float(s[2])
    				else :
    					print("***error  バイアスの与え方が不適当")
    						# 接続方法
    							# 接続データの数
    		s = f.readline().split()
    		n = int(s[1])
    		f.readline()
    		f.readline()
    		f.readline()
    	
    		if n > 0 :
    							# 接続データの処理
    			for i0 in range(0, n) :
    				s  = f.readline().split()
    								# 接続情報
    				k1 = int(s[0])
    				k2 = int(s[1])
    				k3 = int(s[2])
    				k4 = int(s[3])
    								# 不適切な接続のチェック
    				sw = 0
    				if k1 < 1 or k2 < 1 or k3 < 1 or k4 < 1 :
    					sw = 1
    				else :
    					if k1 > self.nou or k2 > self.nou or k3 > self.nou or k4 > self.nou :
    						sw = 1
    					else :
    						if k1 > k2 or k3 > k4 :
    							sw = 1
    						else :
    							if k4 >= k1 :
    								sw = 1
    							else :
    								l1 = -1
    								k  = 0
    								for i1 in range(self.nolvl, -1, -1) :
    									k += self.nohu[i1]
    									if k1 <= k :
    										l1 = i1
    										break
    								l2 = -1
    								k  = 0
    								for i1 in range(self.nolvl, -1, -1) :
    									k += self.nohu[i1]
    									if k4 <= k :
    										l2 = i1
    										break
    								if l2 <= l1 :
    									sw = 1
    	
    				if sw > 0 :
    					print("***error  ユニット番号が不適当(" + str(k1) + " " + str(k2) + " " + str(k3) + " " + str(k4) + ")")
    								# 重みの初期値の与え方
    				k1 -= 1
    				k2 -= 1
    				k3 -= 1
    				k4 -= 1
    	
    				id = int(s[4])
    	
    				if id == 1 :
    					x1  = float(s[5])
    					x2  = float(s[6])
    				else :
    					if id > 1 :
    						x1  = float(s[5])
    					else :
    						if id != 0 :
    							print("***error  接続方法が不適当")
    								# 重みの初期値の設定
    				for i1 in range(k3, k4+1) :
    					for i2 in range(k1, k2+1) :
    						self.con[i1][i2] = id
    						if id == 0 :
    							self.w[i1][i2] = 0.0
    						elif id == 1 :
    							self.w[i1][i2] = (x2 - x1) * random() + x1
    						elif id == 2 :
    							self.w[i1][i2] = x1
    						elif id == 3 :
    							self.w[i1][i2] = x1
    	
    		f.close()
    	
    	##########################################
    	# 誤差の計算,及び,重みとバイアスの修正
    	#      ptn[i1] : 出力パターン
    	##########################################
    	
    	def Err_back(self, ptn) :
    	
    		for i1 in range(0, self.nou-self.noiu) :
    						# 誤差の計算
    			if i1 < self.noou :
    				if self.f_type == 0 :
    					self.dp[i1] = (ptn[i1] - self.op[i1]) * self.op[i1] * (1.0 - self.op[i1])
    				else :
    					self.dp[i1] = 0.5 * (ptn[i1] - self.op[i1]) * (self.op[i1] - 1.0) * (self.op[i1] + 1.0)
    			else :
    				x1 = 0.0
    				for i2 in range(0, i1) :
    					if self.con[i2][i1] > 0 :
    						x1 += self.dp[i2] * self.w[i2][i1]
    				if self.f_type == 0 :
    					self.dp[i1] = self.op[i1] * (1.0 - self.op[i1]) * x1
    				else :
    					self.dp[i1] = 0.5 * (self.op[i1] - 1.0) * (self.op[i1] + 1.0) * x1
    						# 重みの修正
    			for i2 in range(i1+1, self.nou) :
    				if self.con[i1][i2] == 1 or self.con[i1][i2] == 2 :
    					x1 = self.eata * self.dp[i1] * self.op[i2] + self.alpha * self.w[i2][i1]
    					self.w[i2][i1]  = x1
    					self.w[i1][i2] += x1
    						# バイアスの修正
    			if self.con[i1][i1] >= -2 :
    				x1 = self.eata * self.dp[i1] + self.alpha * self.w[i1][i1]
    				self.w[i1][i1]  = x1
    				self.theta[i1] += x1
    	
    	########################################################
    	# 与えられた入力パターンに対する各ユニットの出力の計算
    	########################################################
    	
    	def Forward(self) :
    	
    		for i1 in range(self.nou-self.noiu-1, -1, -1) :
    	
    			sum = -self.theta[i1]
    	
    			for i2 in range(i1+1, self.nou) :
    				if self.con[i1][i2] > 0 :
    					sum -= self.w[i1][i2] * self.op[i2]
    	
    			if self.f_type == 0 :
    				self.op[i1] = 1.0 / (1.0 + exp(sum))
    			else :
    				self.op[i1] = 1.0 - 2.0 / (1.0 + exp(sum))
    	
    	#############################
    	# 学習の実行
    	#      p : 認識パターン
    	#      m_tri : 最大学習回数
    	#############################
    	
    	def Learn(self, p, m_tri) :
    	
    		k0 = -1
    				# エラーチェック
    		if self.noiu != p.noiu or self.noou != p.noou :
    			print("***error  入力または出力ユニットの数が違います")
    	
    		for i1 in range(0, m_tri) :
    				# パターンを与える順番の決定
    			if self.order == 0 :   # 順番
    				k0 += 1
    				if k0 >= p.noip :
    					k0 = 0
    			else :   # ランダム
    				k0 = int(random() * p.noip)
    				if k0 >= p.noip :
    					k0 = p.noip - 1
    				# 出力ユニットの結果を計算
    			k1 = self.nou - self.noiu
    			for i2 in range(0, self.noiu) :
    				self.op[k1+i2] = p.iptn[k0][i2]
    	
    			self.Forward()
    				# 重みとバイアスの修正
    			self.Err_back(p.optn[k0])
    	
    	################################################
    	# 与えられた対象の認識と出力
    	#      p : 認識パターン
    	#      pr : =0 : 出力を行わない
    	#           =1 : 出力を行う
    	#           =2 : 出力を行う(未学習パターン)
    	#      tri : 現在の学習回数
    	#      return : 誤って認識したパターンの数
    	################################################
    	
    	def Recog(self, p, pr, tri) :
    	
    		No = 0
    				# ファイルのオープン
    		if self.p_type < 0 and pr > 0 :
    			if pr == 1 :
    				out = open(self.o_file, "w")
    				out.write("***学習パターン***\n\n")
    			else :
    				out = open(self.o_file, "a")
    				out.write("\n***未学習パターン***\n\n")
    				# 各パターンに対する出力
    		for i1 in range(0, p.noip) :
    						# 入力パターンの設定
    			k1 = self.nou - self.noiu
    			for i2 in range(0, self.noiu) :
    				self.op[k1+i2] = p.iptn[i1][i2]
    						# 出力の計算
    			self.Forward()
    						# 結果の表示
    			if self.p_type != 0 and pr > 0 :
    	
    				print("入力パターン{0:4d}    ".format(i1+1), end="")
    				for i2 in range(0, self.noiu) :
    					print("{0:5.2f}".format(self.op[k1+i2]), end="")
    					if i2 == self.noiu-1 :
    						print("")
    					else :
    						if ((i2+1) % 10) == 0 :
    							print("\n                    ", end="")
    	
    				print("\n    出力パターン(理想)   ", end="")
    				for i2 in range(0, self.noou) :
    					print("{0:10.3f}".format(p.optn[i1][i2]), end="")
    					if i2 == self.noou-1 :
    						print("")
    					else :
    						if ((i2+1) % 5) == 0 :
    							print("\n                         ", end="")
    	
    			sw = 0
    			if self.p_type != 0 and pr > 0 :
    				print("                (実際)   ", end="")
    			for i2 in range(0, self.noou) :
    				if self.p_type != 0 and pr > 0 :
    					print("{0:10.3f}".format(self.op[i2]), end="")
    					if i2 == self.noou-1 :
    						print("\n")
    					else :
    						if ((i2+1) % 5) == 0 :
    							print("\n                         ", end="")
    				if abs(self.op[i2]-p.optn[i1][i2]) > self.eps :
    					sw = 1
    	
    			if sw > 0 :
    				No += 1
    	
    			if self.p_type < 0 and pr > 0 :
    	
    				out.write("入力パターン{0:4d}    ".format(i1+1))
    				for i2 in range(0, self.noiu) :
    					out.write("{0:5.2f}".format(self.op[k1+i2]))
    					if i2 == self.noiu-1 :
    						out.write("\n")
    					else :
    						if ((i2+1) % 10) == 0 :
    							out.write("\n                    ")
    	
    				out.write("\n    出力パターン(理想)   ")
    				for i2 in range(0, self.noou) :
    					out.write("{0:10.3f}".format(p.optn[i1][i2]))
    					if i2 == self.noou-1 :
    						out.write("\n")
    					else :
    						if ((i2+1) % 5) == 0 :
    							out.write("\n                         ")
    	
    				out.write("                (実際)   ")
    				for i2 in range(0, self.noou) :
    					out.write("{0:10.3f}".format(self.op[i2]))
    					if i2 == self.noou-1 :
    						out.write("\n")
    					else :
    						if ((i2+1) % 5) == 0 :
    							out.write("\n                         ")
    	
    			if self.p_type != 0 and pr > 0 :
    				input("")
    				# 重みの出力
    		if (self.p_type < -1 or self.p_type > 1) and pr == 1 :
    	
    			print("    重み")
    			for i1 in range(0, self.nou-self.noiu) :
    				print("      to{0:4d} from   ".format(i1+1), end="")
    				ln = -1
    				for i2 in range(0, self.nou) :
    					if self.con[i1][i2] > 0 :
    						if ln <= 0 :
    							if ln < 0 :
    								ln = 0
    							else :
    								print("\n                    ", end="")
    						print("{0:4d}{1:11.3f}".format(i2+1, self.w[i1][i2]), end="")
    						ln += 1
    						if ln == 4 :
    							ln = 0
    	
    				print("")
    	
    			print("\n    バイアス   ", end="")
    			ln = 0
    			for i1 in range(0, self.nou-self.noiu) :
    				print("{0:4d}{1:11.3f}".format(i1+1, self.theta[i1]), end="")
    				ln += 1
    				if ln == 4 and i1 != self.nou-self.noiu-1 :
    					ln = 0
    					print("\n               ", end="")
    			print("")
    	
    			input("")
    	
    		if self.p_type < 0 and pr == 1 :
    	
    			out.write("    重み\n")
    			for i1 in range(0, self.nou-self.noiu) :
    				out.write("      to{0:4d} from   ".format(i1+1))
    				ln = -1
    				for i2 in range(0, self.nou) :
    					if self.con[i1][i2] > 0 :
    						if ln <= 0 :
    							if ln < 0 :
    								ln = 0
    							else :
    								out.write("\n                    ")
    						out.write("{0:4d}{1:11.3f}".format(i2+1, self.w[i1][i2]))
    						ln += 1
    						if ln == 4 :
    							ln = 0
    	
    				out.write("\n")
    	
    			out.write("\n    バイアス   ")
    			ln = 0
    			for i1 in range(0, self.nou-self.noiu) :
    				out.write("{0:4d}{1:11.3f}".format(i1+1, self.theta[i1]))
    				ln += 1
    				if ln == 4 and i1 != self.nou-self.noiu-1 :
    					ln = 0
    					out.write("\n               ")
    	
    			if ln != 0 :
    				out.write("\n")
    	
    		if self.p_type < 0 and pr > 0 :
    			out.close()
    	
    		return No
    
    ##########################
    # back propagation model
    #      coded by Y.Suganuma
    ##########################
    
    ct = 0
    no = 1
    				# エラー
    if len(sys.argv) != 3 :
    	print("***error   入力データファイル名を指定して下さい")
    
    else :
    				# ネットワークの定義
    	net = Backpr(sys.argv[1], sys.argv[2])
    				# 学習パターン等の入力
    	m_tri  = int(input("学習回数は? "))
    	conv   = int(input("何回毎に収束を確認しますか? "))
    	f_name = input("学習パターンのファイル名は? ")
    	dt1    = BackData(f_name)
    				# 学習
    	while ct < m_tri and no > 0 :
    
    		if (ct + conv) < m_tri :
    			tri = conv
    		else :
    			tri = m_tri - ct
    		ct += tri
    
    		net.Learn(dt1, tri)   # 学習
    
    		no = net.Recog(dt1, 0, ct)   # 学習対象の認識
    
    		print("   回数 " + str(ct) + " 誤って認識したパターン数 " + str(no))
    
    	no = net.Recog(dt1, 1, ct)   # 学習対象の認識と出力
    				# 未学習パターンの認識
    	sw = int(input("未学習パターンの認識を行いますか?(=1:行う,=0:行わない) "))
    
    	if sw > 0 :
    
    		f_name = input("未学習パターンのファイル名は? ")
    		dt2    = BackData(f_name)
    		no     = net.Recog(dt2, 2, ct)   # 未学習対象の認識と出力
    
    """
    ------------------------制御データ----------------
    誤差 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
    """
    
    """
    ------------------------制御データ----------------
    誤差 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
    """
    			

  7. C#

    /****************************/
    /* back propagation model   */
    /*      coded by Y.Suganuma */
    /****************************/
    using System;
    using System.IO;
    
    class Program
    {
    	/****************/
    	/* main program */
    	/****************/
    	static void Main(String[] args)
    	{
    					// エラー
    		if (args.Length != 2) {
    			Console.WriteLine("***error   入力データファイル名を指定して下さい");
    			Environment.Exit(1);
    		}
    
    		else {
    					// ネットワークの定義
    			Backpr net = new Backpr (args[0], args[1]);
    					// 学習パターン等の入力
    			Console.Write("学習回数は? ");
    			int m_tri = int.Parse(Console.ReadLine());   // 最大学習回数
    			Console.Write("何回毎に収束を確認しますか? ");
    			int conv = int.Parse(Console.ReadLine());   // 収束確認回数
    
    			Console.Write("学習パターンのファイル名は? ");
    			String f_name = Console.ReadLine();
    
    			BackData dt1 = new BackData(f_name);
    					// 学習
    			int max = 0, no = 1;
    			while (max < m_tri && no > 0) {
    
    				int tri = ((max + conv) < m_tri) ? conv : m_tri - max;
    				max    += tri;
    
    				net.Learn(dt1, tri);   // 学習
    
    				no = net.Recog(dt1, 0, max);   // 学習対象の認識
    
    				Console.WriteLine("   回数 " + max + " 誤って認識したパターン数 " + no);
    			}
    
    			no = net.Recog(dt1, 1, max);   // 学習対象の認識と出力
    					// 未学習パターンの認識
    			Console.Write("未学習パターンの認識を行いますか?(=1:行う,=0:行わない) ");
    			int sw = int.Parse(Console.ReadLine());
    
    			if (sw > 0) {
    
    				Console.Write("未学習パターンのファイル名は? ");
    				f_name = Console.ReadLine();
    
    				BackData dt2 = new BackData(f_name);
    
    				no = net.Recog(dt2, 2, max);   // 未学習対象の認識と出力
    			}
    		}
    	}
    }
    
    /******************************************************/
    /* バックプロパゲーションの制御(クラス BackControl) */
    /******************************************************/
    class BackControl {
    	protected double alpha, eata;   //重み及びバイアス修正パラメータ
    	protected double eps;   // 許容誤差
    	protected int order;   // 入力パターンの与え方(=0:順番,=1:ランダム)
    	protected int p_type;   // 出力先・方法の指定
                                //   =0 : 誤って認識した数だけ出力
                                //   =1 : 認識結果を出力
                                //   =2 : 認識結果と重みを出力
                                //        (負の時は,認識結果と重みをファイルへも出力)
    	protected String o_file;   // 出力ファイル名
    
    	/*************************************/
    	/* クラスBackControlのコンストラクタ */
    	/*      name : 入力データファイル名  */
    	/*************************************/
    	public BackControl(String name)
    	{
    		char[] charSep = new char[] {' '};
    		String[] lines = File.ReadAllLines(name);
    		String[] str   = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		eps            = double.Parse(str[1]);
    		p_type         = int.Parse(str[3]);
    		if (p_type < 0)
    			o_file = str[5];
    
    		str   = lines[1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		order = int.Parse(str[1]);
    		eata  = double.Parse(str[3]);
    		alpha = double.Parse(str[5]);
    	}
    }
    
    /*****************************************************/
    /* バックプロパゲーションのデータ(クラス BackData) */
    /*****************************************************/
    class BackData {
    	public int noiu;   // 入力ユニットの数
    	public int noou;   // 出力ユニットの数
    	public int noip;   // 入力パターンの数
    	public double[][] iptn;   // iptn[i][j] : (i+1)番目の入力パターンの(j+1)番目の
                                  //              入力ユニットの入力値
                                  //                i=0,noip-1  j=0,noiu-1
    	public double[][] optn;   // optn[i][j] : (i+1)番目の入力パターンに対する(j+1)
                                  //              番目の出力ユニットの目標出力値
                                  //                i=0,noip-1  j=0,noou-1
    
    	/************************************/
    	/* クラスBackDataのコンストラクタ   */
    	/*      name : 入力データファイル名 */
    	/************************************/
    	public BackData(String name)
    	{
    		char[] charSep = new char[] {' '};
    		String[] lines = File.ReadAllLines(name);
    				//
    				// 入力パターン数等
    				//
    		String[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		noip         = int.Parse(str[1]);
    		noiu         = int.Parse(str[3]);
    		noou         = int.Parse(str[5]);
    				//
    				// 領域の確保
    				//
    		iptn = new double [noip][];
    		optn = new double [noip][];
    		for (int i1 = 0; i1 < noip; i1++) {
    			iptn[i1] = new double [noiu];
    			optn[i1] = new double [noou];
    		}
    				//
    				// 入力パターン及び各入力パターンに対する出力パターンの入力
    				//
    		for (int i1 = 0; i1 < noip; i1++) {
    			int k = 2 * i1 + 1;
    			str = lines[k].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    			for (int i2 = 0; i2 < noiu; i2++)
    				iptn[i1][i2] = double.Parse(str[i2+1]);
    			str = lines[k+1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    			for (int i2 = 0; i2 < noou; i2++)
    				optn[i1][i2] = double.Parse(str[i2+1]);
    		}
    	}
    }
    
    /*******************************************/
    /* バックプロパゲーション(クラス Backpr) */
    /*******************************************/
    class Backpr : BackControl {
    	sbyte[][] 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
    	int f_type;   // シグモイド関数のタイプ
                      //   0 : [0,1]
                      //   1 : [-1,1])
    	int noiu;   // 入力ユニットの数
    	int noou;   // 出力ユニットの数
    	int[] nohu;   // nohu[i] : レベル(i+1)の隠れ層のユニット数(隠れ層
                      //           には下から順に番号が付けられ,出力層はレ
                      //           ベル(nolvl+1)の隠れ層とも見做される)
                      //             i=0,nolvl
    	int nolvl;   // 隠れユニットの階層数
    	int nou;   // 入力,出力,及び,隠れ層の各ユニットの数の和(各ユニ
                   // ットには最も上の出力ユニットから,隠れ層の各ユニット,
                   // 及び,入力ユニットに至る一連のユニット番号が付けられ
                   // る)
    	double[] dp;   // dp[i] : ユニット(i+1)の誤差  i=0,nou-1
    	double[] op;   // op[i] : ユニット(i+1)の出力  i=0,nou-1
    	double[] theta;   //theta[i] : ユニット(i+1)のバイアス  i=0,nou
    	double[][] 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
    	Random rn;   // 乱数
    
    	/************************************************/
    	/* クラスBackprのコンストラクタ                 */
    	/*      name_c : 制御データ用入力ファイル名     */
    	/*      name_s : ネットワーク記述入力ファイル名 */
    	/************************************************/
    	public Backpr(String name_c, String name_s) : base(name_c)
    	{
    		char[] charSep = new char[] {' '};
    		String[] lines = File.ReadAllLines(name_s);
    				//
    				// 乱数の初期化
    				//
    		rn  = new Random();   // 乱数の初期設定
    				//
    				// 入力ユニット,出力ユニットの数,関数タイプ
    				//
    		String[] str = lines[0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		noiu         = int.Parse(str[1]);
    		noou         = int.Parse(str[3]);
    		f_type       = int.Parse(str[5]);
    		nou          = noiu + noou;   // 入力ユニットと出力ユニットの和
    				//
    				// 隠れユニットの階層数と各階層のユニット数
    				//
    		str         = lines[1].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		nolvl       = int.Parse(str[1]);
    		nohu        = new int [nolvl+1];
    		nohu[nolvl] = noou;   // 出力ユニットの数
    
    		if (nolvl > 0) {
    			for (int i1 = 0; i1 < nolvl; i1++) {
    				nohu[i1]  = int.Parse(str[i1+3]);
    				nou      += nohu[i1];
    			}
    		}
    				//
    				// 領域の確保
    				//
    		con = new sbyte [nou][];
    		for (int i1 = 0; i1 < nou; i1++) {
    			con[i1] = new sbyte [nou];
    			for (int i2 = 0; i2 < nou; i2++)
    				con[i1][i2] =  (i1 == i2) ? (sbyte)-1 : (sbyte)0;
    		}
    
    		w = new double [nou][];
    		for (int i1 = 0; i1 < nou; i1++) {
    			w[i1] = new double [nou];
    			for (int i2 = 0; i2 < nou; i2++)
    				w[i1][i2] = 0.0;
    		}
    
    		dp    = new double [nou];
    		op    = new double [nou];
    		theta = new double [nou];
    
    		for (int i1 = 0; i1 < nou; i1++)
    			theta[i1] = 0.2 * rn.NextDouble() - 0.1;
    				//
    				// 各ユニットのバイアスとユニット間の接続関係
    				//
    					// バイアス
    						// バイアスデータの数
    		str    = lines[2].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		int nb = int.Parse(str[1]);
    		if (nb > 0) {
    						// バイアスデータの処理
    			for (int i0 = 0; i0 < nb; i0++) {
    							// ユニット番号
    				str    = lines[i0+6].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    				int k1 = int.Parse(str[0]);
    							// 不適当なユニット番号のチェック
    				if (k1 < 1 || k1 > (nou-noiu)) {
    					Console.WriteLine("***error  ユニット番号 " + k1 + " が不適当");
    					Environment.Exit(1);
    				}
    							// バイアスの与え方
    				k1--;
    				int id      = int.Parse(str[1]);
    				con[k1][k1] = (sbyte)id;
    							// バイアスの初期設定
    				switch (con[k1][k1]) {
    					case -1:
    						double x1 = double.Parse(str[2]);
    						double x2 = double.Parse(str[3]);
    						theta[k1] = (x2 - x1) * rn.NextDouble() + x1;
    						break;
    					case -2:
    						theta[k1] = double.Parse(str[2]);
    						break;
    					case -3:
    						theta[k1] = double.Parse(str[2]);
    						break;
    					default:
    						Console.WriteLine("***error  バイアスの与え方が不適当");
    						Environment.Exit(1);
    						break;
    				}
    			}
    		}
    					// 接続方法
    						// 接続データの数
    		str   = lines[nb+6].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		int n = int.Parse(str[1]);
    
    		if (n > 0) {
    						// 接続データの処理
    			for (int i0 = 0; i0 < n; i0++) {
    							// 接続情報
    				str    = lines[nb+10+i0].Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    				int k1 = int.Parse(str[0]);
    				int k2 = int.Parse(str[1]);
    				int k3 = int.Parse(str[2]);
    				int k4 = int.Parse(str[3]);
    							// 不適切な接続のチェック
    				int sw = 0;
    				if (k1 < 1 || k2 < 1 || k3 < 1 || k4 < 1)
    					sw = 1;
    				else {
    					if (k1 > nou || k2 > nou || k3 > nou || k4 > nou)
    						sw = 1;
    					else {
    						if (k1 > k2 || k3 > k4)
    							sw = 1;
    						else {
    							if (k4 >= k1)
    								sw = 1;
    							else {
    								int l1 = -1;
    								int k  = 0;
    								for (int i1 = nolvl; i1 >= 0 && l1 < 0; i1--) {
    									k += nohu[i1];
    									if (k1 <= k)
    										l1 = i1;
    								}
    								int l2 = -1;
    								k      = 0;
    								for (int i1 = nolvl; i1 >= 0 && l2 < 0; i1--) {
    									k += nohu[i1];
    									if (k4 <= k)
    										l2 = i1;
    								}
    								if (l2 <= l1)
    									sw = 1;
    							}
    						}
    					}
    				}
    
    				if (sw > 0) {
    					Console.WriteLine("***error  ユニット番号が不適当("
                                           + k1 + " " + k2 + " " + k3 + " " + k4 + ")");
    					Environment.Exit(1);
    				}
    							// 重みの初期値の与え方
    				k1--;
    				k2--;
    				k3--;
    				k4--;
    
    				int id    = int.Parse(str[4]);
    				double x1 = 0.0;
    				double x2 = 0.0;
    
    				if (id == 1) {
    					x1 = double.Parse(str[5]);
    					x2 = double.Parse(str[6]);
    				}
    				else {
    					if (id > 1)
    						x1 = double.Parse(str[5]);
    					else {
    						if (id != 0) {
    							Console.WriteLine("***error  接続方法が不適当");
    							Environment.Exit(1);
    						}
    					}
    				}
    							// 重みの初期値の設定
    				for (int i1 = k3; i1 <= k4; i1++) {
    					for (int i2 = k1; i2 <= k2; i2++) {
    						con[i1][i2] = (sbyte)id;
    						switch (id) {
    							case 0:
    								w[i1][i2] = 0.0;
    								break;
    							case 1:
    								w[i1][i2] = (x2 - x1) * rn.NextDouble() + x1;
    								break;
    							case 2:
    								w[i1][i2] = x1;
    								break;
    							case 3:
    								w[i1][i2] = x1;
    								break;
    						}
    					}
    				}
    			}
    		}
    	}
    
    	/******************************************/
    	/* 誤差の計算,及び,重みとバイアスの修正 */
    	/*      ptn[i1] : 出力パターン            */
    	/******************************************/
    	void Err_back(double[] ptn)
    	{
    		for (int i1 = 0; i1 < nou-noiu; i1++) {
    					// 誤差の計算
    			if (i1 < noou) {
    				if (f_type == 0)
    					dp[i1] = (ptn[i1] - op[i1]) * op[i1] * (1.0 - op[i1]);
    				else
    					dp[i1] = 0.5 * (ptn[i1] - op[i1]) * 
                                 (op[i1] - 1.0) * (op[i1] + 1.0);
    			}
    			else {
    				double x1 = 0.0;
    				for (int i2 = 0; i2 < i1; i2++) {
    					if (con[i2][i1] > 0)
    						x1 += dp[i2] * w[i2][i1];
    				}
    				if (f_type == 0)
    					dp[i1] = op[i1] * (1.0 - op[i1]) * x1;
    				else
    					dp[i1] = 0.5 * (op[i1] - 1.0) * (op[i1] + 1.0) * x1;
    			}
    					// 重みの修正
    			for (int i2 = i1+1; i2 < nou; i2++) {
    				if (con[i1][i2] == 1 || con[i1][i2] == 2) {
    					double x1  = eata * dp[i1] * op[i2] + alpha * w[i2][i1];
    					w[i2][i1]  = x1;
    					w[i1][i2] += x1;
    				}
    			}
    					// バイアスの修正
    			if (con[i1][i1] >= -2) {
    				double x1  = eata * dp[i1] + alpha * w[i1][i1];
    				w[i1][i1]  = x1;
    				theta[i1] += x1;
    			}
    		}
    	}
    
    	/********************************************************/
    	/* 与えられた入力パターンに対する各ユニットの出力の計算 */
    	/********************************************************/
    	void Forward()
    	{
    		for (int i1 = nou-noiu-1; i1 >= 0; i1--) {
    
    			double sum = -theta[i1];
    
    			for (int i2 = i1+1; i2 < nou; i2++) {
    				if (con[i1][i2] > 0)
    					sum -= w[i1][i2] * op[i2];
    			}
    
    			op[i1] = (f_type == 0) ? 1.0 / (1.0 + Math.Exp(sum)) :
                                         1.0 - 2.0 / (1.0 + Math.Exp(sum));
    		}
    	}
    
    	/*****************************/
    	/* 学習の実行                */
    	/*      p : 認識パターン     */
    	/*      m_tri : 最大学習回数 */
    	/*****************************/
    	public void Learn(BackData p, int m_tri)
    	{
    				//
    				// エラーチェック
    				//
    		if (noiu != p.noiu || noou != p.noou) {
    			Console.WriteLine("***error  入力または出力ユニットの数が違います");
    			Environment.Exit(1);
    		}
    
    		int k0 = -1;
    		for (int i1 = 0; i1 < m_tri; i1++) {
    				//
    				// パターンを与える順番の決定
    				//
    			if (order == 0) {       // 順番
    				k0++;
    				if (k0 >= p.noip)
    					k0 = 0;
    			}
    			else {                  // ランダム
    				k0 = (int)(rn.NextDouble() * p.noip);
    				if (k0 >= p.noip)
    					k0 = p.noip - 1;
    			}
    				//
    				// 出力ユニットの結果を計算
    				//
    			int k1 = nou - noiu;
    			for (int i2 = 0; i2 < noiu; i2++)
    				op[k1+i2] = p.iptn[k0][i2];
    
    			Forward();
    				//
    				// 重みとバイアスの修正
    				//
    			Err_back(p.optn[k0]);
    		}
    	}
    
    	/***********************************************/
    	/* 与えられた対象の認識と出力                  */
    	/*      p : 認識パターン                       */
    	/*      pr : =0 : 出力を行わない               */
    	/*           =1 : 出力を行う                   */
    	/*           =2 : 出力を行う(未学習パターン) */
    	/*      tri : 現在の学習回数                   */
    	/*      return : 誤って認識したパターンの数    */
    	/***********************************************/
    	public int Recog(BackData p, int pr, int tri)
    	{
    				//
    				// ファイルのオープン
    				//
    		StreamWriter OUT = null;
    		if (p_type < 0 && pr > 0) {
    			OUT = new StreamWriter(o_file, true); 
    			if (pr == 1) {
    				OUT.WriteLine("***学習パターン***");
    				OUT.WriteLine();
    			}
    			else {
    				OUT.WriteLine();
    				OUT.WriteLine("***未学習パターン***");
    				OUT.WriteLine();
    			}
    		}
    				//
    				// 各パターンに対する出力
    				//
    		int No = 0;
    
    		for (int i1 = 0; i1 < p.noip; i1++) {
    					// 入力パターンの設定
    			int k1 = nou - noiu;
    			for (int i2 = 0; i2 < noiu; i2++)
    				op[k1+i2] = p.iptn[i1][i2];
    					// 出力の計算
    			Forward();
    					// 結果の表示
    			if (p_type != 0 && pr > 0) {
    
    				Console.Write("入力パターン" + (i1+1) + "   ");
    				for (int i2 = 0; i2 < noiu; i2++) {
    					Console.Write(" " + op[k1+i2]);
    					if (i2 == noiu-1)
    						Console.WriteLine();
    					else {
    						if(((i2+1) % 10) == 0) {
    							Console.WriteLine();
    							Console.Write("                   ");
    						}
    					}
    				}
    
    				Console.WriteLine();
    				Console.Write("    出力パターン(理想)  ");
    				for (int i2 = 0; i2 < noou; i2++) {
    					Console.Write(" " + p.optn[i1][i2]);
    					if (i2 == noou-1)
    						Console.WriteLine();
    					else {
    						if(((i2+1) % 5) == 0) {
    							Console.WriteLine();
    							Console.Write("                        ");
    						}
    					}
    				}
    			}
    
    			int sw = 0;
    			if (p_type != 0 && pr > 0)
    				Console.Write("                (実際)  ");
    			for (int i2 = 0; i2 < noou; i2++) {
    				if (p_type != 0 && pr > 0) {
    					Console.Write(" " + op[i2]);
    					if (i2 == noou-1)
    						Console.WriteLine();
    					else {
    						if(((i2+1) % 5) == 0) {
    							Console.WriteLine();
    							Console.Write("                        ");
    						}
    					}
    				}
    				if (Math.Abs(op[i2]-p.optn[i1][i2]) > eps)
    					sw = 1;
    			}
    
    			if (sw > 0)
    				No++;
    
    			if (p_type < 0 && pr > 0) {
    
    				OUT.Write("入力パターン" + (i1+1) + "   ");
    				for (int i2 = 0; i2 < noiu; i2++) {
    					OUT.Write(" " + op[k1+i2]);
    					if (i2 == noiu-1)
    						OUT.WriteLine();
    					else {
    						if(((i2+1) % 10) == 0) {
    							OUT.WriteLine();
    							OUT.Write("                   ");
    						}
    					}
    				}
    
    				OUT.WriteLine();
    				OUT.Write("    出力パターン(理想)  ");
    				for (int i2 = 0; i2 < noou; i2++) {
    					OUT.Write(" " + p.optn[i1][i2]);
    					if (i2 == noou-1)
    						OUT.WriteLine();
    					else {
    						if(((i2+1) % 5) == 0) {
    							OUT.WriteLine();
    							OUT.Write("                        ");
    						}
    					}
    				}
    
    				OUT.Write("                (実際)  ");
    				for (int i2 = 0; i2 < noou; i2++) {
    					OUT.Write(" " + op[i2]);
    					if (i2 == noou-1)
    						OUT.WriteLine();
    					else {
    						if(((i2+1) % 5) == 0) {
    							OUT.WriteLine();
    							OUT.Write("                        ");
    						}
    					}
    				}
    			}
    
    			if (p_type != 0 && pr > 0)
    				Console.ReadLine();
    		}
    				//
    				// 重みの出力
    				//
    		int ln;
    		if ((p_type < -1 || p_type > 1) && pr == 1) {
    
    			Console.WriteLine("    重み");
    			for (int i1 = 0; i1 < nou-noiu; i1++) {
    				Console.Write("      to " + (i1+1) + " from  ");
    				ln = -1;
    				for (int i2 = 0; i2 < nou; i2++) {
    					if (con[i1][i2] > 0) {
    						if (ln <= 0) {
    							if (ln < 0)
    								ln = 0;
    							else {
    								Console.WriteLine();
    								Console.Write("                   ");
    							}
    						}
    						Console.Write(" " + (i2+1) + " " + w[i1][i2]);
    						ln += 1;
    						if (ln == 4)
    							ln = 0;
    					}
    				}
    
    				Console.WriteLine();
    			}
    
    			Console.WriteLine();
    			Console.Write("    バイアス  ");
    			ln = 0;
    			for (int i1 = 0; i1 < nou-noiu; i1++) {
    				Console.Write(" " + (i1+1) + " " + theta[i1]);
    				ln += 1;
    				if (ln == 4 && i1 != nou-noiu-1) {
    					ln = 0;
    					Console.WriteLine();
    					Console.Write("              ");
    				}
    			}
    
    			if (ln != 0)
    				Console.WriteLine();
    
    			Console.ReadLine();
    		}
    
    		if (p_type < 0 && pr == 1) {
    
    			OUT.WriteLine("    重み");
    			for (int i1 = 0; i1 < nou-noiu; i1++) {
    				OUT.Write("      to " + (i1+1) + " from  ");
    				ln = -1;
    				for (int i2 = 0; i2 < nou; i2++) {
    					if (con[i1][i2] > 0) {
    						if (ln <= 0) {
    							if (ln < 0)
    								ln = 0;
    							else {
    								OUT.WriteLine();
    								OUT.Write("                   ");
    							}
    						}
    						OUT.Write(" " + (i2+1) + " " + w[i1][i2]);
    						ln += 1;
    						if (ln == 4)
    							ln = 0;
    					}
    				}
    
    				OUT.WriteLine();
    			}
    
    			OUT.WriteLine();
    			OUT.Write("    バイアス  ");
    			ln = 0;
    			for (int i1 = 0; i1 < nou-noiu; i1++) {
    				OUT.Write(" " + (i1+1) + " " + theta[i1]);
    				ln += 1;
    				if (ln == 4 && i1 != nou-noiu-1) {
    					ln = 0;
    					OUT.WriteLine();
    					OUT.Write("\n              ");
    				}
    			}
    
    			if (ln != 0)
    				OUT.WriteLine();
    		}
    
    		if (p_type < 0 && pr > 0)
    			OUT.Close();
    
    		return No;
    	}
    }
    
    /*
    ------------------------制御データ----------------
    誤差 0.1 出力 -2 出力ファイル kekka
    順番 0 η 0.5 α 0.8
    画面表示(円の大きさ,フォントサイズ,幅,高さ) 20 20 400 300
    
    ------------------------構造データ----------------
    入力ユニット数 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
    */
    			

  8. VB

    '**************************'
    ' back propagation model   '
    '      coded by Y.Suganuma '
    '**************************'
    Imports System.IO
    Imports System.Text.RegularExpressions
    
    Module Test
    
    	Sub Main(args() As String)
    
    					' エラー
    		If args.Length <> 2
    			Console.WriteLine("***error   入力データファイル名を指定して下さい")
    			Environment.Exit(1)
    
    		Else
    					' ネットワークの定義
    			Dim net As Backpr = new Backpr(args(0), args(1))
    					' 学習パターン等の入力
    			Console.Write("学習回数は? ")
    			Dim m_tri As Integer = Integer.Parse(Console.ReadLine())   ' 最大学習回数
    			Console.Write("何回毎に収束を確認しますか? ")
    			Dim conv As Integer = Integer.Parse(Console.ReadLine())   ' 収束確認回数
    
    			Console.Write("学習パターンのファイル名は? ")
    			Dim f_name As String = Console.ReadLine()
    
    			Dim dt1 As BackData = new BackData(f_name)
    					' 学習
    			Dim max As Integer = 0
    			Dim no As Integer  = 1
    			Do While max < m_tri and no > 0
    
    				Dim tri As Integer
    				If (max + conv) < m_tri
    					tri = conv
    				Else
    					tri = m_tri - max
    				End If
    				max += tri
    
    				net.Learn(dt1, tri)   ' 学習
    
    				no = net.Recog(dt1, 0, max)   ' 学習対象の認識
    
    				Console.WriteLine("   回数 " & max & " 誤って認識したパターン数 " & no)
    			Loop
    
    			no = net.Recog(dt1, 1, max)   ' 学習対象の認識と出力
    					' 未学習パターンの認識
    			Console.Write("未学習パターンの認識を行いますか?(=1:行う,=0:行わない) ")
    			Dim sw As Integer = Integer.Parse(Console.ReadLine())
    
    			If sw > 0
    
    				Console.Write("未学習パターンのファイル名は? ")
    				f_name = Console.ReadLine()
    
    				Dim dt2 As BackData = new BackData(f_name)
    
    				no = net.Recog(dt2, 2, max)   ' 未学習対象の認識と出力
    			End If
    		End If
    
    	End Sub
    
    	'****************************************************'
    	' バックプロパゲーションの制御(クラス BackControl) '
    	'****************************************************'
    	Class BackControl
    
    		Protected alpha As Double   '重み及びバイアス修正パラメータ
    		Protected eata As Double   '重み及びバイアス修正パラメータ
    		Protected eps As Double   ' 許容誤差
    		Protected order As Integer   ' 入力パターンの与え方(=0:順番,=1:ランダム)
    		Protected p_type As Integer   ' 出力先・方法の指定
    	                                  '   =0 : 誤って認識した数だけ出力
    	                                  '   =1 : 認識結果を出力
    	                                  '   =2 : 認識結果と重みを出力
    	                                  '  (負の時は,認識結果と重みをファイルへも出力)
    		Protected o_file As String   ' 出力ファイル名
    
    		'***********************************'
    		' クラスBackControlのコンストラクタ '
    		'      name : 入力データファイル名  '
    		'***********************************'
    		Public Sub New(name As String)
    
    			Dim inp As StreamReader = New StreamReader(name)
    			Dim MS As Regex         = New Regex("\s+") 
    			Dim str() As String     = MS.Split(inp.ReadLine().Trim())
    			eps                     = Double.Parse(str(1))
    			p_type                  = Integer.Parse(str(3))
    			If p_type < 0
    				o_file = str(5)
    			End If
    
    			str   = MS.Split(inp.ReadLine().Trim())
    			order = Integer.Parse(str(1))
    			eata  = Double.Parse(str(3))
    			alpha = Double.Parse(str(5))
    
    			inp.Close()
    
    		End Sub
    
    	End Class
    
    	'***************************************************'
    	' バックプロパゲーションのデータ(クラス BackData) '
    	'***************************************************'
    	Class BackData
    
    		Public noiu As Integer   ' 入力ユニットの数
    		Public noou As Integer   ' 出力ユニットの数
    		Public noip As Integer   ' 入力パターンの数
    		Public iptn(,) As Double   ' iptn(i,j) : (i+1)番目の入力パターンの(j+1)番目の
    	                               '              入力ユニットの入力値
    	                               '                i=0,noip-1  j=0,noiu-1
    		Public optn(,) As Double   ' optn(i,j) : (i+1)番目の入力パターンに対する(j+1)
    	                               '              番目の出力ユニットの目標出力値
    	                               '                i=0,noip-1  j=0,noou-1
    	
    		'**********************************'
    		' クラスBackDataのコンストラクタ   '
    		'      name : 入力データファイル名 '
    		'**********************************'
    		Public Sub New(name As String)
    
    			Dim MS As Regex         = New Regex("\s+") 
    			Dim inp As StreamReader = New StreamReader(name)
    					'
    					' 入力パターン数等
    					'
    			Dim str() As String = MS.Split(inp.ReadLine().Trim())
    			noip                = Integer.Parse(str(1))
    			noiu                = Integer.Parse(str(3))
    			noou                = Integer.Parse(str(5))
    					'
    					' 領域の確保
    					'
    			ReDim iptn(noip,noiu)
    			ReDim optn(noip,noou)
    					'
    					' 入力パターン及び各入力パターンに対する出力パターンの入力
    					'
    			For i1 As Integer = 0 To noip-1
    				str = MS.Split(inp.ReadLine().Trim())
    				For i2 As Integer = 0 To noiu-1
    					iptn(i1,i2) = Double.Parse(str(i2+1))
    				Next
    				str = MS.Split(inp.ReadLine().Trim())
    				For i2 As Integer = 0 To noou-1
    					optn(i1,i2) = Double.Parse(str(i2+1))
    				Next
    			Next
    
    			inp.Close()
    
    		End Sub
    
    	End Class
    
    	'*****************************************'
    	' バックプロパゲーション(クラス Backpr) '
    	'*****************************************'
    	Class Backpr
    
    		Inherits BackControl   ' クラス BackControl を継承
    		Private con(,) As Integer   ' バイアスの与え方,及び,接続方法
    	                                '   (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
    		Private f_type As Integer   ' シグモイド関数のタイプ
    	                                '   0 : (0,1)
    	                                '   1 : (-1,1))
    		Private noiu As Integer   ' 入力ユニットの数
    		Private noou As Integer   ' 出力ユニットの数
    		Private nohu() As Integer   ' nohu(i) : レベル(i+1)の隠れ層のユニット数(隠れ層
    	                                '           には下から順に番号が付けられ,出力層はレ
    	                                '           ベル(nolvl+1)の隠れ層とも見做される)
    	                                '             i=0,nolvl
    		Private nolvl As Integer   ' 隠れユニットの階層数
    		Private nou As Integer   ' 入力,出力,及び,隠れ層の各ユニットの数の和(各ユニ
    	                             ' ットには最も上の出力ユニットから,隠れ層の各ユニット,
    	                             ' 及び,入力ユニットに至る一連のユニット番号が付けられ
    	                             ' る)
    		Private dp() As Double   ' dp(i) : ユニット(i+1)の誤差  i=0,nou-1
    		Private op() As Double   ' op(i) : ユニット(i+1)の出力  i=0,nou-1
    		Private theta() As Double   'theta(i) : ユニット(i+1)のバイアス  i=0,nou
    		Private w(,) As Double   ' 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
    		 Private rn As Random   ' 乱数
    	
    		'**********************************************'
    		' クラスBackprのコンストラクタ                 '
    		'      name_c : 制御データ用入力ファイル名     '
    		'      name_s : ネットワーク記述入力ファイル名 '
    		'**********************************************'
    		Public Sub New(name_c As String, name_s As String)
    
    			MyBase.new(name_c)   ' 基底クラスのコンストラクタ
    			Dim MS As Regex         = New Regex("\s+") 
    			Dim inp As StreamReader = New StreamReader(name_s)
    					'
    					' 乱数の初期化
    					'
    			rn  = new Random()   ' 乱数の初期設定
    					'
    					' 入力ユニット,出力ユニットの数,関数タイプ
    					'
    			Dim str() As String = MS.Split(inp.ReadLine().Trim())
    			noiu                = Integer.Parse(str(1))
    			noou                = Integer.Parse(str(3))
    			f_type              = Integer.Parse(str(5))
    			nou                 = noiu + noou   ' 入力ユニットと出力ユニットの和
    					'
    					' 隠れユニットの階層数と各階層のユニット数
    					'
    			str   = MS.Split(inp.ReadLine().Trim())
    			nolvl = Integer.Parse(str(1))
    			ReDim nohu(nolvl+1)
    			nohu(nolvl) = noou   ' 出力ユニットの数
    	
    			If nolvl > 0
    				For i1 As Integer = 0 To nolvl-1
    					nohu(i1)  = Integer.Parse(str(i1+3))
    					nou      += nohu(i1)
    				Next
    			End If
    					'
    					' 領域の確保
    					'
    			ReDim con(nou,nou)
    			For i1 As Integer = 0 To nou-1
    				For i2 As Integer = 0 To nou-1
    					If i1 = i2
    						con(i1,i2) =  -1
    					Else
    						con(i1,i2) = 0
    					End If
    				Next
    			Next
    	
    			ReDim w(nou,nou)
    			For i1 As Integer = 0 To nou-1
    				For i2 As Integer = 0 To nou-1
    					w(i1,i2) = 0.0
    				Next
    			Next
    	
    			ReDim dp(nou)
    			ReDim op(nou)
    			ReDim theta(nou)
    	
    			For i1 As Integer = 0 To nou-1
    				theta(i1) = 0.2 * rn.NextDouble() - 0.1
    			Next
    					'
    					' 各ユニットのバイアスとユニット間の接続関係
    					'
    						' バイアス
    							' バイアスデータの数
    			str               = MS.Split(inp.ReadLine().Trim())
    			Dim nb As Integer = Integer.Parse(str(1))
    			inp.ReadLine()
    			inp.ReadLine()
    			inp.ReadLine()
    
    			If nb > 0
    							' バイアスデータの処理
    				For i0 As Integer = 0 To nb-1
    								' ユニット番号
    					str               = MS.Split(inp.ReadLine().Trim())
    					Dim k1 As Integer = Integer.Parse(str(0))
    								' 不適当なユニット番号のチェック
    					If k1 < 1 or k1 > (nou-noiu)
    						Console.WriteLine("***error  ユニット番号 " & k1 & " が不適当")
    						Environment.Exit(1)
    					End If
    								' バイアスの与え方
    					k1 -= 1
    					Dim id As Integer = Integer.Parse(str(1))
    					con(k1,k1)        = id
    								' バイアスの初期設定
    					Select Case con(k1,k1)
    						Case -1
    							Dim x1 As Double = Double.Parse(str(2))
    							Dim x2 As Double = Double.Parse(str(3))
    							theta(k1) = (x2 - x1) * rn.NextDouble() + x1
    						Case -2
    							theta(k1) = Double.Parse(str(2))
    						Case -3
    							theta(k1) = Double.Parse(str(2))
    						Case Else
    							Console.WriteLine("***error  バイアスの与え方が不適当")
    							Environment.Exit(1)
    					End Select
    				Next
    			End If
    						' 接続方法
    							' 接続データの数
    			str              = MS.Split(inp.ReadLine().Trim())
    			Dim n As Integer = Integer.Parse(str(1))
    			inp.ReadLine()
    			inp.ReadLine()
    			inp.ReadLine()
    	
    			If n > 0
    							' 接続データの処理
    				For i0 As Integer = 0 To n-1
    								' 接続情報
    					str               = MS.Split(inp.ReadLine().Trim())
    					Dim k1 As Integer = Integer.Parse(str(0))
    					Dim k2 As Integer = Integer.Parse(str(1))
    					Dim k3 As Integer = Integer.Parse(str(2))
    					Dim k4 As Integer = Integer.Parse(str(3))
    								' 不適切な接続のチェック
    					Dim sw As Integer = 0
    					If k1 < 1 or k2 < 1 or k3 < 1 or k4 < 1
    						sw = 1
    					Else
    						If k1 > nou or k2 > nou or k3 > nou or k4 > nou
    							sw = 1
    						Else
    							If k1 > k2 or k3 > k4
    								sw = 1
    							Else
    								If k4 >= k1
    									sw = 1
    								Else
    									Dim l1 As Integer  = -1
    									Dim k As Integer   = 0
    									Dim i1t As Integer = nolvl
    									Do While i1t >= 0 and l1 < 0
    										k += nohu(i1t)
    										If k1 <= k
    											l1 = i1t
    										End If
    										i1t -= 1
    									Loop
    									Dim l2 As Integer = -1
    									k                 = 0
    									i1t               = nolvl
    									Do While i1t >= 0 and l2 < 0
    										k += nohu(i1t)
    										If k4 <= k
    											l2 = i1t
    										End If
    										i1t -= 1
    									Loop
    									If l2 <= l1
    										sw = 1
    									End If
    								End If
    							End If
    						End If
    					End If
    	
    					If sw > 0
    						Console.WriteLine("***error  ユニット番号が不適当(" &
    						                   k1 & " " & k2 & " " & k3 & " " & k4 & ")")
    						Environment.Exit(1)
    					End If
    								' 重みの初期値の与え方
    					k1 -= 1
    					k2 -= 1
    					k3 -= 1
    					k4 -= 1
    	
    					Dim id As Integer = Integer.Parse(str(4))
    					Dim x1 As Double  = 0.0
    					Dim x2 As Double  = 0.0
    	
    					If id = 1
    						x1 = Double.Parse(str(5))
    						x2 = Double.Parse(str(6))
    					Else
    						If (id > 1)
    							x1 = Double.Parse(str(5))
    						Else
    							If id <> 0
    								Console.WriteLine("***error  接続方法が不適当")
    								Environment.Exit(1)
    							End If
    						End If
    					End If
    								' 重みの初期値の設定
    					For i1 As Integer = k3 To k4
    						For i2 As Integer = k1 To k2
    							con(i1,i2) = id
    							Select Case id
    								Case 0
    									w(i1,i2) = 0.0
    								Case 1
    									w(i1,i2) = (x2 - x1) * rn.NextDouble() + x1
    								Case 2
    									w(i1,i2) = x1
    								Case 3
    									w(i1,i2) = x1
    							End Select
    						Next
    					Next
    				Next
    			End If
    
    			inp.Close()
    
    		End Sub
    
    		'***************************'
    		' 学習の実行                '
    		'      p : 認識パターン     '
    		'      m_tri : 最大学習回数 '
    		'***************************'
    		Public Sub Learn(p As BackData, m_tri As Integer)
    					'
    					' エラーチェック
    					'
    			If noiu <> p.noiu or noou <> p.noou
    				Console.WriteLine("***error  入力または出力ユニットの数が違います")
    				Environment.Exit(1)
    			End If
    	
    			Dim k0 As Integer = -1
    			For i1 As Integer = 0 To m_tri-1
    					'
    					' パターンを与える順番の決定
    					'
    				If order = 0   ' 順番
    					k0 += 1
    					If k0 >= p.noip
    						k0 = 0
    					End If
    				Else   ' ランダム
    					k0 = Math.Floor(rn.NextDouble() * p.noip)
    					If k0 >= p.noip
    						k0 = p.noip - 1
    					End If
    				End If
    					'
    					' 出力ユニットの結果を計算
    					'
    				Dim k1 As Integer = nou - noiu
    				For i2 As Integer = 0 To noiu-1
    					op(k1+i2) = p.iptn(k0,i2)
    				Next
    	
    				Forward()
    					'
    					' 重みとバイアスの修正
    					'
    				Dim ptn(noou) As Double
    				For i2 As Integer = 0 To noou-1
    					ptn(i2) = p.optn(k0,i2)
    				Next
    				Err_back(ptn)
    			Next
    
    		End Sub
    
    		'******************************************************'
    		' 与えられた入力パターンに対する各ユニットの出力の計算 '
    		'******************************************************'
    		Sub Forward()
    
    			For i1 As Integer = nou-noiu-1 To 0 Step -1
    	
    				Dim sum As Double = -theta(i1)
    	
    				For i2 As Integer = i1+1 To nou-1
    					If con(i1,i2) > 0
    						sum -= w(i1,i2) * op(i2)
    					End If
    				Next
    	
    				If f_type = 0
    					op(i1) = 1.0 / (1.0 + Math.Exp(sum)) :
    				Else
    					op(i1) = 1.0 - 2.0 / (1.0 + Math.Exp(sum))
    				End If
    			Next
    
    		End Sub
    
    		'****************************************'
    		' 誤差の計算,及び,重みとバイアスの修正 '
    		'      ptn(i1) : 出力パターン            '
    		'****************************************'
    		Sub Err_back(ptn() As Double)
    
    			For i1 As Integer = 0 To nou-noiu-1
    						' 誤差の計算
    				If i1 < noou
    					If f_type = 0
    						dp(i1) = (ptn(i1) - op(i1)) * op(i1) * (1.0 - op(i1))
    					Else
    						dp(i1) = 0.5 * (ptn(i1) - op(i1)) * (op(i1) - 1.0) * (op(i1) + 1.0)
    					End If
    				Else
    					Dim x1 As Double = 0.0
    					For i2 As Integer = 0 To i1-1
    						If con(i2,i1) > 0
    							x1 += dp(i2) * w(i2,i1)
    						End If
    					Next
    					If f_type = 0
    						dp(i1) = op(i1) * (1.0 - op(i1)) * x1
    					Else
    						dp(i1) = 0.5 * (op(i1) - 1.0) * (op(i1) + 1.0) * x1
    					End If
    				End If
    						' 重みの修正
    				For i2 As Integer = i1+1 To nou-1
    					If con(i1,i2) = 1 or con(i1,i2) = 2
    						Dim x1 As Double = eata * dp(i1) * op(i2) + alpha * w(i2,i1)
    						w(i2,i1)  = x1
    						w(i1,i2) += x1
    					End If
    				Next
    						' バイアスの修正
    				If con(i1,i1) >= -2
    					Dim x1 As Double = eata * dp(i1) + alpha * w(i1,i1)
    					w(i1,i1)   = x1
    					theta(i1) += x1
    				End If
    			Next
    
    		End Sub
    
    		'*********************************************'
    		' 与えられた対象の認識と出力                  '
    		'      p : 認識パターン                       '
    		'      pr : =0 : 出力を行わない               '
    		'           =1 : 出力を行う                   '
    		'           =2 : 出力を行う(未学習パターン) '
    		'      tri : 現在の学習回数                   '
    		'      return : 誤って認識したパターンの数    '
    		'*********************************************'
    		Public Function Recog(p As BackData, pr As Integer, tri As Integer)
    					'
    					' ファイルのオープン
    					'
    			Dim Out As StreamWriter
    
    			If p_type < 0 and pr > 0
    				OUT = new StreamWriter(o_file, true) 
    				If pr = 1
    					OUT.WriteLine("***学習パターン***")
    					OUT.WriteLine()
    				Else
    					OUT.WriteLine()
    					OUT.WriteLine("***未学習パターン***")
    					OUT.WriteLine()
    				End If
    			End If
    					'
    					' 各パターンに対する出力
    					'
    			Dim No As Integer = 0
    	
    			For i1 As Integer = 0 To p.noip-1
    						' 入力パターンの設定
    				Dim k1 As Integer = nou - noiu
    				For i2 As Integer = 0 To noiu-1
    					op(k1+i2) = p.iptn(i1,i2)
    				Next
    						' 出力の計算
    				Forward()
    						' 結果の表示
    				If p_type <> 0 and pr > 0
    	
    					Console.Write("入力パターン" & (i1+1) & "   ")
    					For i2 As Integer = 0 To noiu-1
    						Console.Write(" " & op(k1+i2))
    						If i2 = noiu-1
    							Console.WriteLine()
    						Else
    							If ((i2+1) Mod 10) = 0
    								Console.WriteLine()
    								Console.Write("                   ")
    							End If
    						End If
    					Next
    	
    					Console.WriteLine()
    					Console.Write("    出力パターン(理想)  ")
    					For i2 As Integer = 0 To noou-1
    						Console.Write(" " & p.optn(i1,i2))
    						If i2 = noou-1
    							Console.WriteLine()
    						Else
    							If((i2+1) Mod 5) = 0
    								Console.WriteLine()
    								Console.Write("                        ")
    							End If
    						End If
    					Next
    				End If
    	
    				Dim sw As Integer = 0
    				If p_type <> 0 and pr > 0
    					Console.Write("                (実際)  ")
    				End If
    				For i2 As Integer = 0 To noou-1
    					If p_type <> 0 and pr > 0
    						Console.Write(" " & op(i2))
    						If i2 = noou-1
    							Console.WriteLine()
    						Else
    							If ((i2+1) Mod 5) = 0
    								Console.WriteLine()
    								Console.Write("                        ")
    							End If
    						End If
    					End If
    					If Math.Abs(op(i2)-p.optn(i1,i2)) > eps
    						sw = 1
    					End If
    				Next
    	
    				If sw > 0
    					No += 1
    				End If
    	
    				If p_type < 0 and pr > 0
    	
    					OUT.Write("入力パターン" & (i1+1) & "   ")
    					For i2 As Integer = 0 To noiu-1
    						OUT.Write(" " & op(k1+i2))
    						If i2 = noiu-1
    							OUT.WriteLine()
    						Else
    							If ((i2+1) Mod 10) = 0
    								OUT.WriteLine()
    								OUT.Write("                   ")
    							End If
    						End If
    					Next
    	
    					OUT.WriteLine()
    					OUT.Write("    出力パターン(理想)  ")
    					For i2 As Integer = 0 To noou-1
    						OUT.Write(" " & p.optn(i1,i2))
    						If i2 = noou-1
    							OUT.WriteLine()
    						Else
    							If ((i2+1) Mod 5) = 0
    								OUT.WriteLine()
    								OUT.Write("                        ")
    							End If
    						End If
    					Next
    	
    					OUT.Write("                (実際)  ")
    					For i2 As Integer = 0 To noou-1
    						OUT.Write(" " & op(i2))
    						If i2 = noou-1
    							OUT.WriteLine()
    						Else
    							If ((i2+1) Mod 5) = 0
    								OUT.WriteLine()
    								OUT.Write("                        ")
    							End If
    						End If
    					Next
    				End If
    	
    				If p_type <> 0 and pr > 0
    					Console.ReadLine()
    				End If
    			Next
    					'
    					' 重みの出力
    					'
    			Dim ln As Integer
    			If (p_type < -1 or p_type > 1) and pr = 1
    	
    				Console.WriteLine("    重み")
    				For i1 As Integer = 0 To nou-noiu-1
    					Console.Write("      to " & (i1+1) & " from  ")
    					ln = -1
    					For i2 As Integer = 0 To nou-1
    						If con(i1,i2) > 0
    							If ln <= 0
    								If ln < 0
    									ln = 0
    								Else
    									Console.WriteLine()
    									Console.Write("                   ")
    								End If
    							End If
    							Console.Write(" " & (i2+1) & " " & w(i1,i2))
    							ln += 1
    							If ln = 4
    								ln = 0
    							End If
    						End If
    					Next
    	
    					Console.WriteLine()
    				Next
    	
    				Console.WriteLine()
    				Console.Write("    バイアス  ")
    				ln = 0
    				For i1 As Integer = 0 To nou-noiu-1
    					Console.Write(" " & (i1+1) & " " & theta(i1))
    					ln += 1
    					If ln = 4 and i1 <> nou-noiu-1
    						ln = 0
    						Console.WriteLine()
    						Console.Write("              ")
    					End If
    				Next
    	
    				If ln <> 0
    					Console.WriteLine()
    				End If
    	
    				Console.ReadLine()
    			End If
    	
    			If p_type < 0 and pr = 1
    	
    				OUT.WriteLine("    重み")
    				For i1 As Integer = 0 To nou-noiu-1
    					OUT.Write("      to " & (i1+1) & " from  ")
    					ln = -1
    					For i2 As Integer = 0 To nou-1
    						If con(i1,i2) > 0
    							If ln <= 0
    								If ln < 0
    									ln = 0
    								Else
    									OUT.WriteLine()
    									OUT.Write("                   ")
    								End If
    							End If
    							OUT.Write(" " & (i2+1) & " " & w(i1,i2))
    							ln += 1
    							If ln = 4
    								ln = 0
    							End If
    						End If
    					Next
    	
    					OUT.WriteLine()
    				Next
    	
    				OUT.WriteLine()
    				OUT.Write("    バイアス  ")
    				ln = 0
    				For i1 As Integer = 0 To nou-noiu-1
    					OUT.Write(" " & (i1+1) & " " & theta(i1))
    					ln += 1
    					If ln = 4 and i1 <> nou-noiu-1
    						ln = 0
    						OUT.WriteLine()
    						OUT.WriteLine()
    						OUT.Write("              ")
    					End If
    				Next
    	
    				If ln <> 0
    					OUT.WriteLine()
    				End If
    			End If
    	
    			If p_type < 0 and pr > 0
    				OUT.Close()
    			End If
    	
    			Return No
    
    		End Function
    
    	End Class
    
    End Module
    
    /*
    ------------------------制御データ----------------
    誤差 0.1 出力 -2 出力ファイル kekka
    順番 0 η 0.5 α 0.8
    画面表示(円の大きさ,フォントサイズ,幅,高さ) 20 20 400 300
    
    ------------------------構造データ----------------
    入力ユニット数 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
    */
    			

静岡理工科大学 菅沼ホーム 目次 索引