00001
00002
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifndef RCSC_ANN_BPN1_H
00033 #define RCSC_ANN_BPN1_H
00034
00035 #include <boost/array.hpp>
00036
00037 #include <algorithm>
00038 #include <numeric>
00039 #include <iostream>
00040 #include <cmath>
00041
00042 namespace rcsc {
00043
00045
00050 struct SigmoidFunc {
00056 double operator()( const double & x ) const
00057 {
00058 return 1.0 / ( 1.0 + std::exp( - x ) );
00059 }
00060
00066 double inverse( const double & y ) const
00067 {
00068 return - std::log( 1.0 / y - 1.0 );
00069 }
00070
00076 double diffAtX( const double & x ) const
00077 {
00078 double s = this->operator()( x );
00079 return s * ( 1.0 - s );
00080 }
00081
00087 double diffAtY( const double & y ) const
00088 {
00089
00090 return y * ( 1.0 - y );
00091 }
00092 };
00093
00095
00100 struct LinearFunc {
00106 double operator()( const double & x ) const
00107 {
00108 return x;
00109 }
00110
00116 double inverse( const double & y ) const
00117 {
00118 return y;
00119 }
00120
00125 double diffAtX( const double & ) const
00126 {
00127 return 1.0;
00128 }
00129
00134 double diffAtY( const double & ) const
00135 {
00136 return 1.0;
00137 }
00138
00139 };
00140
00142
00150 template < std::size_t INPUT,
00151 std::size_t HIDDEN,
00152 std::size_t OUTPUT,
00153 typename FuncH = SigmoidFunc,
00154 typename FuncO = SigmoidFunc >
00155 class BPNetwork1 {
00156 public:
00157 typedef double value_type;
00158
00160 typedef boost::array< value_type, INPUT > input_array;
00162 typedef boost::array< value_type, OUTPUT > output_array;
00163
00164 private:
00165
00167 const value_type M_eta;
00169 const value_type M_alpha;
00170
00172 boost::array< value_type, INPUT + 1 > M_weight_i_to_h[HIDDEN];
00174 boost::array< value_type, INPUT + 1 > M_delta_weight_i_to_h[HIDDEN];
00175
00177 boost::array< value_type, HIDDEN + 1 > M_weight_h_to_o[OUTPUT];
00179 boost::array< value_type, HIDDEN + 1 > M_delta_weight_h_to_o[OUTPUT];
00180
00185 mutable boost::array< value_type, HIDDEN + 1 > M_hidden_layer;
00186
00187 public:
00193 BPNetwork1()
00194 : M_eta( 0.3 )
00195 , M_alpha( 0.9 )
00196 {
00197 init();
00198 }
00199
00205 BPNetwork1( const value_type & eta,
00206 const value_type & alpha )
00207 : M_eta( eta )
00208 , M_alpha( alpha )
00209 {
00210 init();
00211 }
00212
00219 template < typename RNG >
00220 BPNetwork1( const value_type & eta,
00221 const value_type & alpha,
00222 RNG & rng )
00223 : M_eta( eta )
00224 , M_alpha( alpha )
00225 {
00226 init();
00227 randomize( rng );
00228 }
00229
00233 void init()
00234 {
00235 M_hidden_layer.assign( 0 );
00236 M_hidden_layer.back() = 1;
00237 for ( std::size_t i = 0; i < HIDDEN; ++i )
00238 {
00239 M_weight_i_to_h[i].assign( 0 );
00240 M_delta_weight_i_to_h[i].assign( 0 );
00241 }
00242 for ( std::size_t i = 0; i < OUTPUT; ++i )
00243 {
00244 M_weight_h_to_o[i].assign( 0 );
00245 M_delta_weight_h_to_o[i].assign( 0 );
00246 }
00247 }
00248
00253 template < typename RNG >
00254 void randomize( RNG & rng )
00255 {
00256 for ( std::size_t i = 0; i < HIDDEN; ++i )
00257 {
00258 std::generate( M_weight_i_to_h[i].begin(),
00259 M_weight_i_to_h[i].end(),
00260 rng );
00261 }
00262 for ( std::size_t i = 0; i < OUTPUT; ++i )
00263 {
00264 std::generate( M_weight_h_to_o[i].begin(),
00265 M_weight_h_to_o[i].end(),
00266 rng );
00267 }
00268 }
00269
00275 void propagate( const input_array & input,
00276 output_array & output ) const
00277 {
00278
00279 FuncH func_h;
00280 for ( std::size_t i = 0; i < HIDDEN; ++i )
00281 {
00282 value_type sum = std::inner_product( input.begin(),
00283 input.end(),
00284 M_weight_i_to_h[i].begin(),
00285 static_cast< value_type >( 0 ) );
00286
00287 sum += M_weight_i_to_h[i].back();
00288 M_hidden_layer[i] = func_h( sum );
00289 }
00290
00291 FuncO func_o;
00292 for ( std::size_t i = 0; i < OUTPUT; ++i )
00293 {
00294 value_type sum = std::inner_product( M_hidden_layer.begin(),
00295 M_hidden_layer.end(),
00296 M_weight_h_to_o[i].begin(),
00297 static_cast< value_type >( 0 ) );
00298
00299 output[i] = func_o( sum );
00300 }
00301 }
00302
00308 value_type train( const input_array & input,
00309 const output_array & teacher )
00310 {
00311 output_array output;
00312 propagate( input, output );
00313
00314
00315 output_array output_back;
00316
00317
00318 FuncO func_o;
00319 for ( std::size_t i = 0; i < OUTPUT; ++i )
00320 {
00321 value_type err = teacher[i] - output[i];
00322 output_back[i] = err * func_o.diffAtY( output[i] );
00323 }
00324
00325
00326 boost::array< value_type, HIDDEN > hidden_back;
00327 FuncH func_h;
00328 for ( std::size_t i = 0; i < HIDDEN; ++i )
00329 {
00330 value_type sum = 0;
00331 for ( std::size_t j = 0; j < OUTPUT; ++j )
00332 {
00333 sum += output_back[j] * M_weight_h_to_o[j][i];
00334 }
00335 hidden_back[i] = sum * func_h.diffAtY( M_hidden_layer[i] );
00336 }
00337
00338
00339 for ( std::size_t i = 0; i < OUTPUT; ++i )
00340 {
00341 for ( std::size_t j = 0; j < HIDDEN + 1; ++j )
00342 {
00343 M_delta_weight_h_to_o[i][j]
00344 = M_eta * M_hidden_layer[j] * output_back[i]
00345 + M_alpha * M_delta_weight_h_to_o[i][j];
00346 M_weight_h_to_o[i][j]
00347 += M_delta_weight_h_to_o[i][j];
00348
00349 }
00350 }
00351
00352
00353 for ( std::size_t i = 0; i < HIDDEN; ++i )
00354 {
00355 for ( std::size_t j = 0; j < INPUT; ++j )
00356 {
00357 M_delta_weight_i_to_h[i][j]
00358 = M_eta * input[j] * hidden_back[i]
00359 + M_alpha * M_delta_weight_i_to_h[i][j];
00360 M_weight_i_to_h[i][j]
00361 += M_delta_weight_i_to_h[i][j];
00362
00363 }
00364 }
00365
00366 for ( std::size_t i = 0; i < HIDDEN; ++i )
00367 {
00368 M_delta_weight_i_to_h[i][INPUT]
00369 = M_eta * 1.0 * hidden_back[i]
00370 + M_alpha * M_delta_weight_i_to_h[i][INPUT];
00371 M_weight_i_to_h[i][INPUT]
00372 += M_delta_weight_i_to_h[i][INPUT];
00373
00374 }
00375
00376
00377 value_type total_error = 0;
00378 propagate( input, output );
00379 for ( std::size_t i = 0; i < OUTPUT; ++i )
00380 {
00381 total_error += std::pow( teacher[i] - output[i], 2.0 );
00382 }
00383
00384 return total_error;
00385 }
00386
00387
00389
00390
00396 bool read( std::istream & is )
00397 {
00398 for ( std::size_t i = 0; i < HIDDEN; ++i )
00399 {
00400 for ( std::size_t j = 0; j < INPUT + 1; ++j )
00401 {
00402 if ( ! is.good() ) return false;
00403 is >> M_weight_i_to_h[i][j];
00404 }
00405 }
00406 for ( std::size_t i = 0; i < OUTPUT; ++i )
00407 {
00408 for ( std::size_t j = 0; j < HIDDEN + 1; ++ j )
00409 {
00410 if ( ! is.good() ) return false;
00411 is >> M_weight_h_to_o[i][j];
00412 }
00413 }
00414 return true;
00415 }
00416
00422 std::ostream & print( std::ostream & os ) const
00423 {
00424 for ( std::size_t i = 0; i < HIDDEN; ++i )
00425 {
00426 std::copy( M_weight_i_to_h[i].begin(),
00427 M_weight_i_to_h[i].end(),
00428 std::ostream_iterator< value_type >( os, " " ) );
00429 }
00430 for ( std::size_t i = 0; i < OUTPUT; ++i )
00431 {
00432 std::copy( M_weight_h_to_o[i].begin(),
00433 M_weight_h_to_o[i].end(),
00434 std::ostream_iterator< value_type >( os, " " ) );
00435 }
00436 return os;
00437 }
00438 };
00439
00440 }
00441
00442 #endif