CvANN_MLP::calc_output_scale: scaling issue (Bug #558)


Added by eunyoung kim over 14 years ago. Updated over 14 years ago.


Status:Done Start date:
Priority:High Due date:
Assignee:Vadim Pisarevsky % Done:

0%

Category:ml
Target version:-
Affected version: Operating System:
Difficulty: HW Platform:
Pull request:

Description

It is saying that it want to map mj..Mj to m..M, but it looks like the other way around.
Because of this, it is failing to go on second round with UPDATE_WEIGHT option. It just crashes after reporting out of range problem.

Here is my simple testing code, which is training for a XOR problem.

#include "ml.h" 
#include "cxcore.h" 
#include "cv.h" 
#include "stdio.h" 

int main(){
  //XOR input
  double in[]={ 0 ,0,
                1, 0,
                0, 1,
                1, 1};
  double out[]={ 0,
                 1,
                 1,
                 0};

  const int IVS = 2; // Input Vector Size
  const int OVS = 1; // Output Vector Size
  const int HN = 10; // Number of Hidden nodes
  const int NV= 4;   //Number of Training Vector

  int layer[] = { IVS, HN, OVS};

  [[CvMat]] *input =cvCreateMat( NV, IVS, CV_64FC1);
  [[CvMat]] *output =cvCreateMat( NV, OVS, CV_64FC1);
  [[CvMat]] *p_output =cvCreateMat( NV, OVS, CV_64FC1);
  [[CvMat]] *layersize =cvCreateMat( 1 , 3 , CV_32SC1);

  cvInitMatHeader(input, NV, IVS, CV_64FC1, in);
  cvInitMatHeader(output, NV, OVS, CV_64FC1, out);
  cvInitMatHeader(layersize, 1, 3, CV_32SC1, layer);

  [[CvANN]]_MLP train_model(layersize, [[CvANN]]_MLP::SIGMOID_SYM,1,1);
  std::cout<< " =========== =========== =========== =========== ==========="<<std::endl;
  std::cout<< "  * First Iteration with initialzation of weights"<<std::endl;
  std::cout<< " =========== =========== =========== =========== ==========="<<std::endl;
  int iter = train_model.train(  input,
                                 output,
                                 NULL,
                                 0,
                                 [[CvANN]]_MLP_TrainParams( cvTermCriteria ( CV_TERMCRIT_ITER |
                                                                         CV_TERMCRIT_EPS,
                                                                         5000,0.001),
                                   [[CvANN]]_MLP_TrainParams::RPROP,
                                   0.1,0.1),
                                 0
                                 //+ [[CvANN]]_MLP::NO_OUTPUT_SCALE
                              );

  std::cout << " * iteration :"<<iter<<std::endl;
  train_model.predict( input, p_output );
  for(int i=0; i<NV;i++){
    std::cout<< CV_MAT_ELEM(*input,double,i,0) << " ," << CV_MAT_ELEM(*input,double,i,1)
             << " : " << CV_MAT_ELEM(*p_output,double,i,0) <<std::endl;

  }
  train_model.save( "/scratch/eunyokim/src/Regina_TempCode/OpenCV_XOR_TEST/firstModel.xml");
  std::cout<< " =========== =========== =========== =========== ==========="<<std::endl;
  std::cout<< "  * Second Iteration without initialzation of weights"<<std::endl;
  std::cout<< " =========== =========== =========== =========== ==========="<<std::endl;

  int iter2 = train_model.train(  input,
                                 output,
                                 NULL,
                                 0,
                                 [[CvANN]]_MLP_TrainParams( cvTermCriteria ( CV_TERMCRIT_ITER |
                                                                         CV_TERMCRIT_EPS,
                                                                         5000,0.001),
                                   [[CvANN]]_MLP_TrainParams::RPROP,
                                   0.1,0.1),
                                 0
                                 +CvANN_MLP::UPDATE_WEIGHTS
                                 //+ [[CvANN]]_MLP::NO_OUTPUT_SCALE
                              );
  std::cout << " * iteration :"<<iter2<<std::endl;
  train_model.save( "/scratch/eunyokim/src/Regina_TempCode/OpenCV_XOR_TEST/secondModel.xml");

  train_model.predict( input, p_output );
  for(int i=0; i<NV;i++){
    std::cout<< CV_MAT_ELEM(*input,double,i,0) << " ," << CV_MAT_ELEM(*input,double,i,1)
             << " : " << CV_MAT_ELEM(*p_output,double,i,0) <<std::endl;

  }

}

And output looks like following:


h11. =========== =========== ===========

* First Iteration with initialzation of weights

h11. =========== =========== ===========

* iteration :17
0 ,0 : 0.00444597
1 ,0 : 1.01488
0 ,1 : 1.00985
1 ,1 : 0.00256477

h11. =========== =========== ===========

* Second Iteration without initialzation of weights

h11. =========== =========== ===========

[[OpenCV]] Error: One of arguments' values is out of range (Some of new output training vector
components run exceed the original range too much) in [[CvANN]]_MLP::calc_output_scale, file
/scratch/eunyokim/src/OpenCV/opencv/modules/ml/src/ann_mlp.cpp, line 641
terminate called after throwing an instance of 'cv::Exception'
what(): /scratch/eunyokim/src/OpenCV/opencv/modules/ml/src/ann_mlp.cpp:641: error: (-
211) Some of new output training vector components run exceed the original range too much
in function [[CvANN]]_MLP::calc_output_scale
Abort trap

