00001 /*************************************************************************** 00002 * Copyright (C) 2005 by Robot Group Leipzig * 00003 * martius@informatik.uni-leipzig.de * 00004 * fhesse@informatik.uni-leipzig.de * 00005 * der@informatik.uni-leipzig.de * 00006 * joergweide84@aol.com (robot12) * 00007 * * 00008 * ANY COMMERCIAL USE FORBIDDEN! * 00009 * LICENSE: * 00010 * This work is licensed under the Creative Commons * 00011 * Attribution-NonCommercial-ShareAlike 2.5 License. To view a copy of * 00012 * this license, visit http://creativecommons.org/licenses/by-nc-sa/2.5/ * 00013 * or send a letter to Creative Commons, 543 Howard Street, 5th Floor, * 00014 * San Francisco, California, 94105, USA. * 00015 * * 00016 * This program is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 00019 * * 00020 * $Log: invertmotornstep.h,v $ 00021 * Revision 1.37 2009/10/23 12:39:03 martius 00022 * added description for inspectable elements 00023 * 00024 * Revision 1.36 2009/08/07 14:40:23 martius 00025 * added new teaching interface 00026 * 00027 * Revision 1.35 2009/08/04 17:23:08 martius 00028 * removed additional constructor again and added a initial matrix into the conf 00029 * 00030 * Revision 1.34 2009/07/15 13:10:11 robot12 00031 * insert a new constructor to create the class with a giving neuron matrix 00032 * 00033 * Revision 1.33 2009/03/20 17:52:33 martius 00034 * modified teaching 00035 * 00036 * Revision 1.32 2008/05/30 11:58:27 martius 00037 * use cmath instead of math.h 00038 * 00039 * Revision 1.31 2008/04/17 14:54:44 martius 00040 * randomGen added, which is a random generator with long period and an 00041 * internal state. Each Agent has an instance and passed it to the controller 00042 * and the wiring. This is good for 00043 * a) repeatability on agent basis, 00044 * b) parallel execution as done in ode_robots 00045 * 00046 * Revision 1.30 2008/01/17 10:02:00 der 00047 * inserted some parameters. 00048 * 00049 * Revision 1.29 2007/12/13 16:42:52 martius 00050 * continuity 00051 * 00052 * Revision 1.28 2007/12/07 10:58:02 der 00053 * NoiseGenerator: method signature of add and generate changed! 00054 * IMNS: added cfactor parameter 00055 * 00056 * Revision 1.27 2007/11/07 13:36:36 martius 00057 * context sensor definition, that are inputs to S 00058 * 00059 * Revision 1.26 2007/04/02 08:21:36 martius 00060 * simple reinforcement 00061 * 00062 * Revision 1.25 2007/02/23 19:36:17 martius 00063 * S and SD matrixes separated 00064 * 00065 * Revision 1.24 2007/02/12 13:18:46 martius 00066 * teaching changed. Use standard backprop 00067 * distal learning 00068 * model compliant learning (untested) 00069 * 00070 * Revision 1.23 2007/01/26 12:03:11 martius 00071 * kwta inhibition and limitRF implemented 00072 * 00073 * Revision 1.22 2006/12/21 11:44:17 martius 00074 * commenting style for doxygen //< -> ///< 00075 * FOREACH and FOREACHC are macros for collection iteration 00076 * 00077 * Revision 1.21 2006/12/01 16:18:26 martius 00078 * S uses first and second derivative. Not really tested yet 00079 * 00080 * Revision 1.20 2006/11/29 16:22:43 martius 00081 * name is a variable of configurable and is used as such 00082 * 00083 * Revision 1.19 2006/10/23 10:47:30 martius 00084 * model as function 00085 * 00086 * Revision 1.18 2006/08/02 09:31:16 martius 00087 * calcErrorFactor moved to invertmotorcontroller 00088 * 00089 * Revision 1.17 2006/07/20 17:14:34 martius 00090 * removed std namespace from matrix.h 00091 * storable interface 00092 * abstract model and invertablemodel as superclasses for networks 00093 * 00094 * Revision 1.16 2006/07/18 15:17:16 martius 00095 * buffer operations like delayed values and smoothed values moved to invertmotorcontroller 00096 * 00097 * Revision 1.15 2006/07/18 14:47:45 martius 00098 * new regularisation of g' and g''/g' and squashP moved to invertmotorcontroller 00099 * 00100 * Revision 1.14 2006/07/14 12:23:58 martius 00101 * selforg becomes HEAD 00102 * 00103 * Revision 1.12.6.12 2006/07/10 13:05:16 martius 00104 * NON-COMMERICAL LICENSE added to controllers 00105 * 00106 * Revision 1.12.6.11 2006/07/10 11:59:23 martius 00107 * Matrixlib now in selforg 00108 * no namespace std in header files 00109 * 00110 * Revision 1.12.6.10 2006/02/24 14:46:44 martius 00111 * removed gR 00112 * 00113 * Revision 1.12.6.9 2006/02/08 15:16:24 martius 00114 * *** empty log message *** 00115 * 00116 * Revision 1.12.6.8 2006/01/31 15:30:34 martius 00117 * model does not learn if too large error. 00118 * 00119 * Revision 1.12.6.7 2006/01/18 16:49:34 martius 00120 * new Update algo (simpler and hopefully better) 00121 * 00122 * Revision 1.12.6.6 2006/01/17 16:58:40 martius 00123 * loading and storing 00124 * 00125 * Revision 1.12.6.5 2006/01/13 12:24:39 martius 00126 * motor teaching included 00127 * 00128 * Revision 1.12.6.4 2005/12/15 17:04:39 martius 00129 * min, max and so on are template functions now 00130 * 00131 * Revision 1.12.6.3 2005/11/21 17:02:46 martius 00132 * calcCandHUpdates as separat function 00133 * better formula for g' (q') using Mittelwertsatz 00134 * works great! 00135 * 00136 * Revision 1.12.6.2 2005/11/16 11:24:26 martius 00137 * moved to selforg 00138 * 00139 * Revision 1.12.6.1 2005/11/14 14:54:02 martius 00140 * cpp file is seperate now 00141 * 00142 * Revision 1.12 2005/10/27 15:46:38 martius 00143 * inspectable interface is expanded to structural information for network visualiser 00144 * 00145 * Revision 1.11 2005/10/24 11:10:27 martius 00146 * disabled exact formula for shift 00147 * 00148 * Revision 1.10 2005/10/21 16:02:49 martius 00149 * added additional model matrix S (switch in contructor) 00150 * 00151 * Revision 1.9 2005/10/21 11:55:13 martius 00152 * id is now toId 00153 * relativeE can be switched on 00154 * uses an symmetric but exact formula for shift calcuation through neuron 00155 * However g'/g'' stays -2g because implementation was making trouble 00156 * 00157 * Revision 1.8 2005/10/06 17:08:08 martius 00158 * switched to stl lists 00159 * Bias noise 00160 * correct error_factor for controller learning 00161 * 00162 * Revision 1.7 2005/09/27 10:59:47 martius 00163 * error_factor (from logaE or rootE) is member now 00164 * 00165 * Revision 1.6 2005/09/22 07:22:59 martius 00166 * proper destruction 00167 * 00168 * Revision 1.5 2005/09/21 07:31:10 martius 00169 * v does not go through g 00170 * 00171 * Revision 1.4 2005/07/28 11:16:08 martius 00172 * there is a switch for exporting just some of the internal parameters 00173 * 00174 * Revision 1.3 2005/07/27 15:44:23 martius 00175 * learning rate adaptation 00176 * 00177 * Revision 1.2 2005/07/21 15:07:59 martius 00178 * working version 00179 * squashing normalised 00180 * 00181 * Revision 1.1 2005/07/19 09:35:35 martius 00182 * invert motor space controller that iterates 00183 * over multiple time steps in past 00184 * 00185 * 00186 ***************************************************************************/ 00187 #ifndef __INVERTMOTORNSTEP_H 00188 #define __INVERTMOTORNSTEP_H 00189 00190 #include "invertmotorcontroller.h" 00191 #include "teachable.h" 00192 00193 #include <assert.h> 00194 #include <cmath> 00195 00196 #include <selforg/matrix.h> 00197 #include <selforg/noisegenerator.h> 00198 00199 typedef struct InvertMotorNStepConf { 00200 int buffersize; ///< buffersize size of the time-buffer for x,y,eta 00201 matrix::Matrix initialC; ///< initial controller matrix C (if not given then randomly chosen, see cInit, cNonDiag...) 00202 double cInit; ///< cInit size of the C matrix to initialised with. 00203 double cNonDiag; ///< cNonDiag is the size of the nondiagonal elements in respect to the diagonal (cInit) ones 00204 double cNonDiagAbs; ///< cNonDiag is the value of the nondiagonal elements 00205 bool useS; ///< useS decides whether to use the S matrix in addition to the A matrix (sees sensors) 00206 /** useSD decides whether to use the SD matrix in addition to the A 00207 matrix (sees first and second derivatives) */ 00208 bool useSD; 00209 /** number of context sensors(considered at the end of the sensor 00210 vector. If not 0, then S will only get them as input */ 00211 int numberContext; 00212 bool someInternalParams; ///< someInternalParams if true only some internal parameters are exported, all otherwise 00213 } InvertMotorNStepConf; 00214 00215 /** 00216 * class for robot controller that uses the georg's matrixlib for 00217 * direct matrix inversion for n channels 00218 * (simple one layer networks) 00219 * 00220 * Implements standart parameters: eps, rho, mu, stepnumber4avg, stepnumber4delay 00221 */ 00222 class InvertMotorNStep : public InvertMotorController, public Teachable { 00223 00224 public: 00225 InvertMotorNStep(const InvertMotorNStepConf& conf = getDefaultConf()); 00226 00227 virtual void init(int sensornumber, int motornumber, RandGen* randGen = 0); 00228 00229 virtual ~InvertMotorNStep(); 00230 00231 /// returns the number of sensors the controller was initialised with or 0 if not initialised 00232 virtual int getSensorNumber() const { return number_sensors; } 00233 /// returns the mumber of motors the controller was initialised with or 0 if not initialised 00234 virtual int getMotorNumber() const { return number_motors; } 00235 00236 /// performs one step (includes learning). 00237 /// Calulates motor commands from sensor inputs. 00238 virtual void step(const sensor* , int number_sensors, motor* , int number_motors); 00239 00240 /// performs one step without learning. Calulates motor commands from sensor inputs. 00241 virtual void stepNoLearning(const sensor* , int number_sensors, 00242 motor* , int number_motors); 00243 00244 /**** STOREABLE ****/ 00245 /** stores the controller values to a given file. */ 00246 virtual bool store(FILE* f) const; 00247 /** loads the controller values from a given file. */ 00248 virtual bool restore(FILE* f); 00249 00250 /**** INSPECTABLE ****/ 00251 virtual std::list<ILayer> getStructuralLayers() const; 00252 virtual std::list<IConnection> getStructuralConnections() const; 00253 00254 /**** TEACHING ****/ 00255 /** The given motor teaching signal is used for this timestep. 00256 It is used as a feed forward teaching signal for the controller. 00257 Please note, that the teaching signal has to be given each timestep 00258 for a continuous teaching process. 00259 */ 00260 virtual void setMotorTeachingSignal(const motor* teaching, int len); 00261 00262 /** The given sensor teaching signal (distal learning) is used for this timestep. 00263 First the belonging motor teachung signal is calculated by the inverse model. 00264 See setMotorTeachingSignal 00265 */ 00266 virtual void setSensorTeachingSignal(const sensor* teaching, int len); 00267 void getLastMotors(motor* motors, int len); 00268 void getLastSensors(sensor* sensors, int len); 00269 00270 00271 /**** New TEACHING interface ****/ 00272 /** The given motor teaching signal is used for this timestep. 00273 It is used as a feed forward teaching signal for the controller. 00274 Please note, that the teaching signal has to be given each timestep 00275 for a continuous teaching process. 00276 @param teaching: matrix with dimensions (motornumber,1) 00277 */ 00278 virtual void setMotorTeaching(const matrix::Matrix& teaching); 00279 00280 /** The given sensor teaching signal (distal learning) is used for this timestep. 00281 The belonging motor teachung signal is calculated by the inverse model. 00282 See setMotorTeaching 00283 @param teaching: matrix with dimensions (motorsensors,1) 00284 */ 00285 virtual void setSensorTeaching(const matrix::Matrix& teaching); 00286 /// returns the last motor values (useful for cross motor coupling) 00287 virtual matrix::Matrix getLastMotorValues(); 00288 /// returns the last sensor values (useful for cross sensor coupling) 00289 virtual matrix::Matrix getLastSensorValues(); 00290 00291 00292 00293 // UNUSED! OLD IMPLEMENTATION which hat some consistency arguments 00294 void calcCandHUpdatesTeaching(matrix::Matrix& C_update, matrix::Matrix& H_update, int y_delay); 00295 00296 /**** REINFORCEMENT ****/ 00297 /** set the reinforcement signal for this timestep. 00298 It is used to calculate a factor for the update. 00299 Factor = 1-0.95*reinforcement. 00300 @param reinforcement value between -1 and 1 (-1 bad, 0 neutral, 1 good) 00301 */ 00302 virtual void setReinforcement(double reinforcement); 00303 00304 00305 00306 static InvertMotorNStepConf getDefaultConf(){ 00307 InvertMotorNStepConf c; 00308 c.buffersize = 50; 00309 c.cInit = 1.0; 00310 c.cNonDiag = 0; 00311 c.useS = false; 00312 c.useSD = false; 00313 c.numberContext = 0; 00314 c.someInternalParams = true; 00315 c.cNonDiagAbs=0.0; 00316 return c; 00317 } 00318 00319 /// sets the sensor channel weights (matrix should be (getSensorNumber() x 1) 00320 void setSensorWeights(const matrix::Matrix& weights); 00321 matrix::Matrix getSensorWeights() const {return sensorweights; } 00322 /// reference to C-matrix 00323 matrix::Matrix& getC(){return C;}; 00324 00325 double getE() const {return v.multTM().val(0,0);} 00326 00327 protected: 00328 unsigned short number_sensors; 00329 unsigned short number_motors; 00330 00331 public: 00332 matrix::Matrix A; ///< Model Matrix (motors to sensors) 00333 matrix::Matrix S; ///< additional Model Matrix (sensors to sensors) 00334 matrix::Matrix SD; ///< additional Model Matrix (sensors derivatives to sensors) 00335 matrix::Matrix C; ///< Controller Matrix 00336 matrix::Matrix H; ///< Controller Bias 00337 matrix::Matrix B; ///< Model Bias 00338 protected: 00339 NoiseGenerator* BNoiseGen; ///< Noisegenerator for noisy bias 00340 NoiseGenerator* YNoiseGen; ///< Noisegenerator for noisy motor output 00341 matrix::Matrix R; ///< C*A 00342 matrix::Matrix SmallID; ///< small identity matrix in the dimension of R 00343 matrix::Matrix xsi; ///< current output error 00344 matrix::Matrix v; ///< current reconstructed error 00345 double E_val; ///< value of Error function 00346 double xsi_norm; ///< norm of matrix 00347 double xsi_norm_avg; ///< average norm of xsi (used to define whether Modell learns) 00348 double pain; ///< if the modelling error (xsi) is too high we have a pain signal 00349 matrix::Matrix* x_buffer; 00350 matrix::Matrix* y_buffer; 00351 matrix::Matrix* eta_buffer; 00352 matrix::Matrix zero_eta; // zero initialised eta 00353 matrix::Matrix x_smooth; 00354 // matrix::Matrix z; ///< membrane potential 00355 matrix::Matrix y_teaching; ///< teaching motor signal 00356 bool useTeaching; ///< flag whether there is an actual teachning signal or not 00357 double reinforcement; ///< reinforcement value (set via setReinforcement()) 00358 double reinforcefactor; ///< reinforcement factor (set to 1 every step after learning) 00359 int t_rand; ///< initial random time to avoid syncronous management of all controllers 00360 00361 matrix::Matrix sensorweights; ///< sensor channel weight (each channel gets a certain importance) 00362 00363 /** factor to teach for continuity: subsequent motor commands 00364 should not differ too much */ 00365 double continuity; 00366 double modelCompliant; ///< learning factor for model (or sensor) compliant learning 00367 int managementInterval; ///< interval between subsequent management function calls 00368 paramval inhibition; ///< inhibition strength for sparce kwta strategy (is scaled with epsC) 00369 paramval kwta; ///< (int) number of synapses that get strengthend 00370 paramval limitRF; ///< (int) receptive field of motor neurons (number of offcenter sensors) if null then no limitation. Mutual exclusive with inhibition 00371 paramval dampS; ///< damping of S matrix 00372 paramval dampC; ///< damping of C matrix 00373 paramval activeExplore; ///< decides whether and how strong the backpropagated error is used as a control signal 00374 paramval cfactor; 00375 paramval cnondiagabs; 00376 paramval cdiagabs; 00377 00378 00379 paramval noiseY; ///< noise strength for y 00380 00381 InvertMotorNStepConf conf; 00382 00383 /// puts the sensors in the ringbuffer, generate controller values and put them in the 00384 // ringbuffer as well 00385 virtual void fillBuffersAndControl(const sensor* x_, int number_sensors, 00386 motor* y_, int number_motors); 00387 00388 /// calculates the first shift into the motor space useing delayed motor values. 00389 // @param delay 0 for no delay and n>0 for n timesteps delay in the time loop 00390 virtual void calcEtaAndBufferIt(int delay); 00391 /// calculates xsi for the current time step using the delayed y values 00392 // and x delayed by one 00393 // @param delay 0 for no delay and n>0 for n timesteps delay in the time loop 00394 virtual void calcXsi(int delay); 00395 00396 /// learn H,C with motors y and corresponding sensors x 00397 // @param delay 0 for no delay and n>0 for n timesteps delay in the time loop 00398 virtual void learnController(int delay); 00399 00400 /// calculates the Update for C and H 00401 // @param delay timesteps to delay the y-values. (usually 0) 00402 // Please note that the delayed values are NOT used for the error calculation 00403 // (this is done in calcXsi()) 00404 virtual void calcCandHUpdates(matrix::Matrix& C_update, matrix::Matrix& H_update, int delay); 00405 00406 /// updates the matrix C and H 00407 virtual void updateCandH(const matrix::Matrix& C_update, const matrix::Matrix& H_update, double squashSize); 00408 00409 /// learn A, (and S) using motors y and corresponding sensors x 00410 // @param delay 0 for no delay and n>0 for n timesteps delay in the time loop 00411 virtual void learnModel(int delay); 00412 00413 /// calculates the predicted sensor values 00414 virtual matrix::Matrix model(const matrix::Matrix* x_buffer, int delay, const matrix::Matrix& y); 00415 00416 /// handles inhibition damping etc. 00417 virtual void management(); 00418 00419 /// returns controller output for given sensor values 00420 virtual matrix::Matrix calculateControllerValues(const matrix::Matrix& x_smooth); 00421 00422 /** Calculates first and second derivative and returns both in on matrix (above). 00423 We use simple discrete approximations: 00424 \f[ f'(x) = (f(x) - f(x-1)) / 2 \f] 00425 \f[ f''(x) = f(x) - 2f(x-1) + f(x-2) \f] 00426 where we have to go into the past because we do not have f(x+1). The scaling can be neglegted. 00427 */ 00428 matrix::Matrix calcDerivatives(const matrix::Matrix* buffer, int delay); 00429 00430 public: 00431 /** k-winner take all inhibition for synapses. k largest synapses are strengthed and the rest are inhibited. 00432 strong synapes are scaled by 1+(damping/k) and weak synapses are scaled by 1-(damping/(n-k)) where n is the 00433 number of synapes 00434 @param weightmatrix reference to weight matrix. Synapses for a neuron are in one row. 00435 The inhibition is done for all rows independently 00436 @param k number of synapes to strengthen 00437 @param damping strength of supression and exitation (typically 0.001) 00438 */ 00439 void kwtaInhibition(matrix::Matrix& weightmatrix, unsigned int k, double damping); 00440 00441 /** sets all connections to zero which are further away then rfSize 00442 from the diagonal. 00443 If rfSize == 1 then only main diagonal is left. 00444 If rfSize = 2: main diagonal and upper and lower side diagonal are kept and so on and so forth. 00445 */ 00446 void limitC(matrix::Matrix& weightmatrix, unsigned int rfSize); 00447 00448 00449 static double clip095(double x); 00450 static double regularizedInverse(double v); 00451 00452 }; 00453 00454 #endif