Simple Recurrent Neural Network Predictor

Dependents:   WeatherPredictor

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);
 }