Skip to content

Instantly share code, notes, and snippets.

@maekawatoshiki
Created March 8, 2015 05:04
Show Gist options
  • Save maekawatoshiki/c8dd8f923c03f45ff7ff to your computer and use it in GitHub Desktop.
Save maekawatoshiki/c8dd8f923c03f45ff7ff to your computer and use it in GitHub Desktop.
Hierarchical neural network
#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