on
[인공지능] 오류역전파 알고리즘을 이용한 문자인식 프로그램
[인공지능] 오류역전파 알고리즘을 이용한 문자인식 프로그램
⭐ 이전에 홀린 홉필드 네트워크 관련 게시물의 최종 과제물입니다.
⭐ https://it-hong.tistory.com/4
1. 기본 설정 값
2. 신경회로망 Topology
3. 학습 알고리즘
0단계) Epoch와 eta와 입력층, 히든층, 출력층의 레이어 수 미리 설정
1단계) 시그모이드 함수 생성
2단계) 입력과 목표 출력을 제시
3단계) 가중치를 랜덤 값으로 초기화
4단계) 시그모이드 함수를 사용해서 입력층 -> 은닉층의 출력값 계산(전방향 학습과정)
5단계) 시그모이드 함수를 사용해서 은닉층 ->출력층의 출력값 계산(전방향 학습과정)
6단계) 출력층 오차계산(전방향 학습과정)
7단계) 은닉층 오차계산(전방향 학습과정)
8단계) 출력층의 가중치 갱신(역방향 학습과정)
9단계) 은닉층의 가중치 갱신(역방향 학습과정)
다시 4단계로 돌아간다.(모든 패턴을 학습시킬 때까지…)
4. 코드
package ai2_1; import java.util.Scanner; public class AI2_8 { static int EPOCH = 1000; // epoch static double ERROR_LIMIT = 0.005; //오차 한계 범위 static double THRESHOLD = 0.1; // 임계치 static int INPUT_LAYER = 25; //입력레이어 갯수 static int HIDDEN_LAYER = 3; //은닉레이어 갯수 static int OUTPUT_LAYER = 8; //출력레이어 갯수 //static int n=0; //epoch가 몇번까지 돌고 멈췄는지 세기 위한 변수 //단계 1 시그모이드 함수 public double sigmoid(double x) { return 1/(1+(Math.exp(-x))); } static double[] input_sum = new double[HIDDEN_LAYER]; static double[] hidden_sum = new double[OUTPUT_LAYER]; static double[] output_output = new double[OUTPUT_LAYER]; static double [][] weight_HO = new double[HIDDEN_LAYER][OUTPUT_LAYER]; static double [][] weight_IH = new double[INPUT_LAYER][HIDDEN_LAYER]; public static void main(String[] args) { //시그모이드 함수를 사용하기 위해 AI2_8 C = new AI2_8(); Scanner scan = new Scanner(System.in); //단계2 입력과 목표 출력을 제시 double[] input_1 = { 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; // ㄱ double[] input_2 = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 }; // ㄴ double[] input_3 = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 }; // ㄷ double[] input_4 = { 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 }; // ㄹ double[] input_5 = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; // ㅁ double[] input_6 = { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; // ㅂ double[] input_7 = { 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1 }; // ㅈ double[] input_8 = { 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1 }; // ㅊ double[] output_1 = { 1, 0, 0, 0, 0, 0, 0, 0 }; double[] output_2 = { 0, 1, 0, 0, 0, 0, 0, 0 }; double[] output_3 = { 0, 0, 1, 0, 0, 0, 0, 0 }; double[] output_4 = { 0, 0, 0, 1, 0, 0, 0, 0 }; double[] output_5 = { 0, 0, 0, 0, 1, 0, 0, 0 }; double[] output_6 = { 0, 0, 0, 0, 0, 1, 0, 0 }; double[] output_7 = { 0, 0, 0, 0, 0, 0, 1, 0 }; double[] output_8 = { 0, 0, 0, 0, 0, 0, 0, 1 }; //단계3 가중치를 랜덤 값으로 초기화 for (int i = 0; i < INPUT_LAYER; i++) { for (int j = 0; j < HIDDEN_LAYER; j++) { double random_w = Math.random();// 난수의 범위를 0.0~1.0로 설정한다. weight_IH[i][j] = random_w; // ㄱ을 학습할 때는 0열에 가중치가 입력되고 ㄴ할 때는 1열에 입력되게... } } for (int i = 0; i < HIDDEN_LAYER; i++) { for (int j = 0; j < OUTPUT_LAYER; j++) { double random_w = Math.random(); weight_HO[i][j] = random_w; } } System.out.println("#(학습전)입력층->은닉층의 가중치값 =>"); for (int M = 0; M < INPUT_LAYER; M++) { for (int j = 0; j < HIDDEN_LAYER; j++) { System.out.print(weight_IH[M][j] + " "); } System.out.println(""); }System.out.println(""); System.out.println("#(학습전)은닉층->출력층의 가중치값 =>"); for (int M = 0; M < HIDDEN_LAYER; M++) { for (int j = 0; j < OUTPUT_LAYER; j++) { System.out.print(weight_HO[M][j] + " "); } System.out.println(""); }System.out.println(""); // 본격 학습시키기 long beforTime = System.currentTimeMillis(); for (int i = 0; i < EPOCH; i++) { C.Compute(input_1, output_1); // ㄱ학습 C.Compute(input_2, output_2); // ㄴ학습 C.Compute(input_3, output_3); // ㄷ학습 C.Compute(input_4, output_4); // ㄹ학습 C.Compute(input_5, output_5); // ㅁ학습 C.Compute(input_6, output_6); // ㅅ학습 C.Compute(input_7, output_7); // ㅈ학습 C.Compute(input_8, output_8); // ㅊ학습 } long afterTime = System.currentTimeMillis(); long secDiffTime = (afterTime - beforTime); System.out.println("학습에 걸린 시간(ms) : " + secDiffTime + ""); System.out.println(" "); //학습이 끝난 후의 출력값의 노드를 체크 System.out.println("#학습이 끝난 후의 출력값 "); for (int i = 0; i < output_output.length; i++) { System.out.print(output_output[i] + " "); } System.out.println(" "); System.out.println("#(학습후)입력층->은닉층의 가중치값 =>"); for (int M = 0; M < INPUT_LAYER; M++) { for (int j = 0; j < HIDDEN_LAYER; j++) { System.out.print(weight_IH[M][j] + " "); } System.out.println(""); }System.out.println(""); System.out.println("#(학습후)은닉층->출력층의 가중치값 =>"); for (int M = 0; M < HIDDEN_LAYER; M++) { for (int j = 0; j < OUTPUT_LAYER; j++) { System.out.print(weight_HO[M][j] + " "); } System.out.println(""); }System.out.println(""); //사용자로부터 테스트하고 하는 input값과 예측하는 output값을 입력받는다. double want_input[] = new double[INPUT_LAYER]; System.out.println("#테스트하고자 하는 input값을 넣으세요 5x5 =>"); for (int m = 0; m < want_input.length; m++) { want_input[m] = scan.nextDouble(); }System.out.println(""); double want_output[] = new double[OUTPUT_LAYER]; System.out.println("#예측하는 output값을 넣으세요 1x8 =>");
이전의 블로그에 올려놨었을 때 전체 코드를 올려놨다고 생각했는데 지금보니 밑부분이 살짝 짤린 것 같습니다.
⭐ 제가 과제를 할 때 다른 사람의 코드를 읽는 것 만으로도 공부에 큰 도움이 됐었는데
대단한 코드는 아니지만 질문이 있다면 댓글 남겨주시면 제가 아는 선에서 대답해드리겠습니다.
또한 코드에 지적할 부분이나 수정할 부분이 있다면 댓글 남겨주시면 큰 도움이 될 것 같습니다.
from http://it-hong.tistory.com/6 by ccl(A) rewrite - 2021-08-06 11:00:18