LIBRCSC Docs
Documentation for HELIOS's BASE LIBRCSC library for RoboCup 2D Simulation League.
All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
bpn1.h
Go to the documentation of this file.
1// -*-c++-*-
2
8/*
9 *Copyright:
10
11 Copyright (C) Hidehisa AKIYAMA
12
13 This code is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 3 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
27 *EndCopyright:
28 */
29
31
32#ifndef RCSC_ANN_BPN1_H
33#define RCSC_ANN_BPN1_H
34
35#include <array>
36#include <algorithm>
37#include <numeric> // inner_product
38#include <iostream>
39#include <cmath>
40
41namespace rcsc {
42
44
55 double operator()( const double & x ) const
56 {
57 return 1.0 / ( 1.0 + std::exp( - x ) );
58 }
59
65 double inverse( const double & y ) const
66 {
67 return - std::log( 1.0 / y - 1.0 );
68 }
69
75 double diffAtX( const double & x ) const
76 {
77 double s = this->operator()( x );
78 return s * ( 1.0 - s );
79 }
80
86 double diffAtY( const double & y ) const
87 {
88 // return diffAtX( inverse( y ) );
89 return y * ( 1.0 - y );
90 }
91};
92
94
99struct LinearFunc {
105 double operator()( const double & x ) const
106 {
107 return x;
108 }
109
115 double inverse( const double & y ) const
116 {
117 return y;
118 }
119
124 double diffAtX( const double & ) const
125 {
126 return 1.0;
127 }
128
133 double diffAtY( const double & ) const
134 {
135 return 1.0;
136 }
137
138};
139
141
149template < std::size_t INPUT,
150 std::size_t HIDDEN,
151 std::size_t OUTPUT,
152 typename FuncH = SigmoidFunc,
153 typename FuncO = SigmoidFunc >
155public:
156 typedef double value_type;
157
159 typedef std::array< value_type, INPUT > input_array;
161 typedef std::array< value_type, OUTPUT > output_array;
162
163private:
164
166 const value_type M_eta;
168 const value_type M_alpha;
169
171 std::array< value_type, INPUT + 1 > M_weight_i_to_h[HIDDEN];
173 std::array< value_type, INPUT + 1 > M_delta_weight_i_to_h[HIDDEN];
174
176 std::array< value_type, HIDDEN + 1 > M_weight_h_to_o[OUTPUT];
178 std::array< value_type, HIDDEN + 1 > M_delta_weight_h_to_o[OUTPUT];
179
184 mutable std::array< value_type, HIDDEN + 1 > M_hidden_layer;
185
186public:
193 : M_eta( 0.3 )
194 , M_alpha( 0.9 )
195 {
196 init();
197 }
198
204 BPNetwork1( const value_type & eta,
205 const value_type & alpha )
206 : M_eta( eta )
207 , M_alpha( alpha )
208 {
209 init();
210 }
211
218 template < typename RNG >
219 BPNetwork1( const value_type & eta,
220 const value_type & alpha,
221 RNG & rng )
222 : M_eta( eta )
223 , M_alpha( alpha )
224 {
225 init();
226 randomize( rng );
227 }
228
232 void init()
233 {
234 M_hidden_layer.assign( 0 );
235 M_hidden_layer.back() = 1;
236 for ( std::size_t i = 0; i < HIDDEN; ++i )
237 {
238 M_weight_i_to_h[i].assign( 0 );
239 M_delta_weight_i_to_h[i].assign( 0 );
240 }
241 for ( std::size_t i = 0; i < OUTPUT; ++i )
242 {
243 M_weight_h_to_o[i].assign( 0 );
244 M_delta_weight_h_to_o[i].assign( 0 );
245 }
246 }
247
252 template < typename RNG >
253 void randomize( RNG & rng )
254 {
255 for ( std::size_t i = 0; i < HIDDEN; ++i )
256 {
257 std::generate( M_weight_i_to_h[i].begin(),
258 M_weight_i_to_h[i].end(),
259 rng );
260 }
261 for ( std::size_t i = 0; i < OUTPUT; ++i )
262 {
263 std::generate( M_weight_h_to_o[i].begin(),
264 M_weight_h_to_o[i].end(),
265 rng );
266 }
267 }
268
274 void propagate( const input_array & input,
275 output_array & output ) const
276 {
277 // Input to Hidden
278 FuncH func_h;
279 for ( std::size_t i = 0; i < HIDDEN; ++i )
280 {
281 value_type sum = std::inner_product( input.begin(),
282 input.end(),
283 M_weight_i_to_h[i].begin(),
284 static_cast< value_type >( 0 ) );
285 // add bias
286 sum += M_weight_i_to_h[i].back();
287 M_hidden_layer[i] = func_h( sum );
288 }
289 // Hidden to Output
290 FuncO func_o;
291 for ( std::size_t i = 0; i < OUTPUT; ++i )
292 {
293 value_type sum = std::inner_product( M_hidden_layer.begin(),
294 M_hidden_layer.end(),
295 M_weight_h_to_o[i].begin(),
296 static_cast< value_type >( 0 ) );
297 // bias is already added
298 output[i] = func_o( sum );
299 }
300 }
301
308 const output_array & teacher )
309 {
310 output_array output;
311 propagate( input, output );
312
313 // error value mulitiplied by differential
314 output_array output_back;
315
316 // caluculate output error back
317 FuncO func_o;
318 for ( std::size_t i = 0; i < OUTPUT; ++i )
319 {
320 value_type err = teacher[i] - output[i];
321 output_back[i] = err * func_o.diffAtY( output[i] );
322 }
323
324 // caluculate hidden layer error back
325 std::array< value_type, HIDDEN > hidden_back;
326 FuncH func_h;
327 for ( std::size_t i = 0; i < HIDDEN; ++i )
328 {
329 value_type sum = 0;
330 for ( std::size_t j = 0; j < OUTPUT; ++j )
331 {
332 sum += output_back[j] * M_weight_h_to_o[j][i];
333 }
334 hidden_back[i] = sum * func_h.diffAtY( M_hidden_layer[i] );
335 }
336
337 // update weights hidden to out
338 for ( std::size_t i = 0; i < OUTPUT; ++i )
339 {
340 for ( std::size_t j = 0; j < HIDDEN + 1; ++j )
341 {
342 M_delta_weight_h_to_o[i][j]
343 = M_eta * M_hidden_layer[j] * output_back[i]
344 + M_alpha * M_delta_weight_h_to_o[i][j];
345 M_weight_h_to_o[i][j]
346 += M_delta_weight_h_to_o[i][j];
347 //+= M_epsilon * ( M_hidden_layer[i] * output_back[j] );
348 }
349 }
350
351 // update weights input to hidden
352 for ( std::size_t i = 0; i < HIDDEN; ++i )
353 {
354 for ( std::size_t j = 0; j < INPUT; ++j )
355 {
356 M_delta_weight_i_to_h[i][j]
357 = M_eta * input[j] * hidden_back[i]
358 + M_alpha * M_delta_weight_i_to_h[i][j];
359 M_weight_i_to_h[i][j]
360 += M_delta_weight_i_to_h[i][j];
361 //+= M_epsilon * ( input[j] * hidden_back[i] );
362 }
363 }
364 // update input layer bias
365 for ( std::size_t i = 0; i < HIDDEN; ++i )
366 {
367 M_delta_weight_i_to_h[i][INPUT]
368 = M_eta * 1.0 * hidden_back[i]
369 + M_alpha * M_delta_weight_i_to_h[i][INPUT];
370 M_weight_i_to_h[i][INPUT]
371 += M_delta_weight_i_to_h[i][INPUT];
372 //+= M_epsilon * ( input[j] * hidden_back[i] );
373 }
374
375 // calcluate error after training
376 value_type total_error = 0;
377 propagate( input, output );
378 for ( std::size_t i = 0; i < OUTPUT; ++i )
379 {
380 total_error += std::pow( teacher[i] - output[i], 2 );
381 }
382 //std::cout << " error = " << total_error << std::endl;
383 return total_error;
384 }
385
386
388 // stream I/O
389
395 bool read( std::istream & is )
396 {
397 for ( std::size_t i = 0; i < HIDDEN; ++i )
398 {
399 for ( std::size_t j = 0; j < INPUT + 1; ++j )
400 {
401 if ( ! is.good() ) return false;
402 is >> M_weight_i_to_h[i][j];
403 }
404 }
405 for ( std::size_t i = 0; i < OUTPUT; ++i )
406 {
407 for ( std::size_t j = 0; j < HIDDEN + 1; ++ j )
408 {
409 if ( ! is.good() ) return false;
410 is >> M_weight_h_to_o[i][j];
411 }
412 }
413 return true;
414 }
415
421 std::ostream & print( std::ostream & os ) const
422 {
423 for ( std::size_t i = 0; i < HIDDEN; ++i )
424 {
425 std::copy( M_weight_i_to_h[i].begin(),
426 M_weight_i_to_h[i].end(),
427 std::ostream_iterator< value_type >( os, " " ) );
428 }
429 for ( std::size_t i = 0; i < OUTPUT; ++i )
430 {
431 std::copy( M_weight_h_to_o[i].begin(),
432 M_weight_h_to_o[i].end(),
433 std::ostream_iterator< value_type >( os, " " ) );
434 }
435 return os;
436 }
437};
438
439}
440
441#endif
Back Propagetion Neural Network.
Definition: bpn1.h:154
BPNetwork1(const value_type &eta, const value_type &alpha)
create with learning parameter
Definition: bpn1.h:204
std::ostream & print(std::ostream &os) const
put network structure to stream by "one" line
Definition: bpn1.h:421
std::array< value_type, INPUT > input_array
typedef of the input array type that uses template parameter.
Definition: bpn1.h:159
BPNetwork1()
default constructor
Definition: bpn1.h:192
BPNetwork1(const value_type &eta, const value_type &alpha, RNG &rng)
create with random number generator
Definition: bpn1.h:219
void propagate(const input_array &input, output_array &output) const
simulate network.
Definition: bpn1.h:274
void init()
init member variables
Definition: bpn1.h:232
double value_type
typedef of the value type
Definition: bpn1.h:156
bool read(std::istream &is)
read network structure from input stream.
Definition: bpn1.h:395
std::array< value_type, OUTPUT > output_array
typedef of the output array type that uses template parameter.
Definition: bpn1.h:161
void randomize(RNG &rng)
create unit connection randomly
Definition: bpn1.h:253
value_type train(const input_array &input, const output_array &teacher)
update unit connection weights using teacher signal
Definition: bpn1.h:307
linear function and differenceial function objcet
Definition: bpn1.h:99
double operator()(const double &x) const
functional operator
Definition: bpn1.h:105
double diffAtY(const double &) const
differencial function for y
Definition: bpn1.h:133
double diffAtX(const double &) const
differencial function for x
Definition: bpn1.h:124
double inverse(const double &y) const
inverse function
Definition: bpn1.h:115
sigmoid function and differencial function object
Definition: bpn1.h:49
double diffAtY(const double &y) const
differencial function for y
Definition: bpn1.h:86
double diffAtX(const double &x) const
Definition: bpn1.h:75
double operator()(const double &x) const
functional operator
Definition: bpn1.h:55
double inverse(const double &y) const
inverse function
Definition: bpn1.h:65