ダウンロード サンプルファイル (9.0 KB)
プログラム
import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class Back extends Applet implements MouseListener,MouseMotionListener,ActionListener{ Button button1,button2,button3,button4; int X0=10,X1=125; int Y0=55,Y1=70,Y2=160,Y3=240,Y4=305; int RX0=30,RX1=60,RX2=210,RX3=260; int RY0=225,RY1=240; int WIDTH=7; //入力データの幅 int HEIGHT=11; //入力データの高さ int INPUT=WIDTH*HEIGHT; //入力層の数(入力データ数) int HIDDEN=16; //隠れ層の数 int PATTERN=10; //パターンの種類 int OUTPUT=PATTERN; //出力層の数(出力データ数) int OUTER_CYCLES=200; //外部サイクルの回数 int INNER_CYCLES=200; //内部サイクルの回数 float ALPHA=1.2f; //学習の加速係数 float BETA=1.2f; //シグモイド曲線の傾斜 int[] sample_in=new int[INPUT]; //学習用入力 int[] written_in=new int[INPUT]; //認識用手書き入力 float[][] weight_ih=new float[INPUT][HIDDEN]; //入力層と隠れ層の //間の重み係数 float[] thresh_h=new float[HIDDEN]; //隠れ層の閾値 float[] hidden_out=new float[HIDDEN]; //隠れ層の出力 float[][] weight_ho=new float[HIDDEN][OUTPUT];//隠れ層と出力層の //間の重み係数 float[] thresh_o=new float[OUTPUT]; //出力層の閾値 float[] recog_out=new float[OUTPUT]; //認識出力(出力層の出力) int[] teach=new int[PATTERN]; //教師信号 boolean learning_flag; //「学習モード」フラグ //学習用入力データの基となるパターン int[][] sample_array={{0,0,1,1,1,0,0, //'0' 0,1,0,0,0,1,0, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 0,1,0,0,0,1,0, 0,0,1,1,1,0,0}, {0,0,0,1,0,0,0, //'1' 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0, 0,0,0,1,0,0,0}, //……中略…… {0,1,1,1,1,1,0, //'9' 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 1,0,0,0,0,0,1, 0,1,1,1,1,1,1, 0,0,0,0,0,0,1, 0,0,0,0,0,0,1, 0,0,0,0,0,0,1, 0,0,0,0,0,0,1, 1,0,0,0,0,0,1, 0,1,1,1,1,1,0}}; //パターンと出力すべき教師信号の比較表 int[][] teach_array=new int[PATTERN][OUTPUT]; //手書き文字入力用座標 int x_new,y_new,x_old,y_old; public void init(){ //……中略…… //教師信号の設定 for(int q=0;q<PATTERN;q++) for(int k=0;k<OUTPUT;k++){ if(q==k) teach_array[q][k]=1; else teach_array[q][k]=0; } //モードの初期設定 learning_flag=true; } //------------------- ボタン関係のメソッド ------------------ public void actionPerformed(ActionEvent ae){ //……中略…… } //---------- マウス関係のメソッド(手書き文字入力)---------- public void mousePressed(MouseEvent me){ int x=me.getX(); int y=me.getY(); if(!learning_flag && x>=RX1 && x<=RX1+WIDTH*10 && y>=RY1 && y<=RY1+HEIGHT*10){ x_old=me.getX(); y_old=me.getY(); written_in[(y_old-RY1)/10*WIDTH+(x_old-RX1)/10]=1; } } public void mouseClicked(MouseEvent me){} public void mouseEntered(MouseEvent me){} public void mouseExited(MouseEvent me){} public void mouseReleased(MouseEvent me){} public void mouseDragged(MouseEvent me){ int x=me.getX(); int y=me.getY(); if(!learning_flag && x>=RX1 && x<=RX1+WIDTH*10 && y>=RY1 && y<=RY1+HEIGHT*10){ Graphics g=getGraphics(); x_new=me.getX(); y_new=me.getY(); g.drawLine(x_old,y_old,x_new,y_new); x_old=x_new; y_old=y_new; written_in[(y_old-RY1)/10*WIDTH+(x_old-RX1)/10]=1; } } public void mouseMoved(MouseEvent me){} //------- 起動時およびrepaint()で呼び出されるメソッド ------- public void paint(Graphics g){ int i,j,k,p,q,r,x; String string; float outer_error; //外部サイクルエラー累計 float inner_error; //内部サイクルエラー累計 float temp_error; //隠れ層の誤差の累計 //学習モードの背景 if(learning_flag){ g.setColor(new Color(255,255,192)); g.fillRect(5,35,590,460); g.setColor(Color.black); g.drawString("学習モード",500,55); } //認識モードの背景 else{ g.setColor(new Color(192,255,255)); g.fillRect(5,35,590,460); g.setColor(Color.black); g.drawString("認識モード",500,55); } //学習用パターンの表示 g.drawString("使用している学習用パターン",X0,Y0); for(q=0;q<PATTERN;q++){ x=56*q; for(j=0;j<HEIGHT;j++) for(i=0;i<WIDTH;i++){ if(sample_array[q][WIDTH*j+i]==1) g.setColor(Color.red); else g.setColor(Color.cyan); g.fillRect(X0+x+6*i,Y1+6*j,5,5); } } g.setColor(Color.black); //-------------------------------------------------------- //---------------------- 学習モード ---------------------- //-------------------------------------------------------- if(learning_flag){ //閾値と重みの乱数設定 for(j=0;j<HIDDEN;j++){ thresh_h[j]=(float)Math.random()-0.5f; for(i=0;i<INPUT;i++) weight_ih[i][j]=(float)Math.random()-0.5f; } for(k=0;k<OUTPUT;k++){ thresh_o[k]=(float)Math.random()-0.5f; for(j=0;j<HIDDEN;j++) weight_ho[j][k]=(float)Math.random()-0.5f; } //----------------------- 学習 ----------------------- for(p=0;p<OUTER_CYCLES;p++){ //外部サイクル outer_error=0.0f; //外部二乗誤差のクリヤー for(q=0;q<PATTERN;q++){ //パターンの切り替え //パターンに対応した入力と教師信号の設定 sample_in=sample_array[q]; teach=teach_array[q]; for(r=0;r<INNER_CYCLES;r++){ //内部サイクル //順方向演算 forwardNeuralNet(sample_in,recog_out); //逆方向演算(バックプロパゲーション) backwardNeuralNet(); } //内部二乗誤差の計算 inner_error=0.0f; //内部二乗誤差のクリヤー for(k=0;k<OUTPUT;k++) inner_error+=(teach[k]-recog_out[k]) *(teach[k]-recog_out[k]); outer_error+=inner_error; //外部二乗誤差への累加算 } //外部サイクルの回数と外部二乗誤差の表示 g.drawString("実行中の外部サイクルの回数と二乗誤差",X0,Y2); g.setColor(new Color(255,255,192)); g.fillRect(X0+5,Y2+10,200,50); //以前の表示を消去 g.setColor(Color.black); g.drawString("OuterCycles="+String.valueOf(p),X0+10,Y2+25); g.drawString("TotalSquaredError=" +String.valueOf(outer_error),X0+10,Y2+45); } //------------------ 学習結果の確認 ------------------ g.drawString("学習結果の確認",X0,Y3); for(k=0;k<OUTPUT;k++){ g.drawString("Output",X1+45*k,Y3+25); g.drawString(" ["+String.valueOf(k)+"]",X1+5+45*k,Y3+40); } for(q=0;q<PATTERN;q++){ //入力パターンの設定 sample_in=sample_array[q]; //順方向演算 forwardNeuralNet(sample_in,recog_out); //結果の表示 g.setColor(Color.black); g.drawString("TestPattern["+String.valueOf(q)+"]", X0+10,Y4+20*q); for(k=0;k<OUTPUT;k++){ if(recog_out[k]>0.99){ //99% より大は赤で YES g.setColor(Color.red); string="YES"; } else if(recog_out[k]<0.01){ // 1% より小は青で NO g.setColor(Color.blue); string="NO "; } else{ // 1% 以上 99% 以下は黒で? g.setColor(Color.black); string=" ? "; } g.drawString(string,X1+10+45*k,Y4+20*q); } } } //-------------------------------------------------------- //---------------------- 認識モード ---------------------- //-------------------------------------------------------- else{ g.setColor(Color.black); g.drawString("マウスで数字を描いてください",RX0,RY0); g.drawRect(RX1-1,RY1-1,WIDTH*10+2,HEIGHT*10+2); //外枠 g.setColor(Color.gray); for(j=1;j<HEIGHT;j++) g.drawLine(RX1,RY1+10*j,RX1+WIDTH*10,RY1+10*j); for(i=1;i<WIDTH;i++) g.drawLine(RX1+10*i,RY1,RX1+10*i,RY1+HEIGHT*10); for(i=0;i<INPUT;i++) written_in[i]=0; //手書き入力データのクリヤ } } //順方向演算のメソッド public void forwardNeuralNet(int[] input, float[] output){ float[] out=new float[OUTPUT]; float[] hidden=new float[HIDDEN]; //隠れ層出力の計算 for(int j=0;j<HIDDEN;j++){ hidden[j]=-thresh_h[j]; for(int i=0;i<INPUT;i++) hidden[j]+=input[i]*weight_ih[i][j]; hidden_out[j]=sigmoid(hidden[j]); } //出力層出力の計算 for(int k=0;k<OUTPUT;k++){ out[k]=-thresh_o[k]; for(int j=0;j<HIDDEN;j++) out[k]+=hidden_out[j]*weight_ho[j][k]; output[k]=sigmoid(out[k]); } } //逆方向演算のメソッド public void backwardNeuralNet(){ int i,j,k; float[] output_error=new float[OUTPUT]; //出力層の誤差 float[] hidden_error=new float[HIDDEN]; //隠れ層の誤差 float temp_error; //出力層の誤差の計算 for(k=0;k<OUTPUT;k++) output_error[k]=(teach[k]-recog_out[k]) *recog_out[k]*(1.0f-recog_out[k]); //隠れ層の誤差の計算 for(j=0;j<HIDDEN;j++){ temp_error=0.0f; for(k=0;k<OUTPUT;k++) temp_error+=output_error[k]*weight_ho[j][k]; hidden_error[j]=hidden_out[j] *(1.0f-hidden_out[j])*temp_error; } //重みの補正 for(k=0;k<OUTPUT;k++) for(j=0;j<HIDDEN;j++) weight_ho[j][k]+=ALPHA*output_error[k]*hidden_out[j]; for(j=0;j<HIDDEN;j++) for(i=0;i<INPUT;i++) weight_ih[i][j]+=ALPHA*hidden_error[j]*sample_in[i]; //閾値の補正 for(k=0;k<OUTPUT;k++) thresh_o[k]-=ALPHA*output_error[k]; for(j=0;j<HIDDEN;j++) thresh_h[j]-=ALPHA*hidden_error[j]; } //Sigmoid関数を計算するメソッド public float sigmoid(float x){ return 1.0f/(1.0f+(float)Math.exp(-BETA*x)); } //入力文字を認識するメソッド public void recognizeCharacter(){ Graphics g=getGraphics(); String string; //順方向演算 forwardNeuralNet(written_in,recog_out); //結果の表示 for(int k=0;k<OUTPUT;k++){ g.setColor(Color.black); g.drawString(String.valueOf(k)+"である",RX2,RY1+20*k); if(recog_out[k]>0.8f) g.setColor(Color.red); else g.setColor(Color.black); g.fillRect(RX3,RY1-10+20*k,(int)(200*recog_out[k]),10); g.drawString(String.valueOf((int)(100*recog_out[k]+0.5f)) +"%",RX3+(int)(200*recog_out[k])+10,RY1+20*k); } } }
- 修正履歴
-
- 2008/03/16 10:31 参考資料をVisual C++ 2005 Express Edition版に変更
この記事は参考になりましたか?
- Javaで学ぶグラフィックス処理連載記事一覧
-
- 数字パズルを半自動的に解くプログラムの作成
- 画像を小刻みに回転して写真の傾きを補正する
- ニューラルネットワークを用いたパターン認識
- この記事の著者
-
石立 喬(イシダテ タカシ)
1955年東京工大卒。同年、NECへ入社し、NEC初のコンピュータの開発に参画。磁気メモリ、半導体メモリの開発、LSI設計などを経て、1989年帝京大学理工学部教授。情報、通信、電子関係の教育を担当。2002年定年により退職し現在に至る。2000年より、Webサイト「Visual C++の勉強部屋」を公開。...
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