But if I change the source code file of opencv/modules/ml/src/ann_mlp.cpp for the part of calc_output_scale. It looks fine at a glance. What I did is just simply switched scale and inv_scale variable.

if( reset_weights )
        for( j = 0; j < vcount; j++ )
        {
            // map mj..Mj to m..M
            double mj = scale[j*2], Mj = scale[j*2+1];
            double a, b;
            double delta = Mj - mj;
            if( delta < DBL_EPSILON )
                a = 1, b = (M + m - Mj - mj)*0.5;
            else
                a = (M - m)/delta, b = m - mj*a;
            //inv_scale[j*2] = a; inv_scale[j*2+1] = b;
            scale[j*2] = a; scale[j*2+1] = b;
            a = 1./a; b = -b*a;
            std::cout<<", a ="<<a<<" ,b = "<<b;
            //scale[j*2] = a; scale[j*2+1] = b;
            inv_scale[j*2] = a; inv_scale[j*2+1] = b;
        }


h11. =========== =========== ===========

* First Iteration with initialzation of weights

h11. =========== =========== ===========

prepare to train
count=4
fr0 :0 dr0 :0t(0,0) : 0
scaler0 :0 , scaler1: 0
fr0 :0 dr0 :1t(1,0) : 1
scaler0 :0 , scaler1: 1
fr0 :0 dr0 :1t(2,0) : 1
scaler0 :0 , scaler1: 1
fr0 :0 dr0 :0t(3,0) : 0
scaler0 :0 , scaler1: 1
mj = 0 ,Mj = 1 ,delta= 1, a =0.526316 ,b = 0.5 scaler0 :1.9 , scaler1: -0.95
* iteration :5000
0 ,0 : 0.381445
1 ,0 : 0.699498
0 ,1 : 0.72889
1 ,1 : -0.151035

h11. =========== =========== ===========

* Second Iteration without initialzation of weights

h11. =========== =========== ===========

prepare to train
count=4
fr0 :0 dr0 :0t(0,0) : 0
t : 0 scaler0 :1.9 , scaler1: -0.95
fr0 :0 dr0 :1t(1,0) : 1
t : 1 scaler0 :1.9 , scaler1: -0.95
fr0 :0 dr0 :1t(2,0) : 1
t : 1 scaler0 :1.9 , scaler1: -0.95
fr0 :0 dr0 :0t(3,0) : 0
t : 0 scaler0 :1.9 , scaler1: -0.95
* iteration :5000
0 ,0 : 0.381445
1 ,0 : 0.699498

