Created
March 8, 2015 05:04
-
-
Save maekawatoshiki/c8dd8f923c03f45ff7ff to your computer and use it in GitHub Desktop.
Hierarchical neural network
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <cstdlib> | |
#include <cmath> | |
#include <ctime> | |
#include <iostream> | |
using namespace std; | |
#define NUM_LEARN 20000 //学習の繰り返し回数 | |
#define NUM_SAMPLE 4 //トレーニングデータのサンプル数(ここでは論理回路なので4個、学習1回の中でのループ回数) | |
#define NUM_INPUT 2 //入力層の数(論理回路の入力) | |
#define NUM_HIDDEN 5 //中間層の数(適当) | |
#define NUM_OUTPUT 1 //出力層の数(出力数1個) | |
#define EPSILON 0.1 //学習時の重み修正定数(η) | |
double sigmoid(double x) | |
{ | |
return 1.0/(1.0+exp(-x)); | |
} | |
struct NN | |
{ | |
int x[NUM_INPUT]; | |
int y[NUM_OUTPUT]; | |
}; | |
NN txy[NUM_SAMPLE] = { 0 }; | |
double x[NUM_INPUT+1],h[NUM_HIDDEN+1],y[NUM_OUTPUT]; | |
double w1[NUM_INPUT+1][NUM_HIDDEN],w2[NUM_HIDDEN+1][NUM_OUTPUT]; | |
double h_back[NUM_HIDDEN+1],y_back[NUM_OUTPUT]; | |
//中間、出力の逆伝播量 | |
int main(void){ | |
int learn, sample, i, j; | |
double net_input; | |
srand((unsigned)time(NULL)); | |
//教師データ(txが入力、tyが出力) | |
txy[0].x[0]=0; | |
txy[0].x[1]=0; | |
txy[0].y[0]=0; | |
txy[1].x[0]=0; | |
txy[1].x[1]=1; | |
txy[1].y[0]=1; | |
txy[2].x[0]=1; | |
txy[2].x[1]=0; | |
txy[2].y[0]=1; | |
txy[3].x[0]=1; | |
txy[3].x[1]=1; | |
txy[3].y[0]=0; | |
for(i = 0;i < NUM_INPUT+1; i++) | |
for(j = 0;j < NUM_HIDDEN; j++) | |
w1[i][j]= (double)rand() / RAND_MAX; | |
for(i = 0;i < NUM_HIDDEN+1; i++) | |
for(j = 0;j < NUM_OUTPUT; j++) | |
w2[i][j]= (double)rand() / RAND_MAX; | |
for(learn = 0; learn < NUM_LEARN; learn++) | |
{ | |
//訓練データに関するループ | |
for(sample = 0; sample < NUM_SAMPLE; sample++) | |
{ | |
//順方向の動作 | |
//訓練データに従って、ネットワークへの入力設定 | |
for(i = 0;i < NUM_INPUT; i++) | |
x[i] = txy[sample].x[i]; | |
//閾値設定x[NUM_INPUT] = 1.0 | |
x[NUM_INPUT] = (double)1.0; | |
//隠れ素子の計算 | |
for( j = 0; j < NUM_HIDDEN;j++) | |
{ | |
net_input = 0; | |
for( i = 0; i < NUM_INPUT+1; i++ ) | |
net_input = net_input + w1[i][j] * x[i]; | |
//シグモイドの適用 | |
h[j] = sigmoid(net_input); | |
} | |
//閾値設定h[NUM_HIDDEN] = 1.0 | |
h[NUM_HIDDEN] = (double)1.0; | |
//出力素子の計算 | |
for (j = 0; j < NUM_OUTPUT;j++) | |
{ | |
net_input = 0; | |
for(i = 0;i < NUM_HIDDEN+1; i++) | |
net_input = net_input + w2[i][j]*h[i]; | |
//シグモイドの適用 | |
y[j]=sigmoid(net_input); | |
printf("y > %lf (%d.%d)\n", y[j], txy[sample].x[0], txy[sample].x[1] ); | |
} | |
//逆方向の動作 | |
//出力層素子の逆伝播 | |
for(j = 0; j < NUM_OUTPUT; j++) | |
y_back[j] = ( y[j] - txy[sample].y[j] ) * ( 1.0 - y[j] ) * y[j]; | |
//隠れ層素子の逆伝播 | |
for(i = 0; i < NUM_HIDDEN;i++) | |
{ | |
net_input = 0; | |
for(j = 0; j < NUM_OUTPUT; j++) | |
net_input = net_input + w2[i][j] * y_back[j]; | |
h_back[i] = net_input * ((double)1.0 - h[i]) * h[i]; | |
} | |
//重みの修正 | |
for(i = 0; i < NUM_INPUT+1; i++) | |
for(j = 0; j < NUM_HIDDEN; j++) | |
w1[i][j] = w1[i][j] - EPSILON * x[i] * h_back[j]; | |
for(i = 0; i < NUM_HIDDEN+1; i++) | |
for(j = 0; j < NUM_OUTPUT; j++) | |
w2[i][j] = w2[i][j] - EPSILON * h[i] * y_back[j]; | |
}//訓練データのループ終わり | |
}//学習データのループ終わり | |
for(i = 0;i < NUM_INPUT; i++) | |
{ | |
cin >> x[i]; | |
} | |
//閾値設定x[NUM_INPUT] = 1.0 | |
h[NUM_HIDDEN] = x[NUM_INPUT] = (double)1.0; | |
//隠れ素子の計算 | |
for( j = 0; j < NUM_HIDDEN;j++) | |
{ | |
net_input = 0; | |
for(i = 0; i < NUM_INPUT+1; i++) | |
{ | |
net_input = net_input + w1[i][j] * x[i]; | |
} | |
//シグモイドの適用 | |
h[j] = sigmoid(net_input); | |
} | |
for (j = 0; j < NUM_OUTPUT;j++) | |
{ | |
net_input = 0; | |
for(i = 0;i < NUM_HIDDEN+1; i++) | |
net_input += w2[i][j] * h[i]; | |
y[j]=sigmoid(net_input); | |
printf("y > %lf (%d.%d)\n", y[j], txy[sample].x[0], txy[sample].x[1] ); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment