00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef LEARN_SOFM_C_DEFINED
00039 #define LEARN_SOFM_C_DEFINED
00040
00041 #include "Learn/SOFM.H"
00042 #include "Image/CutPaste.H"
00043 #include "GUI/DebugWin.H"
00044 #include <fcntl.h>
00045 #include <stdio.h>
00046
00047 SOFM::SOFM(const char *net_name, int InputSize, int x, int y){
00048
00049
00050 name = net_name;
00051 MapSizeX = x;
00052 MapSizeY = y;
00053
00054 InputLayer = new Layer;
00055 KohonenLayer = new Layer;
00056
00057
00058 InputLayer->Units = InputSize;
00059 InputLayer->Output = new double[InputSize];
00060
00061
00062 KohonenLayer->Units = x*y;
00063 KohonenLayer->Output = new double[x*y];
00064 KohonenLayer->Weight = new float*[x*y];
00065 KohonenLayer->StepSizeX = new double[x*y];
00066 KohonenLayer->StepSizeY = new double[x*y];
00067 KohonenLayer->dScoreMean = new double[x*y];
00068 KohonenLayer->score = new double[x*y];
00069 KohonenLayer->BadDim = new int[x*y];
00070 KohonenLayer->Lambda = new double[x*y];
00071
00072 for (int i=0; i<KohonenLayer->Units; i++){
00073 KohonenLayer->Weight[i] = new float[InputLayer->Units];
00074 }
00075
00076
00077 itsWinner = -1;
00078 itsLooser = -1;
00079 KohonenAlpha = 0;
00080 OutAlpha = 0 ;
00081 StepAlpha = 0;
00082 Gamma = 0;
00083 Sigma = 0.1;
00084
00085 itsLearningTime = 0;
00086 }
00087
00088 void SOFM::InitSofm(){
00089
00090 for(int i=0; i<KohonenLayer->Units; i++){
00091 KohonenLayer->StepSizeX[i] = -20;
00092 KohonenLayer->StepSizeY[i] = -20;
00093 KohonenLayer->dScoreMean[i] = 0;
00094 KohonenLayer->score[i] = 0;
00095 KohonenLayer->BadDim[i] = 0;
00096 KohonenLayer->Lambda[i] = 0;
00097 }
00098 }
00099
00100 double SOFM::RandomRange(double Low, double High){
00101 return ( (double) rand() / RAND_MAX) * (High - Low) + Low;
00102 }
00103
00104 double SOFM::RandomBinaryRange(double Low, double High){
00105 int i;
00106 i = (int)(1.0*rand()/(RAND_MAX+1.0));
00107 if (i)
00108 return High;
00109 else
00110 return Low;
00111 }
00112
00113
00114 void SOFM::RandomWeights(int min, int max){
00115 initRandomNumbers();
00116 for (int i=0; i<KohonenLayer->Units; i++){
00117 for (int j=0; j<InputLayer->Units; j++){
00118 KohonenLayer->Weight[i][j] = (float)RandomRange(min, max);
00119 }
00120 }
00121 }
00122
00123 void SOFM::ZeroWeights(){
00124
00125 for (int i=0; i<KohonenLayer->Units; i++){
00126 for (int j=0; j<InputLayer->Units; j++){
00127 KohonenLayer->Weight[i][j] = 0;
00128 }
00129 }
00130 }
00131
00132
00133 SOFM::~SOFM(){
00134 delete InputLayer;
00135 delete KohonenLayer;
00136 }
00137
00138
00139 void SOFM::SetInput(float *in){
00140 for (int i=0; i<InputLayer->Units; i++){
00141 InputLayer->Output[i] = in[i];
00142 }
00143 }
00144
00145 void SOFM::setInput(const std::vector<double> &in){
00146 for (int i=0; i<InputLayer->Units; i++){
00147 InputLayer->Output[i] = in[i];
00148 }
00149 }
00150
00151 void SOFM::setInput(const Image<float> &in){
00152 for (int i=0; i<InputLayer->Units; i++){
00153 InputLayer->Output[i] = in[i];
00154 }
00155 }
00156
00157 Image<float> SOFM::getMap(){
00158
00159 Image<float> sofmOut(MapSizeX,MapSizeY,NO_INIT);
00160
00161
00162 Image<float>::iterator dest_itr = sofmOut.beginw();
00163
00164 int i=0;
00165 for (Image<float>::iterator itr = sofmOut.beginw(), stop = sofmOut.endw();
00166 itr != stop; itr++, dest_itr++, i++) {
00167 *dest_itr = (float)KohonenLayer->Output[i];
00168 }
00169
00170 return sofmOut;
00171
00172 }
00173
00174 Image<float> SOFM::getActMap(){
00175
00176 Image<float> sofmOut(MapSizeX,MapSizeY,NO_INIT);
00177
00178
00179 Image<float>::iterator dest_itr = sofmOut.beginw();
00180
00181 int i=0;
00182 for (Image<float>::iterator itr = sofmOut.beginw(), stop = sofmOut.endw();
00183 itr != stop; itr++, dest_itr++, i++) {
00184 *dest_itr = (float)KohonenLayer->Output[i];
00185 }
00186
00187 return sofmOut;
00188
00189 }
00190
00191 Image<PixRGB<byte> > SOFM::getWeightsImage(){
00192
00193
00194 int i=0;
00195 Image<PixRGB<byte> > sofmOut;
00196
00197 if (InputLayer->Units == 3)
00198 {
00199 sofmOut = Image<PixRGB<byte> >(MapSizeX,MapSizeY,NO_INIT);
00200
00201
00202 Image<PixRGB<byte> >::iterator dest_itr = sofmOut.beginw();
00203
00204 for (Image<PixRGB<byte> >::iterator itr = sofmOut.beginw(), stop = sofmOut.endw();
00205 itr != stop; itr++, dest_itr++, i++) {
00206 *dest_itr = PixRGB<byte>(KohonenLayer->Weight[i][0], KohonenLayer->Weight[i][1], KohonenLayer->Weight[i][2]);
00207 }
00208 } else {
00209 int patchSize = (int)sqrt(InputLayer->Units);
00210 int w = MapSizeX*patchSize;
00211 int h = MapSizeY*patchSize;
00212 Image<float> tmp(w,h,NO_INIT);
00213
00214 for(int j=0; j<MapSizeY; j++)
00215 for(int i=0; i<MapSizeX; i++)
00216 {
00217 int weightIdx = j*MapSizeY + i;
00218 Image<float> patch(patchSize, patchSize, NO_INIT);
00219 for(uint pix=0; pix<patch.size(); pix++)
00220 patch[pix] = KohonenLayer->Weight[weightIdx][pix];
00221 inplaceNormalize(patch, 0.0F, 255.0F);
00222 inplacePaste(tmp, patch, Point2D<int>(i*patchSize,j*patchSize));
00223 }
00224
00225 sofmOut = toRGB(tmp);
00226
00227 }
00228
00229
00230 return sofmOut;
00231
00232 }
00233
00234 std::vector<float> SOFM::getWeights(const Point2D<int> loc)
00235 {
00236 std::vector<float> weights;
00237
00238 int weightIdx = loc.j*MapSizeY + loc.i;
00239 for(int i=0; i<InputLayer->Units; i++)
00240 weights.push_back(KohonenLayer->Weight[weightIdx][i]);
00241
00242 return weights;
00243
00244 }
00245
00246
00247 void SOFM::Propagate(DISTANCE_MEASURE dm){
00248
00249 double minOut = +HUGE_VAL, maxOut = -HUGE_VAL;
00250 int winner = -1, looser = -1;
00251
00252
00253 for (int i=0; i<KohonenLayer->Units; i++){
00254
00255 switch (dm)
00256 {
00257 case EUCLIDEAN:
00258 {
00259
00260 double sum = 0;
00261 for(int j=0; j<InputLayer->Units; j++)
00262 {
00263 double out = InputLayer->Output[j];
00264 double weight = KohonenLayer->Weight[i][j];
00265 sum += (out - weight)*(out - weight);
00266 }
00267 KohonenLayer->Output[i] = sqrt(sum);
00268 }
00269 break;
00270 case KL:
00271 {
00272
00273 double sum = 0;
00274 for(int j=0; j<InputLayer->Units; j++){
00275 double out = InputLayer->Output[j];
00276 double weight = KohonenLayer->Weight[i][j];
00277 sum += weight*log(weight/out);
00278 }
00279 KohonenLayer->Output[i] = fabs(sum);
00280 }
00281 break;
00282 case L2GMM:
00283 {
00284
00285
00286
00287 }
00288 }
00289
00290
00291 if (KohonenLayer->Output[i] < minOut){
00292 minOut = KohonenLayer->Output[i];
00293 winner = i;
00294 }
00295 if (KohonenLayer->Output[i] > maxOut){
00296 maxOut = KohonenLayer->Output[i];
00297 looser = i;
00298 }
00299
00300 }
00301
00302 itsWinner = winner;
00303 itsWinnerValue = minOut;
00304 itsLooser = looser;
00305 itsLooserValue = maxOut;
00306
00307 }
00308
00309 double SOFM::Neighborhood(int i){
00310
00311 double Distance;
00312 int iRow, iCol, jRow, jCol;
00313
00314 iRow = i / MapSizeX; jRow = itsWinner / MapSizeX;
00315 iCol = i % MapSizeX; jCol = itsWinner % MapSizeX;
00316
00317 Distance = sqrt(((iRow-jRow)*(iRow-jRow)) + ((iCol-jCol)*(iCol-jCol)));
00318
00319 return exp(-(Distance*Distance) / (2*(Sigma*Sigma)));
00320 }
00321
00322 Point2D<int> SOFM::getWinner(double& val)
00323 {
00324 int y = itsWinner/MapSizeX;
00325 int x = itsWinner - (y*MapSizeX);
00326
00327 val = itsWinnerValue;
00328
00329 return Point2D<int>(x,y);
00330 }
00331
00332
00333 void SOFM::Train(float *Input, float *Target, double score){
00334
00335 double Out, Weight, Lambda=0;
00336
00337
00338 for(int i=0; i<KohonenLayer->Units; i++){
00339 Lambda = Neighborhood(i);
00340 if (Lambda > 0.000001){
00341 for(int j=0; j<InputLayer->Units; j++){
00342 Out = Input[j];
00343 Weight = KohonenLayer->Weight[i][j];
00344 KohonenLayer->Weight[i][j] += KohonenAlpha * Lambda * (Out - Weight);
00345 }
00346 }
00347 KohonenLayer->Lambda[i] = Lambda;
00348
00349
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 }
00377
00378 void SOFM::organize(std::vector<double> &input){
00379
00380 double Out, Weight, Lambda=0;
00381
00382
00383 for(int i=0; i<KohonenLayer->Units; i++){
00384 Lambda = Neighborhood(i);
00385 if (Lambda > 0.000001){
00386 for(int j=0; j<InputLayer->Units; j++){
00387 Out = input[j];
00388 Weight = KohonenLayer->Weight[i][j];
00389 KohonenLayer->Weight[i][j] += KohonenAlpha * Lambda * (Out - Weight);
00390 }
00391 }
00392 KohonenLayer->Lambda[i] = Lambda;
00393
00394
00395 }
00396
00397 }
00398
00399 void SOFM::organize(const Image<float>& input){
00400
00401 double Out, Weight, Lambda=0;
00402
00403
00404 SetLearningRate(itsLearningTime++);
00405
00406
00407 for(int i=0; i<KohonenLayer->Units; i++){
00408 Lambda = Neighborhood(i);
00409 if (Lambda > 0.000001){
00410 for(int j=0; j<InputLayer->Units; j++){
00411 Out = input[j];
00412 Weight = KohonenLayer->Weight[i][j];
00413
00414 KohonenLayer->Weight[i][j] += 1 * Lambda * (Out - Weight);
00415 }
00416 }
00417 KohonenLayer->Lambda[i] = Lambda;
00418
00419
00420 }
00421
00422 }
00423
00424 void SOFM::SetLearningRate(unsigned long long learning_time){
00425
00426
00427 KohonenAlpha = 0.1 * pow(0.001, (double) learning_time / 1000);
00428 OutAlpha = 1;
00429 StepAlpha = 0.05;
00430 Gamma = 0.05;
00431
00432
00433 Sigma = 0.5 + ( MapSizeX * pow(0.2, (double) learning_time / 1000));
00434
00435
00436
00437
00438 }
00439
00440 void SOFM::ReadNet(const char *filename){
00441 int fd;
00442 int in, sizeX, sizeY;
00443
00444 if ((fd = open(filename, 0, 0644)) == -1) return;
00445
00446 printf("Reading from %s\n", filename);
00447
00448 if(read(fd, (char *) &in, sizeof(int)) != sizeof(int)) LFATAL("fread error");
00449 if(read(fd, (char *) &sizeX, sizeof(int)) != sizeof(int)) LFATAL("fread error");
00450 if(read(fd, (char *) &sizeY, sizeof(int)) != sizeof(int)) LFATAL("fread error");
00451 if(read(fd, (char *) &itsLearningTime, sizeof(itsLearningTime)) != sizeof(itsLearningTime)) LFATAL("fread error");
00452
00453 printf("%i %i %i %llu\n", in, sizeX, sizeY, itsLearningTime);
00454
00455
00456
00457 for (int i=0; i<KohonenLayer->Units; i++){
00458 int sz = sizeof(float)*InputLayer->Units;
00459 if(read(fd, KohonenLayer->Weight[i], sz) != sz) LFATAL("fread failed");
00460 }
00461
00462 close(fd);
00463
00464 }
00465
00466 void SOFM::WriteNet(const char *filename){
00467 int fd;
00468
00469 if ((fd = creat(filename, 0644)) == -1) {
00470 printf("Can not open %s for saving\n", filename);
00471 return;
00472 }
00473
00474
00475 if(write(fd, (char *) &InputLayer->Units, sizeof(int)) != sizeof(int)) LFATAL("write failed");
00476 if(write(fd, (char *) &MapSizeX, sizeof(int)) != sizeof(int)) LFATAL("write failed");
00477 if(write(fd, (char *) &MapSizeY, sizeof(int)) != sizeof(int)) LFATAL("write failed");
00478 if(write(fd, (char *) &itsLearningTime, sizeof(itsLearningTime)) != sizeof(itsLearningTime)) LFATAL("write failed");
00479
00480
00481
00482 for (int i=0; i<KohonenLayer->Units; i++){
00483 int sz = sizeof(float)*InputLayer->Units;
00484 if(write(fd, KohonenLayer->Weight[i], sz) != sz) LFATAL("write failed");
00485 }
00486
00487 close(fd);
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 #endif // LEARN_SOFM_C_DEFINED