It looks like working at the first glance, but it still has a problem, which is producing exactly same result at the second part to the first part. I am not sure if the UPDATE_WEIGHT option is working.

Thank you


xor.cxx - Testing file (3.5 kB) eunyoung kim, 2010-09-11 12:11 am

ReportForIssues201009.pptx (82.6 kB) eunyoung kim, 2010-09-20 09:50 pm

ann_mlp.cpp.eunyokim (46.7 kB) eunyoung kim, 2010-09-20 09:55 pm


Associated revisions

Revision 2c03c14f
Added by Vadim Pisarevsky over 14 years ago

probably fixed the bug in ANN::calc_output_scale with update_weights=true (ticket #558)

History

Updated by eunyoung kim over 14 years ago

And here's my version of opencv
Path: .
URL: https://code.ros.org/svn/opencv/trunk/opencv
Repository Root: https://code.ros.org/svn/opencv
Repository UUID: 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08
Revision: 3603
Node Kind: directory
Schedule: normal
Last Changed Author: mdim
Last Changed Rev: 3603
Last Changed Date: 2010-09-10 10:44:46 -0500 (Fri, 10 Sep 2010)

Updated by anonymous - over 14 years ago

  • Status deleted (Open)

Updated by Anonymous over 14 years ago

Please e-mail me if I think something wrong.
I would like to make it work asap.

Best,

Updated by eunyoung kim over 14 years ago

Hello all,

Please see attachments, ReportForIssues201009.pptx and ann_mlp.cpp.eunyokim. Powerpoint file is the explanation how to fix the problem and the ann_mlp.cpp.eunyokim is just my version of ann_mlp.cpp, which is solved for reported bug.

Hope this helps for faster revision of the OpenCV code.

Best regards,

Regina

Updated by anonymous - over 14 years ago

Oh, and here is my patch.

golgi:src eunyokim$ svn diff
Index: ann_mlp.cpp ===================================================================
--- ann_mlp.cpp (revision 3647)
++ ann_mlp.cpp (working copy)
@ -593,8 +593,9 @
bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
bool no_scale = (flags & NO_OUTPUT_SCALE) != 0;
int l_count = layer_sizes->cols;
- double* scale = weights[l_count];
- double* inv_scale = weights[l_count+1];
//Changed between scale and inv_scale
+ double* inv_scale = weights[l_count];
+ double* scale = weights[l_count+1];
int count = vecs->count;

CV_FUNCNAME( "CvANN_MLP::calc_output_scale" );
@ -654,9 +655,10 @
a = 1, b = (M + m - Mj - mj)*0.5;
else
a = (M - m)/delta, b = m - mj*a;
+ //change scale <-> inv_scale
+ scale[j*2] = a; scale[j*2+1] = b;
+ a = 1./a; b = b*a;
inv_scale[j*2] = a; inv_scale[j*2+1] = b;
a = 1./a; b = b*a;
scale[j*2] = a; scale[j*2+1] = b;
}
END;

Updated by [email protected] - over 14 years ago

Any progress on this bug?

Updated by eunyoung kim over 14 years ago

I am still waiting for response.
I also submitted this to the sourceforge: https://sourceforge.net/tracker/?func=detail&atid=376677&aid=3086084&group_id=22870

Updated by Vadim Pisarevsky over 14 years ago

hello and sorry for delay. Perhaps, the bug has been fixed in r3974.
Only a single line in CvANN_MLP::calc_output_scale has been changed:

t = t*scale[j*2] + scale[2*j+1];
=>
t = t*inv_scale[j*2] + inv_scale[2*j+1];

  • Status set to Done
  • (deleted custom field) set to fixed

Also available in: Atom PDF