------------------------制御データ---------------- 誤差 0.1 出力 -2 出力ファイル kekka 順番 0 η 0.5 α 0.8 乱数 123 画面表示(円の大きさ,フォントサイズ,幅,高さ) 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 -----------------------プログラム------------------ /****************************/ /* 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 seed; // 乱数の初期値; 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.nextToken(); seed = Integer.parseInt(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(seed); // 乱数の初期設定 /* 入力ユニット,出力ユニットの数,関数タイプ */ 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; 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 乱数 123 画面表示(円の大きさ,フォントサイズ,幅,高さ) 20 20 400 300
入力ユニット数 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
パターンの数 4 入力ユニット数 2 出力ユニット数 1 入力1 0 0 出力1 0 入力2 0 1 出力2 1 入力3 1 0 出力3 1 入力4 1 1 出力4 0
回数 500 誤って認識したパターン数 4 回数 1000 誤って認識したパターン数 4 回数 1500 誤って認識したパターン数 4 回数 2000 誤って認識したパターン数 4 回数 2500 誤って認識したパターン数 4 回数 3000 誤って認識したパターン数 3 回数 3500 誤って認識したパターン数 0
入力パターン 1 0.00 0.00 出力パターン(理想) 0.000 (実際) 0.060 入力パターン 2 0.00 1.00 出力パターン(理想) 1.000 (実際) 0.911 ・・・・・・ 重み to 1 from 2 -10.700 3 -4.675 4 -4.675 to 2 from 3 -6.825 4 -6.827 バイアス 1 7.139 2 2.501