Simple Recurrent Neural Network Predictor
Diff: SRNN.cpp
- Revision:
- 5:026d42b4455f
- Parent:
- 4:9d94330f380a
- Child:
- 6:e97ccc643bf1
--- a/SRNN.cpp Wed Feb 18 15:01:17 2015 +0000 +++ b/SRNN.cpp Thu Feb 19 08:20:23 2015 +0000 @@ -18,6 +18,7 @@ // sample/sample_maxmin allocation this->sample = new float[len_seqence * dim_signal]; + this->norm_sample = new float[len_seqence * dim_signal]; this->sample_maxmin = new float[dim_signal * 2]; memcpy(this->sample, input_sample, sizeof(float) * len_seqence * dim_signal); @@ -34,6 +35,30 @@ expand_in_signal = new float[dim_signal + num_mid_neuron + 1]; expand_mid_signal = new float[num_mid_neuron + 1]; + // For BUG FIX... + // 係数行列のサイズ + int row_in_mid = num_mid_neuron; + int col_in_mid = dim_signal + num_mid_neuron + 1; + int row_mid_out = dim_signal; + int col_mid_out = num_mid_neuron + 1; + + // 行列のアロケート + // 係数行列の更新量 + this->dWin_mid = new float[row_in_mid * col_in_mid]; + this->dWmid_out = new float[row_mid_out * col_mid_out]; + + // 前回の更新量:慣性項に用いる. + this->prevdWin_mid = new float[row_in_mid * col_in_mid]; + this->prevdWmid_out = new float[row_mid_out * col_mid_out]; + // 出力層の信号 + this->out_signal = new float[dim_signal]; + // 入力層->中間層の信号和 + this->in_mid_net = new float[num_mid_neuron]; + // 中間層->出力層の信号和. + this->mid_out_net = new float[dim_signal]; + // 誤差信号 + this->sigma = new float[dim_signal]; + // Parameter settings (Tuning by taiyo) this->squareError = FLT_MAX; // (large value) this->maxIteration = 5000; @@ -52,6 +77,7 @@ SRNN::~SRNN(void) { delete [] sample; + delete [] norm_sample; delete [] sample_maxmin; delete [] predict_signal; delete [] Win_mid; @@ -72,8 +98,8 @@ /* Predict : predicting next sequence of input */ void SRNN::predict(float* input) { + float *norm_input = new float[this->dim_signal]; - // output signal float* out_signal = new float[dim_signal]; // value of network in input->hidden layer @@ -142,6 +168,7 @@ int row_mid_out = dim_signal; int col_mid_out = num_mid_neuron + 1; + /* // 行列のアロケート // 係数行列の更新量 float* dWin_mid = new float[row_in_mid * col_in_mid]; @@ -151,7 +178,7 @@ float* prevdWin_mid = new float[row_in_mid * col_in_mid]; float* prevdWmid_out = new float[row_mid_out * col_mid_out]; - float* norm_sample = new float[len_seqence * dim_signal]; // 正規化したサンプル信号; 実際の学習は正規化した信号を用います. + // float* norm_sample = new float[len_seqence * dim_signal]; // 正規化したサンプル信号; 実際の学習は正規化した信号を用います. // 出力層の信号 float* out_signal = new float[dim_signal]; @@ -163,6 +190,7 @@ // 誤差信号 float* sigma = new float[dim_signal]; + */ // 係数行列の初期化 for (int i=0; i < row_in_mid; i++) @@ -173,16 +201,17 @@ for (int j=0; j < col_mid_out; j++) MATRIX_AT(Wmid_out,col_mid_out,i,j) = uniform_rand(width_initW); + // 信号の正規化:経験上,非常に大切な処理 + float buf_float; for (int i_seq=0; i_seq < len_seqence; i_seq++) { for (int dim_n=0; dim_n < dim_signal; dim_n++) { - MATRIX_AT(norm_sample,dim_signal,i_seq,dim_n) = - normalize_signal(MATRIX_AT(this->sample,dim_signal,i_seq,dim_n), - MATRIX_AT(this->sample_maxmin,2,dim_n,0), - MATRIX_AT(this->sample_maxmin,2,dim_n,1)); - // printf("%f ", MATRIX_AT(norm_sample,dim_signal,i_seq,dim_n)); + MATRIX_AT(norm_sample,dim_signal,i_seq,dim_n) + = normalize_signal(MATRIX_AT(this->sample,dim_signal,i_seq,dim_n), + MATRIX_AT(this->sample_maxmin,2,dim_n,0), + MATRIX_AT(this->sample_maxmin,2,dim_n,1)); } - //printf("\r\n"); + // printf("%f %f %f \r\n", MATRIX_AT(norm_sample,dim_signal,i_seq,0), MATRIX_AT(norm_sample,dim_signal,i_seq,1),MATRIX_AT(norm_sample,dim_signal,i_seq,2)); } // 前回の二乗誤差値:収束判定に用いる. @@ -191,6 +220,8 @@ /* 学習ループ */ while (1) { + // printf("dWin_out : %p, dWmid_out : %p, prevdWin_mid : %p, prevdWmid_out : %p, out_signal : %p, in_mid_net : %p, mid_out_net : %p, sigma : %p \r\n", dWin_mid, dWmid_out,prevdWin_mid, prevdWmid_out, out_signal, in_mid_net, mid_out_net, sigma); + // 終了条件を満たすか確認 if (!end_flag) { end_flag = !(iteration < maxIteration @@ -217,10 +248,21 @@ memset(prevdWmid_out, float(0), sizeof(float) * row_mid_out * col_mid_out); } + memset(dWin_mid, float(0), sizeof(float) * row_in_mid * col_in_mid); + memset(dWmid_out, float(0), sizeof(float) * row_mid_out * col_mid_out); + /* 学習ステップその1:ニューラルネットの出力信号を求める */ // 入力値を取得 - memcpy(expand_in_signal, &(norm_sample[seq * dim_signal]), sizeof(float) * dim_signal); + memcpy(expand_in_signal, &(norm_sample[(seq * dim_signal)]), sizeof(float) * dim_signal); + + /* + if ( iteration >= 0 ) { + printf("%d first 3 norm_sample : %f(%p) %f(%p) %f(%p) \r\n", iteration, norm_sample[seq * dim_signal], &(norm_sample[seq * dim_signal]), norm_sample[seq * dim_signal + 1], &(norm_sample[seq * dim_signal + 1]), norm_sample[seq * dim_signal + 2], &(norm_sample[seq * dim_signal + 2])); + printf("%d first 3 expand_in_signal : %f(%p) %f(%p) %f(%p) \r\n", iteration, expand_in_signal[0], &(expand_in_signal[0]), expand_in_signal[1], &(expand_in_signal[1]), expand_in_signal[2], &(expand_in_signal[2])); + } + */ + // SRNN特有:入力層に中間層のコピーが追加され,中間層に入力される. if (iteration == 0) { // 初回は0埋めする @@ -270,10 +312,11 @@ MATRIX_AT(sample_maxmin,2,i_dim,0), MATRIX_AT(sample_maxmin,2,i_dim,1)); } + + // printf("%d sample : %f %f %f \r\n", seq, sample[dim_signal * seq], sample[dim_signal * seq + 1], sample[dim_signal * seq + 2]); + // printf("%d output : %f(%p) %f(%p) %f(%p) \r\n", iteration, out_signal[0], &(out_signal[0]), out_signal[1], &(out_signal[1]), out_signal[2], &(out_signal[2])); // printf("%d predict : %f %f %f \r\n", iteration, predict_signal[0], predict_signal[1], predict_signal[2]); - // print_mat(Wmid_out, row_mid_out, col_mid_out); - // この時点での二乗誤差計算 squareError = 0; // 次の系列との誤差を見ている!! ここが注目ポイント @@ -286,6 +329,11 @@ } } squareError /= dim_signal; + // printf("%f \r\n", squareError); + if ( isnan(squareError) || isinf(squareError) ) { + fprintf( stderr, "SRNN LEARNING ERROR!! Learning failed (detected %f) \r\n", squareError); + exit(1); + } /* 学習の終了 */ // 終了フラグが立ち,かつ系列の最後に達していたら学習終了 @@ -305,17 +353,24 @@ end_flag = 1; } + /* + if ( iteration > 40 ) { + printf("%d sample : %f %f %f \r\n", seq, sample[dim_signal * seq], sample[dim_signal * seq + 1], sample[dim_signal * seq + 2]); + printf("%d norm_sample : %f %f %f \r\n", iteration, MATRIX_AT(norm_sample,dim_signal,seq,0), MATRIX_AT(norm_sample,dim_signal,seq,1), MATRIX_AT(norm_sample,dim_signal,seq,2)); + } + */ + /* 学習ステップその2:逆誤差伝搬 */ // 誤差信号の計算 - for (int n = 0; n < dim_signal; n++) { + for (int n_dim = 0; n_dim < dim_signal; n_dim++) { if (seq < len_seqence - 1) { - sigma[n] = (out_signal[n] - MATRIX_AT(norm_sample,dim_signal,seq+1,n)) * out_signal[n] * (1 - out_signal[n]); + sigma[n_dim] = (out_signal[n_dim] - MATRIX_AT(norm_sample,dim_signal,(seq+1),n_dim)) * out_signal[n_dim] * (1 - out_signal[n_dim]); } else { /* 末尾と先頭の誤差を取る (大抵,大きくなる) */ - sigma[n] = (out_signal[n] - MATRIX_AT(norm_sample, dim_signal,0,n)) * out_signal[n] * (1 - out_signal[n]); + sigma[n_dim] = (out_signal[n_dim] - MATRIX_AT(norm_sample,dim_signal,0,n_dim)) * out_signal[n_dim] * (1 - out_signal[n_dim]); } } - // printf("Sigma : %f %f %f \r\n", sigma[0], sigma[1], sigma[2]); + // printf("%d Sigma : %f %f %f \r\n", iteration, sigma[0], sigma[1], sigma[2]); // 出力->中間層の係数の変更量計算 for (int n = 0; n < dim_signal; n++) { @@ -369,15 +424,15 @@ } - delete [] dWin_mid; - delete [] dWmid_out; - delete [] prevdWin_mid; - delete [] prevdWmid_out; - delete [] norm_sample; - delete [] out_signal; - delete [] in_mid_net; - delete [] mid_out_net; - delete [] sigma; + // delete [] dWin_mid; + // delete [] dWmid_out; + // delete [] prevdWin_mid; + // delete [] prevdWmid_out; + // delete [] norm_sample; + // delete [] out_signal; + // delete [] in_mid_net; + // delete [] mid_out_net; + // delete [] sigma; return squareError; } @@ -385,5 +440,5 @@ // サンプルの(リ)セット void SRNN::set_sample(float* sample_data) { - memcpy(sample, sample_data, sizeof(float) * len_seqence * dim_signal); + memcpy(this->sample, sample_data, sizeof(float) * len_seqence * dim_signal); }