/* ahh.h */
/* 역전파 다층 신경망을 구현한 헤더 입니다.*/
//뉴런 구조체
typedef struct CZ_NURUN
{
double *weight; //입력 가중치
double thold; //임계치
double out; //출력값
double error_gradient; // 오차기울기
}NURUN;
typedef struct CZ_ANN
{
int layer; //총 층의 개수
int *nurun_num; //각 층별 뉴런의 개수
int input_num; //초기 뉴런의 입력 개수
double alpa;
NURUN **nurun; //전체 뉴런의 가중치 정보 실질적인 뉴런
}ANN;
//뉴런 초기화 대상, 은닉층개수, 각 층별 뉴런의 개수, 층별 뉴런의 입력개수
int Init_ANN(struct CZ_ANN *ann,int hidden,int *nurun_num, int input_num);
double Porjection_ANN(struct CZ_ANN *ann,int *input); //정방향연산
double step(double x);
double sigmoid(double x);
double error_gradient(struct CZ_ANN *ann,int layer, int nurun, double error); //출력층의 오차기울기
double error(double dst_out, double now_out); //오차리턴
double error_gradient_for_hidden(struct CZ_ANN *ann,int layer, int nurun); //은닉층의 오차기울기
double weight_ubdate( struct CZ_ANN *ann,int layer, int nurun, int weight, double input,double dest_out);
double weight_ubdate( struct CZ_ANN *ann,int layer, int nurun, int weight, double input ,double dest_out)
{
double error = 0;
error = dest_out - ann->nurun[layer][nurun].out;
if(layer == ann->layer -1)ann->nurun[layer][nurun].weight[weight] = ann->alpa * input * error_gradient(ann,layer,nurun,error);
ann->nurun[layer][nurun].weight[weight] = ann->alpa * input * error_gradient_for_hidden(ann,layer,nurun);
return 0;
}
double error(double dst_out, double now_out){return dst_out - now_out;}
double error_gradient(struct CZ_ANN *ann,int layer, int nurun, double error)
{
ann->nurun[layer][nurun].error_gradient = ann->nurun[layer][nurun].out * (1 - ann->nurun[layer][nurun].out) * error;
return ann->nurun[layer][nurun].error_gradient;
}
double error_gradient_for_hidden(struct CZ_ANN *ann,int layer, int nurun)
{
double error = 0;
int cnt =0;
for(cnt=0; cnt < ann->nurun_num[layer+1] ; cnt++)
error += ann->nurun[layer+1][cnt].error_gradient * ann->nurun[layer+1][cnt].weight[nurun];
return error_gradient(ann,layer,nurun,error);
}
double sigmoid(double x){ return 1/(1+exp((-1)*x)); }
double Porjection_ANN(struct CZ_ANN *ann,int *input)
{
int layer,nurun,inp;
for(layer=0; layer < ann->layer;layer++)//층에 접근
{
for(nurun=0; nurun < ann->nurun_num[layer];nurun++)//뉴런에 접근
{
ann->nurun[layer][nurun].out = 0; //선형 가산
if(layer==0)for(inp = 0; inp < ann->input_num;inp++) ann->nurun[layer][nurun].out += input[inp]*ann->nurun[layer][nurun].weight[inp];
else for(inp = 0; inp < ann->nurun_num[layer-1];inp++)
ann->nurun[layer][nurun].out += ann->nurun[layer-1][inp].out*ann->nurun[layer][nurun].weight[inp];
ann->nurun[layer][nurun].out = sigmoid(ann->nurun[layer][nurun].out - ann->nurun[layer][nurun].thold);
}
}
return 0;
}
double step(double x)
{
if( x < 0 ) return 0;
else return 1;
}
int Init_ANN(struct CZ_ANN *ann,int hidden,int *nurun_num, int input_num)
{
int cnt, cnt2,cnt3;
ann->alpa = 0.01;
ann->layer=hidden+1; //출력층의 개수를 포함
ann->nurun_num = (int*)malloc(sizeof(int)*ann->layer);
//층별 뉴런 정보 할당
for(cnt=0;cnt<ann->layer;cnt++) ann->nurun_num[cnt] = nurun_num[cnt];
ann->input_num = input_num; //초기입력개수 할당
ann->nurun = (NURUN**)malloc(sizeof(NURUN)*ann->layer);//레이어 할당
for(cnt=0;cnt < ann->layer;cnt++) ann->nurun[cnt] = (NURUN*)malloc(sizeof(NURUN)*ann->nurun_num[cnt]);//뉴런할당
for(cnt=0;cnt < ann->layer;cnt++)for(cnt2=0;cnt2 < ann->nurun_num[cnt];cnt2++)
if(cnt == 0)ann->nurun[cnt][cnt2].weight = (double*)malloc(sizeof(double)*ann->input_num);//촉수할당
else ann->nurun[cnt][cnt2].weight = (double*)malloc(sizeof(double)*ann->nurun_num[cnt-1]);//하층뉴런의 입력개수는 상층뉴런의 개수와 동일
//초기 가중치 할당
for(cnt=0;cnt < ann->layer;cnt++)for(cnt2=0;cnt2 < ann->nurun_num[cnt];cnt2++)
if(cnt==0)for(cnt3=0;cnt3<ann->input_num;cnt3++)ann->nurun[cnt][cnt2].weight[cnt3] = 1;//입력측의 가중치는 생각하지 말자..
else for(cnt3=0;cnt3<ann->nurun_num[cnt-1];cnt3++)ann->nurun[cnt][cnt2].weight[cnt3] = cnt2;
return 0;
}
/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ann.h"
int main()
{
ANN ann; //뉴런 생성
int hidden = 1;
int nurun_num[2] = {2,1};
int input_num = 2;
int input[4][2] = {0,0,0,1,1,0,1,1};
int cnt, cnt2, cnt3;
//뉴런 초기화
Init_ANN(&ann,hidden,nurun_num,input_num);
ann.nurun[0][0].thold = 7.3061;
ann.nurun[0][1].thold = 2.8441;
ann.nurun[1][0].thold = 4.5589;
ann.nurun[0][0].weight[0] = 4.7621;
ann.nurun[0][0].weight[1] = 4.7618;
ann.nurun[0][1].weight[0] = 6.3917;
ann.nurun[0][1].weight[1] = 6.3917;
ann.nurun[1][0].weight[0] = -10.3788;
ann.nurun[1][0].weight[1] = 9.7691;
int a =0;
printf("다층 신경망 Xor 학습\n");
for(a=0;a<4;a++)
{
Porjection_ANN(&ann,input[a]); //뉴런에 입력을 넣어 연산을 본다.
/*
for(cnt=0;cnt < ann.layer;cnt++)
{
for(cnt2=0;cnt2 < ann.nurun_num[cnt];cnt2++)
{
printf("출력 : %lf ",ann.nurun[cnt][cnt2].out);
printf(" ");
}
printf("\n");
}*/
for(cnt2=0;cnt2 < ann.nurun_num[ann.layer-1];cnt2++)
{
printf("\n입력 : %d Xor %d ",input[a][0],input[a][1]);
printf("출력 : %lf ",ann.nurun[ann.layer-1][cnt2].out);
printf("판정 : %lf ",step(ann.nurun[ann.layer-1][cnt2].out - 0.5));
}
printf("\n");
}
printf("\n");
system("pause");
return 0;
}
폴더 정리하다 발견한 거 투척.
좀 오래전에 만들다 던졌던 것 같은데, 다층신경망이랍시고 만든 다음에 역전파 만들려다가 귀찮아서 때려침 -_-;;
덕분에 신경망인데 학습을 못하는 장애를 가진 코드 가 탄생 ㅋㅋ
어릴때의 나는 지금보다 똑똑했던 것 같다 ㅠ
처음 짤때는 좋은데 그 뒤로 거의 안쓰는게 인공지능 과목[...]
ㄷㄷㄷ 천재
코드가 너무 옆으로 간다..보기 힘들다..엔터키 고장났나보다..
이 프로그램 옛날에 본 것 같은데...
옛날에 올렸던 코드일 듯