Skip to content

Instantly share code, notes, and snippets.

@KUKDfhia
Created July 18, 2017 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KUKDfhia/850b3462bae3be62909f61460d62ebaa to your computer and use it in GitHub Desktop.
Save KUKDfhia/850b3462bae3be62909f61460d62ebaa to your computer and use it in GitHub Desktop.
/* プログラム名:neurallearn.c */
/* copyright "© 2017 KUKDfhia." */
/* link "http://qiita.com/KUKDfhia" */
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
/* パラメータを設定する(今書いてある値は例であるため、好きに設定してよい) */
#define NUM_LEARN 15000 /* 学習回数 */
#define NUM_SAMPLE 10 /* 訓練データ数(今回は10パターン用意する)*/
#define NUM_INPUT 4 /* 入力層の数(7セグメント表示器の入力)*/
#define NUM_HIDDEN_ONE 12 /* 中間層1の数(自由)*/
#define NUM_HIDDEN_TWO 10 /* 中間層2の数(自由)*/
#define NUM_HIDDEN_THREE 8 /* 中間層3の数(自由)*/
#define NUM_OUTPUT 7 /* 出力層の数(7セグメント表示器の出力)*/
#define EPSILON 0.5 /* 学習係数ε */
#define ALPHA 1 /* 慣性係数α ※振動を避けるために設定するものであるが、基本的に1に設定しておけば問題なし */
/* シグモイド関数 */
double sigmoid(double x){
double f;
f=1.0/(1.0+exp(-x));
return f; /* 戻り値が関数値 */
}
int tx[NUM_SAMPLE][NUM_INPUT],ty[NUM_SAMPLE][NUM_OUTPUT]; /* txが入力、tyが出力 教師データを格納する */
double x[NUM_INPUT+1],h1[NUM_HIDDEN_ONE+1],h2[NUM_HIDDEN_TWO+1],h3[NUM_HIDDEN_THREE+1],y[NUM_OUTPUT]; /* xが入力、h1が中間1、h2が中間2、h3が中間3、yが出力 それぞれニューロンの値。+1は閾値表現用 */
double w1[NUM_INPUT+1][NUM_HIDDEN_ONE],w2[NUM_HIDDEN_ONE+1][NUM_HIDDEN_TWO],w3[NUM_HIDDEN_TWO+1][NUM_HIDDEN_THREE],w4[NUM_HIDDEN_THREE+1][NUM_OUTPUT]; /* w1が入力ー中間1、w2が中間1ー中間2、w3が中間2ー中間3、w4が中間3ー出力の結合荷重の値 */
double h1_back[NUM_HIDDEN_ONE+1],h2_back[NUM_HIDDEN_TWO+1],h3_back[NUM_HIDDEN_THREE+1],y_back[NUM_OUTPUT]; /* h1_backが中間1、h2_backが中間2、h3_backが中間3、y_backが出力の逆伝播量 */
int main(void){
int ilearn,isample,i,j;
double net_input,epsilon,alpha;
FILE *csv;
srand((unsigned)time(NULL));
epsilon=(double)EPSILON;
alpha=(double)ALPHA;
/* input.csvから入力に用いる教師データを配列txに設定する */
csv=fopen("input.csv", "r");
if(csv==NULL){
printf("ファイルがオープンできません\n");
return -1;
}
for(i=0;i<NUM_SAMPLE;i++){
for(j=0;j<NUM_INPUT;j++){
if(fscanf(csv,"%d,",&tx[i][j])!='\0');
}
}
fclose(csv);
  /* output.csvから出力に用いる教師データを配列tyに設定する */
csv=fopen("output.csv", "r");
if(csv==NULL){
printf("ファイルがオープンできません\n");
return -1;
}
for(i=0;i<NUM_SAMPLE;i++){
for(j=0;j<NUM_OUTPUT;j++){
if(fscanf(csv,"%d,",&ty[i][j])!='\0');
}
}
fclose(csv);
/* 結合荷重にランダムな初期値を設定(-0.1~0.1の範囲) */
for(i=0;i<NUM_INPUT+1;i++){
for(j=0;j<NUM_HIDDEN_ONE;j++){
w1[i][j]=(double)rand()/RAND_MAX/10.0;
if((rand()%100+1)>=51){
w1[i][j]=-w1[i][j];
}
}
}
for(i=0;i<NUM_HIDDEN_ONE+1;i++){
for(j=0;j<NUM_HIDDEN_TWO;j++){
w2[i][j]=(double)rand()/RAND_MAX/10.0;
if((rand()%100+1)>=51){
w2[i][j]=-w2[i][j];
}
}
}
for(i=0;i<NUM_HIDDEN_TWO+1;i++){
for(j=0;j<NUM_HIDDEN_THREE;j++){
w3[i][j]=(double)rand()/RAND_MAX/10.0;
if((rand()%100+1)>=51){
w3[i][j]=-w3[i][j];
}
}
}
for(i=0;i<NUM_HIDDEN_THREE+1;i++){
for(j=0;j<NUM_OUTPUT;j++){
w4[i][j]=(double)rand()/RAND_MAX/10.0;
if((rand()%100+1)>=51){
w4[i][j]=-w4[i][j];
}
}
}
/* 学習の繰り返し */
printf("学習を開始します\n");
for(ilearn=0;ilearn<NUM_LEARN;ilearn++){
/* 訓練データの繰り返し */
for(isample=0;isample<NUM_SAMPLE;isample++){
   
/* 順方向の動作 */
/* 訓練データに従って、ネットワークへの入力設定 */
for(i=0;i<NUM_INPUT;i++){
x[i]=tx[isample][i];
}
/* 閾値設定x */
x[NUM_INPUT]=(double)1.0;
   
/* 隠れ素子1の計算 */
for(j=0;j<NUM_HIDDEN_ONE;j++){
net_input=0;
for(i=0;i<NUM_INPUT+1;i++){
net_input=net_input+w1[i][j]*x[i];
}
    /* シグモイドの適用 */
h1[j]=sigmoid(net_input);
}
   /* 閾値設定h1 */
h1[NUM_HIDDEN_ONE]=(double)1.0;
/* 隠れ素子2の計算 */
for(j=0;j<NUM_HIDDEN_TWO;j++){
net_input=0;
for(i=0;i<NUM_HIDDEN_ONE+1;i++){
net_input=net_input+w2[i][j]*h1[i];
}
  /* シグモイドの適用 */
h2[j]=sigmoid(net_input);
}
/* 閾値設定h2 */
h2[NUM_HIDDEN_TWO]=(double)1.0;
/* 隠れ素子3の計算 */
for(j=0;j<NUM_HIDDEN_THREE;j++){
net_input=0;
for(i=0;i<NUM_HIDDEN_TWO+1;i++){
net_input=net_input+w3[i][j]*h2[i];
}
/* シグモイドの適用 */
h3[j]=sigmoid(net_input);
}
/* 閾値設定h3 */
h3[NUM_HIDDEN_THREE]=(double)1.0;
/* 出力素子の計算 */
for (j=0;j<NUM_OUTPUT;j++){
net_input=0;
for(i=0;i<NUM_HIDDEN_THREE+1;i++){
net_input=net_input+w4[i][j]*h3[i];
}
/* シグモイドの適用 */
y[j]=sigmoid(net_input);
}
/* 逆方向の動作 */
/* 出力層の逆伝播 */
for(j=0;j<NUM_OUTPUT;j++){
y_back[j]=(y[j]-ty[isample][j])*((double)1.0-y[j])*y[j];
}
    /* 隠れ層3の逆伝播 */
for(i=0;i<NUM_HIDDEN_THREE;i++){
net_input=0;
for(j=0;j<NUM_OUTPUT;j++){
net_input=net_input+w4[i][j]*y_back[j];
}
h3_back[i]=net_input*((double)1.0-h3[i])*h3[i];
}
/* 隠れ層2の逆伝播 */
for(i=0;i<NUM_HIDDEN_TWO;i++){
net_input=0;
for(j=0;j<NUM_HIDDEN_THREE;j++){
net_input=net_input+w3[i][j]*h3_back[j];
}
h2_back[i]=net_input*((double)1.0-h2[i])*h2[i];
}
/* 隠れ層1の逆伝播 */
for(i=0;i<NUM_HIDDEN_ONE;i++){
net_input=0;
for(j=0;j<NUM_HIDDEN_TWO;j++){
net_input=net_input+w2[i][j]*h2_back[j];
}
h1_back[i]=net_input*((double)1.0-h1[i])*h1[i];
}
/* 結合荷重の修正 */
for(i=0;i<NUM_INPUT+1;i++){
for(j=0;j<NUM_HIDDEN_ONE;j++){
w1[i][j]=(alpha*w1[i][j])-(epsilon*x[i]*h1_back[j]);
}
}
for(i=0;i<NUM_HIDDEN_ONE+1;i++){
for(j=0;j<NUM_HIDDEN_TWO;j++){
w2[i][j]=(alpha*w2[i][j])-(epsilon*h1[i]*h2_back[j]);
}
}
for(i=0;i<NUM_HIDDEN_TWO+1;i++){
for(j=0;j<NUM_HIDDEN_THREE;j++){
w3[i][j]=(alpha*w3[i][j])-(epsilon*h2[i]*h3_back[j]);
}
}
for(i=0;i<NUM_HIDDEN_THREE+1;i++){
for(j=0;j<NUM_OUTPUT;j++){
w4[i][j]=(alpha*w4[i][j])-(epsilon*h3[i]*y_back[j]);
}
}
}
}
/* 学習後の結合荷重の値をcsvに記録する(この値をneuralfuture.cのプログラムに適用する事で7セグメント表示器の出力についての予測値を求める) */
/* kekka1.csvに学習後の結合荷重w1の値を記録する */
csv=fopen("kekka1.csv", "w");
if(csv==NULL){
printf("ファイルがオープンできません\n");
return -1;
}
for(i=0;i<NUM_INPUT+1;i++){
for(j=0;j<NUM_HIDDEN_ONE;j++){
fprintf(csv,"%f\n",w1[i][j]);
}
}
fclose(csv);
/* kekka2.csvに学習後の結合荷重w2の値を記録する */
csv=fopen("kekka2.csv", "w");
if(csv==NULL){
printf("ファイルがオープンできません\n");
return -1;
}
for(i=0;i<NUM_HIDDEN_ONE+1;i++){
for(j=0;j<NUM_HIDDEN_TWO;j++){
fprintf(csv,"%f\n",w2[i][j]);
}
}
fclose(csv);
/* kekka3.csvに学習後の結合荷重w3の値を記録する */
csv=fopen("kekka3.csv", "w");
if(csv==NULL){
printf("ファイルがオープンできません\n");
return -1;
}
for(i=0;i<NUM_HIDDEN_TWO+1;i++){
for(j=0;j<NUM_HIDDEN_THREE;j++){
fprintf(csv,"%f\n",w3[i][j]);
}
}
fclose(csv);
/* kekka4.csvに学習後の結合荷重w4の値を記録する */
csv=fopen("kekka4.csv", "w");
if(csv==NULL){
printf("ファイルがオープンできません\n");
return -1;
}
for(i=0;i<NUM_HIDDEN_THREE+1;i++){
for(j=0;j<NUM_OUTPUT;j++){
fprintf(csv,"%f\n",w4[i][j]);
}
}
fclose(csv);
  printf("学習が終了しました\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment