cd10c0d218e84d12a487e07f7080c7d857f8ed9a
[platform/upstream/opencv.git] / modules / ml / src / ann_mlp.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //
12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
13 // Third party copyrights are property of their respective owners.
14 //
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
17 //
18 //   * Redistribution's of source code must retain the above copyright notice,
19 //     this list of conditions and the following disclaimer.
20 //
21 //   * Redistribution's in binary form must reproduce the above copyright notice,
22 //     this list of conditions and the following disclaimer in the documentation
23 //     and/or other materials provided with the distribution.
24 //
25 //   * The name of Intel Corporation may not be used to endorse or promote products
26 //     derived from this software without specific prior written permission.
27 //
28 // This software is provided by the copyright holders and contributors "as is" and
29 // any express or implied warranties, including, but not limited to, the implied
30 // warranties of merchantability and fitness for a particular purpose are disclaimed.
31 // In no event shall the Intel Corporation or contributors be liable for any direct,
32 // indirect, incidental, special, exemplary, or consequential damages
33 // (including, but not limited to, procurement of substitute goods or services;
34 // loss of use, data, or profits; or business interruption) however caused
35 // and on any theory of liability, whether in contract, strict liability,
36 // or tort (including negligence or otherwise) arising in any way out of
37 // the use of this software, even if advised of the possibility of such damage.
38 //
39 //M*/
40
41 #include "precomp.hpp"
42
43 namespace cv { namespace ml {
44
45 struct SimulatedAnnealingSolver::Impl
46 {
47     int refcount;
48
49     const Ptr<SimulatedAnnealingSolverSystem> systemPtr;
50     SimulatedAnnealingSolverSystem& system;
51     RNG rEnergy;
52     double coolingRatio;
53     double initialT;
54     double finalT;
55     int iterPerStep;
56
57     Impl(const Ptr<SimulatedAnnealingSolverSystem>& s) :
58         refcount(1),
59         systemPtr(s),
60         system(*(s.get())),
61         rEnergy(12345)
62     {
63         CV_Assert(!systemPtr.empty());
64         initialT = 2;
65         finalT = 0.1;
66         coolingRatio = 0.95;
67         iterPerStep = 100;
68     }
69
70     inline double energy() { return system.energy(); }
71     inline void changeState() { system.changeState(); }
72     inline void reverseState() { system.reverseState(); }
73
74     void addref() { CV_XADD(&refcount, 1); }
75     void release() { if (CV_XADD(&refcount, -1) == 1) delete this; }
76 protected:
77     virtual ~Impl() { CV_Assert(refcount==0); }
78 };
79
80 struct AnnParams
81 {
82     AnnParams()
83     {
84         termCrit = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 1000, 0.01 );
85         trainMethod = ANN_MLP::RPROP;
86         bpDWScale = bpMomentScale = 0.1;
87         rpDW0 = 0.1; rpDWPlus = 1.2; rpDWMinus = 0.5;
88         rpDWMin = FLT_EPSILON; rpDWMax = 50.;
89         initialT=10;finalT=0.1,coolingRatio=0.95;itePerStep=10;
90         rEnergy = cv::RNG(12345);
91     }
92
93     TermCriteria termCrit;
94     int trainMethod;
95
96     double bpDWScale;
97     double bpMomentScale;
98
99     double rpDW0;
100     double rpDWPlus;
101     double rpDWMinus;
102     double rpDWMin;
103     double rpDWMax;
104
105     double initialT;
106     double finalT;
107     double coolingRatio;
108     int itePerStep;
109     RNG rEnergy;
110 };
111
112 template <typename T>
113 inline T inBounds(T val, T min_val, T max_val)
114 {
115     return std::min(std::max(val, min_val), max_val);
116 }
117
118 SimulatedAnnealingSolver::SimulatedAnnealingSolver(const Ptr<SimulatedAnnealingSolverSystem>& system)
119 {
120     impl = new Impl(system);
121 }
122
123 SimulatedAnnealingSolver::SimulatedAnnealingSolver(const SimulatedAnnealingSolver& b)
124 {
125     if (b.impl) b.impl->addref();
126     release();
127     impl = b.impl;
128 }
129
130 void SimulatedAnnealingSolver::release()
131 {
132     if (impl) { impl->release(); impl = NULL; }
133 }
134
135 void SimulatedAnnealingSolver::setIterPerStep(int ite)
136 {
137     CV_Assert(impl);
138     CV_Assert(ite>0);
139     impl->iterPerStep = ite;
140 }
141
142 int SimulatedAnnealingSolver::run()
143 {
144     CV_Assert(impl);
145     CV_Assert(impl->initialT>impl->finalT);
146     double Ti = impl->initialT;
147     double previousEnergy = impl->energy();
148     int exchange = 0;
149     while (Ti > impl->finalT)
150     {
151         for (int i = 0; i < impl->iterPerStep; i++)
152         {
153             impl->changeState();
154             double newEnergy = impl->energy();
155             if (newEnergy < previousEnergy)
156             {
157                 previousEnergy = newEnergy;
158                 exchange++;
159             }
160             else
161             {
162                 double r = impl->rEnergy.uniform(0.0, 1.0);
163                 if (r < std::exp(-(newEnergy - previousEnergy) / Ti))
164                 {
165                     previousEnergy = newEnergy;
166                     exchange++;
167                 }
168                 else
169                 {
170                     impl->reverseState();
171                 }
172             }
173
174         }
175         Ti *= impl->coolingRatio;
176     }
177     impl->finalT = Ti;
178     return exchange;
179 }
180
181 void SimulatedAnnealingSolver::setEnergyRNG(const RNG& rng)
182 {
183     CV_Assert(impl);
184     impl->rEnergy = rng;
185 }
186
187 void SimulatedAnnealingSolver::setInitialTemperature(double x)
188 {
189     CV_Assert(impl);
190     CV_Assert(x>0);
191     impl->initialT = x;
192 }
193
194 void SimulatedAnnealingSolver::setFinalTemperature(double x)
195 {
196     CV_Assert(impl);
197     CV_Assert(x>0);
198     impl->finalT = x;
199 }
200
201 double SimulatedAnnealingSolver::getFinalTemperature()
202 {
203     CV_Assert(impl);
204     return impl->finalT;
205 }
206
207 void SimulatedAnnealingSolver::setCoolingRatio(double x)
208 {
209     CV_Assert(impl);
210     CV_Assert(x>0 && x<1);
211     impl->coolingRatio = x;
212 }
213
214 class SimulatedAnnealingANN_MLP : public SimulatedAnnealingSolverSystem
215 {
216 protected:
217     ml::ANN_MLP& nn;
218     Ptr<ml::TrainData> data;
219     int nbVariables;
220     vector<double*> adrVariables;
221     RNG rVar;
222     RNG rIndex;
223     double varTmp;
224     int index;
225 public:
226     SimulatedAnnealingANN_MLP(ml::ANN_MLP& x, const Ptr<ml::TrainData>& d) : nn(x), data(d)
227     {
228         initVarMap();
229     }
230     ~SimulatedAnnealingANN_MLP() {}
231 protected:
232     void changeState()
233     {
234         index = rIndex.uniform(0, nbVariables);
235         double dv = rVar.uniform(-1.0, 1.0);
236         varTmp = *adrVariables[index];
237         *adrVariables[index] = dv;
238     }
239
240     void reverseState()
241     {
242         *adrVariables[index] = varTmp;
243     }
244
245     double energy() const { return nn.calcError(data, false, noArray()); }
246
247 protected:
248     void initVarMap()
249     {
250         Mat l = nn.getLayerSizes();
251         nbVariables = 0;
252         adrVariables.clear();
253         for (int i = 1; i < l.rows-1; i++)
254         {
255             Mat w = nn.getWeights(i);
256             for (int j = 0; j < w.rows; j++)
257             {
258                 for (int k = 0; k < w.cols; k++, nbVariables++)
259                 {
260                     if (j == w.rows - 1)
261                     {
262                         adrVariables.push_back(&w.at<double>(w.rows - 1, k));
263                     }
264                     else
265                     {
266                         adrVariables.push_back(&w.at<double>(j, k));
267                     }
268                 }
269             }
270         }
271     }
272
273 };
274
275 double ANN_MLP::getAnnealInitialT() const
276 {
277     const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
278     if (!this_)
279         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
280     return this_->getAnnealInitialT();
281 }
282
283 void ANN_MLP::setAnnealInitialT(double val)
284 {
285     ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
286     if (!this_)
287         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
288     this_->setAnnealInitialT(val);
289 }
290
291 double ANN_MLP::getAnnealFinalT() const
292 {
293     const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
294     if (!this_)
295         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
296     return this_->getAnnealFinalT();
297 }
298
299 void ANN_MLP::setAnnealFinalT(double val)
300 {
301     ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
302     if (!this_)
303         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
304     this_->setAnnealFinalT(val);
305 }
306
307 double ANN_MLP::getAnnealCoolingRatio() const
308 {
309     const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
310     if (!this_)
311         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
312     return this_->getAnnealCoolingRatio();
313 }
314
315 void ANN_MLP::setAnnealCoolingRatio(double val)
316 {
317     ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
318     if (!this_)
319         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
320     this_->setAnnealCoolingRatio(val);
321 }
322
323 int ANN_MLP::getAnnealItePerStep() const
324 {
325     const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
326     if (!this_)
327         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
328     return this_->getAnnealItePerStep();
329 }
330
331 void ANN_MLP::setAnnealItePerStep(int val)
332 {
333     ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
334     if (!this_)
335         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
336     this_->setAnnealItePerStep(val);
337 }
338
339 void ANN_MLP::setAnnealEnergyRNG(const RNG& rng)
340 {
341     ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
342     if (!this_)
343         CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
344     this_->setAnnealEnergyRNG(rng);
345 }
346
347 class ANN_MLPImpl : public ANN_MLP_ANNEAL
348 {
349 public:
350     ANN_MLPImpl()
351     {
352         clear();
353         setActivationFunction( SIGMOID_SYM, 0, 0);
354         setLayerSizes(Mat());
355         setTrainMethod(ANN_MLP::RPROP, 0.1, FLT_EPSILON);
356     }
357
358     virtual ~ANN_MLPImpl() {}
359
360     CV_IMPL_PROPERTY(TermCriteria, TermCriteria, params.termCrit)
361     CV_IMPL_PROPERTY(double, BackpropWeightScale, params.bpDWScale)
362     CV_IMPL_PROPERTY(double, BackpropMomentumScale, params.bpMomentScale)
363     CV_IMPL_PROPERTY(double, RpropDW0, params.rpDW0)
364     CV_IMPL_PROPERTY(double, RpropDWPlus, params.rpDWPlus)
365     CV_IMPL_PROPERTY(double, RpropDWMinus, params.rpDWMinus)
366     CV_IMPL_PROPERTY(double, RpropDWMin, params.rpDWMin)
367     CV_IMPL_PROPERTY(double, RpropDWMax, params.rpDWMax)
368     CV_IMPL_PROPERTY(double, AnnealInitialT, params.initialT)
369     CV_IMPL_PROPERTY(double, AnnealFinalT, params.finalT)
370     CV_IMPL_PROPERTY(double, AnnealCoolingRatio, params.coolingRatio)
371     CV_IMPL_PROPERTY(int, AnnealItePerStep, params.itePerStep)
372
373     //CV_IMPL_PROPERTY(RNG, AnnealEnergyRNG, params.rEnergy)
374     inline void setAnnealEnergyRNG(const RNG& val) { params.rEnergy = val; }
375
376     void clear()
377     {
378         min_val = max_val = min_val1 = max_val1 = 0.;
379         rng = RNG((uint64)-1);
380         weights.clear();
381         trained = false;
382         max_buf_sz = 1 << 12;
383     }
384
385     int layer_count() const { return (int)layer_sizes.size(); }
386
387     void setTrainMethod(int method, double param1, double param2)
388     {
389         if (method != ANN_MLP::RPROP && method != ANN_MLP::BACKPROP && method != ANN_MLP::ANNEAL)
390             method = ANN_MLP::RPROP;
391         params.trainMethod = method;
392         if(method == ANN_MLP::RPROP )
393         {
394             if( param1 < FLT_EPSILON )
395                 param1 = 1.;
396             params.rpDW0 = param1;
397             params.rpDWMin = std::max( param2, 0. );
398         }
399         else if (method == ANN_MLP::BACKPROP)
400         {
401             if (param1 <= 0)
402                 param1 = 0.1;
403             params.bpDWScale = inBounds<double>(param1, 1e-3, 1.);
404             if (param2 < 0)
405                 param2 = 0.1;
406             params.bpMomentScale = std::min(param2, 1.);
407         }
408     }
409
410     int getTrainMethod() const
411     {
412         return params.trainMethod;
413     }
414
415     void setActivationFunction(int _activ_func, double _f_param1, double _f_param2)
416     {
417         if( _activ_func < 0 || _activ_func > LEAKYRELU)
418             CV_Error( CV_StsOutOfRange, "Unknown activation function" );
419
420         activ_func = _activ_func;
421
422         switch( activ_func )
423         {
424         case SIGMOID_SYM:
425             max_val = 0.95; min_val = -max_val;
426             max_val1 = 0.98; min_val1 = -max_val1;
427             if( fabs(_f_param1) < FLT_EPSILON )
428                 _f_param1 = 2./3;
429             if( fabs(_f_param2) < FLT_EPSILON )
430                 _f_param2 = 1.7159;
431             break;
432         case GAUSSIAN:
433             max_val = 1.; min_val = 0.05;
434             max_val1 = 1.; min_val1 = 0.02;
435             if (fabs(_f_param1) < FLT_EPSILON)
436                 _f_param1 = 1.;
437             if (fabs(_f_param2) < FLT_EPSILON)
438                 _f_param2 = 1.;
439             break;
440         case RELU:
441             if (fabs(_f_param1) < FLT_EPSILON)
442                 _f_param1 = 1;
443             min_val = max_val = min_val1 = max_val1 = 0.;
444             _f_param2 = 0.;
445             break;
446         case LEAKYRELU:
447             if (fabs(_f_param1) < FLT_EPSILON)
448                 _f_param1 = 0.01;
449             min_val = max_val = min_val1 = max_val1 = 0.;
450             _f_param2 = 0.;
451             break;
452         default:
453             min_val = max_val = min_val1 = max_val1 = 0.;
454             _f_param1 = 1.;
455             _f_param2 = 0.;
456         }
457
458         f_param1 = _f_param1;
459         f_param2 = _f_param2;
460     }
461
462
463     void init_weights()
464     {
465         int i, j, k, l_count = layer_count();
466
467         for( i = 1; i < l_count; i++ )
468         {
469             int n1 = layer_sizes[i-1];
470             int n2 = layer_sizes[i];
471             double val = 0, G = n2 > 2 ? 0.7*pow((double)n1,1./(n2-1)) : 1.;
472             double* w = weights[i].ptr<double>();
473
474             // initialize weights using Nguyen-Widrow algorithm
475             for( j = 0; j < n2; j++ )
476             {
477                 double s = 0;
478                 for( k = 0; k <= n1; k++ )
479                 {
480                     val = rng.uniform(0., 1.)*2-1.;
481                     w[k*n2 + j] = val;
482                     s += fabs(val);
483                 }
484
485                 if( i < l_count - 1 )
486                 {
487                     s = 1./(s - fabs(val));
488                     for( k = 0; k <= n1; k++ )
489                         w[k*n2 + j] *= s;
490                     w[n1*n2 + j] *= G*(-1+j*2./n2);
491                 }
492             }
493         }
494     }
495
496     Mat getLayerSizes() const
497     {
498         return Mat_<int>(layer_sizes, true);
499     }
500
501     void setLayerSizes( InputArray _layer_sizes )
502     {
503         clear();
504
505         _layer_sizes.copyTo(layer_sizes);
506         int l_count = layer_count();
507
508         weights.resize(l_count + 2);
509         max_lsize = 0;
510
511         if( l_count > 0 )
512         {
513             for( int i = 0; i < l_count; i++ )
514             {
515                 int n = layer_sizes[i];
516                 if( n < 1 + (0 < i && i < l_count-1))
517                     CV_Error( CV_StsOutOfRange,
518                              "there should be at least one input and one output "
519                              "and every hidden layer must have more than 1 neuron" );
520                 max_lsize = std::max( max_lsize, n );
521                 if( i > 0 )
522                     weights[i].create(layer_sizes[i-1]+1, n, CV_64F);
523             }
524
525             int ninputs = layer_sizes.front();
526             int noutputs = layer_sizes.back();
527             weights[0].create(1, ninputs*2, CV_64F);
528             weights[l_count].create(1, noutputs*2, CV_64F);
529             weights[l_count+1].create(1, noutputs*2, CV_64F);
530         }
531     }
532
533     float predict( InputArray _inputs, OutputArray _outputs, int ) const
534     {
535         if( !trained )
536             CV_Error( CV_StsError, "The network has not been trained or loaded" );
537
538         Mat inputs = _inputs.getMat();
539         int type = inputs.type(), l_count = layer_count();
540         int n = inputs.rows, dn0 = n;
541
542         CV_Assert( (type == CV_32F || type == CV_64F) && inputs.cols == layer_sizes[0] );
543         int noutputs = layer_sizes[l_count-1];
544         Mat outputs;
545
546         int min_buf_sz = 2*max_lsize;
547         int buf_sz = n*min_buf_sz;
548
549         if( buf_sz > max_buf_sz )
550         {
551             dn0 = max_buf_sz/min_buf_sz;
552             dn0 = std::max( dn0, 1 );
553             buf_sz = dn0*min_buf_sz;
554         }
555
556         cv::AutoBuffer<double> _buf(buf_sz+noutputs);
557         double* buf = _buf;
558
559         if( !_outputs.needed() )
560         {
561             CV_Assert( n == 1 );
562             outputs = Mat(n, noutputs, type, buf + buf_sz);
563         }
564         else
565         {
566             _outputs.create(n, noutputs, type);
567             outputs = _outputs.getMat();
568         }
569
570         int dn = 0;
571         for( int i = 0; i < n; i += dn )
572         {
573             dn = std::min( dn0, n - i );
574
575             Mat layer_in = inputs.rowRange(i, i + dn);
576             Mat layer_out( dn, layer_in.cols, CV_64F, buf);
577
578             scale_input( layer_in, layer_out );
579             layer_in = layer_out;
580
581             for( int j = 1; j < l_count; j++ )
582             {
583                 double* data = buf + ((j&1) ? max_lsize*dn0 : 0);
584                 int cols = layer_sizes[j];
585
586                 layer_out = Mat(dn, cols, CV_64F, data);
587                 Mat w = weights[j].rowRange(0, layer_in.cols);
588                 gemm(layer_in, w, 1, noArray(), 0, layer_out);
589                 calc_activ_func( layer_out, weights[j] );
590
591                 layer_in = layer_out;
592             }
593
594             layer_out = outputs.rowRange(i, i + dn);
595             scale_output( layer_in, layer_out );
596         }
597
598         if( n == 1 )
599         {
600             int maxIdx[] = {0, 0};
601             minMaxIdx(outputs, 0, 0, 0, maxIdx);
602             return (float)(maxIdx[0] + maxIdx[1]);
603         }
604
605         return 0.f;
606     }
607
608     void scale_input( const Mat& _src, Mat& _dst ) const
609     {
610         int cols = _src.cols;
611         const double* w = weights[0].ptr<double>();
612
613         if( _src.type() == CV_32F )
614         {
615             for( int i = 0; i < _src.rows; i++ )
616             {
617                 const float* src = _src.ptr<float>(i);
618                 double* dst = _dst.ptr<double>(i);
619                 for( int j = 0; j < cols; j++ )
620                     dst[j] = src[j]*w[j*2] + w[j*2+1];
621             }
622         }
623         else
624         {
625             for( int i = 0; i < _src.rows; i++ )
626             {
627                 const double* src = _src.ptr<double>(i);
628                 double* dst = _dst.ptr<double>(i);
629                 for( int j = 0; j < cols; j++ )
630                     dst[j] = src[j]*w[j*2] + w[j*2+1];
631             }
632         }
633     }
634
635     void scale_output( const Mat& _src, Mat& _dst ) const
636     {
637         int cols = _src.cols;
638         const double* w = weights[layer_count()].ptr<double>();
639
640         if( _dst.type() == CV_32F )
641         {
642             for( int i = 0; i < _src.rows; i++ )
643             {
644                 const double* src = _src.ptr<double>(i);
645                 float* dst = _dst.ptr<float>(i);
646                 for( int j = 0; j < cols; j++ )
647                     dst[j] = (float)(src[j]*w[j*2] + w[j*2+1]);
648             }
649         }
650         else
651         {
652             for( int i = 0; i < _src.rows; i++ )
653             {
654                 const double* src = _src.ptr<double>(i);
655                 double* dst = _dst.ptr<double>(i);
656                 for( int j = 0; j < cols; j++ )
657                     dst[j] = src[j]*w[j*2] + w[j*2+1];
658             }
659         }
660     }
661
662     void calc_activ_func(Mat& sums, const Mat& w) const
663     {
664         const double* bias = w.ptr<double>(w.rows - 1);
665         int i, j, n = sums.rows, cols = sums.cols;
666         double scale = 0, scale2 = f_param2;
667
668         switch (activ_func)
669         {
670         case IDENTITY:
671             scale = 1.;
672             break;
673         case SIGMOID_SYM:
674             scale = -f_param1;
675             break;
676         case GAUSSIAN:
677             scale = -f_param1*f_param1;
678             break;
679         case RELU:
680             scale = 1;
681             break;
682         case LEAKYRELU:
683             scale = 1;
684             break;
685         default:
686             ;
687         }
688
689         CV_Assert(sums.isContinuous());
690
691         if (activ_func != GAUSSIAN)
692         {
693             for (i = 0; i < n; i++)
694             {
695                 double* data = sums.ptr<double>(i);
696                 for (j = 0; j < cols; j++)
697                 {
698                     data[j] = (data[j] + bias[j])*scale;
699                     if (activ_func == RELU)
700                         if (data[j] < 0)
701                             data[j] = 0;
702                     if (activ_func == LEAKYRELU)
703                         if (data[j] < 0)
704                             data[j] *= f_param1;
705                 }
706             }
707
708             if (activ_func == IDENTITY || activ_func == RELU || activ_func == LEAKYRELU)
709                 return;
710         }
711         else
712         {
713             for (i = 0; i < n; i++)
714             {
715                 double* data = sums.ptr<double>(i);
716                 for (j = 0; j < cols; j++)
717                 {
718                     double t = data[j] + bias[j];
719                     data[j] = t*t*scale;
720                 }
721             }
722         }
723
724         exp(sums, sums);
725
726         if (sums.isContinuous())
727         {
728             cols *= n;
729             n = 1;
730         }
731
732         switch (activ_func)
733         {
734         case SIGMOID_SYM:
735             for (i = 0; i < n; i++)
736             {
737                 double* data = sums.ptr<double>(i);
738                 for (j = 0; j < cols; j++)
739                 {
740                     if (!cvIsInf(data[j]))
741                     {
742                         double t = scale2*(1. - data[j]) / (1. + data[j]);
743                         data[j] = t;
744                     }
745                     else
746                     {
747                         data[j] = -scale2;
748                     }
749                 }
750             }
751             break;
752
753         case GAUSSIAN:
754             for (i = 0; i < n; i++)
755             {
756                 double* data = sums.ptr<double>(i);
757                 for (j = 0; j < cols; j++)
758                     data[j] = scale2*data[j];
759             }
760             break;
761
762         default:
763             ;
764         }
765     }
766
767     void calc_activ_func_deriv(Mat& _xf, Mat& _df, const Mat& w) const
768     {
769         const double* bias = w.ptr<double>(w.rows - 1);
770         int i, j, n = _xf.rows, cols = _xf.cols;
771
772         if (activ_func == IDENTITY)
773         {
774             for (i = 0; i < n; i++)
775             {
776                 double* xf = _xf.ptr<double>(i);
777                 double* df = _df.ptr<double>(i);
778
779                 for (j = 0; j < cols; j++)
780                 {
781                     xf[j] += bias[j];
782                     df[j] = 1;
783                 }
784             }
785         }
786         else if (activ_func == RELU)
787         {
788             for (i = 0; i < n; i++)
789             {
790                 double* xf = _xf.ptr<double>(i);
791                 double* df = _df.ptr<double>(i);
792
793                 for (j = 0; j < cols; j++)
794                 {
795                     xf[j] += bias[j];
796                     if (xf[j] < 0)
797                     {
798                         xf[j] = 0;
799                         df[j] = 0;
800                     }
801                     else
802                         df[j] = 1;
803                 }
804             }
805         }
806         else if (activ_func == LEAKYRELU)
807         {
808             for (i = 0; i < n; i++)
809             {
810                 double* xf = _xf.ptr<double>(i);
811                 double* df = _df.ptr<double>(i);
812
813                 for (j = 0; j < cols; j++)
814                 {
815                     xf[j] += bias[j];
816                     if (xf[j] < 0)
817                     {
818                         xf[j] = f_param1*xf[j];
819                         df[j] = f_param1;
820                     }
821                     else
822                         df[j] = 1;
823                 }
824             }
825         }
826         else if (activ_func == GAUSSIAN)
827         {
828             double scale = -f_param1*f_param1;
829             double scale2 = scale*f_param2;
830             for (i = 0; i < n; i++)
831             {
832                 double* xf = _xf.ptr<double>(i);
833                 double* df = _df.ptr<double>(i);
834
835                 for (j = 0; j < cols; j++)
836                 {
837                     double t = xf[j] + bias[j];
838                     df[j] = t * 2 * scale2;
839                     xf[j] = t*t*scale;
840                 }
841             }
842             exp(_xf, _xf);
843
844             for (i = 0; i < n; i++)
845             {
846                 double* xf = _xf.ptr<double>(i);
847                 double* df = _df.ptr<double>(i);
848
849                 for (j = 0; j < cols; j++)
850                     df[j] *= xf[j];
851             }
852         }
853         else
854         {
855             double scale = f_param1;
856             double scale2 = f_param2;
857
858             for (i = 0; i < n; i++)
859             {
860                 double* xf = _xf.ptr<double>(i);
861                 double* df = _df.ptr<double>(i);
862
863                 for (j = 0; j < cols; j++)
864                 {
865                     xf[j] = (xf[j] + bias[j])*scale;
866                     df[j] = -fabs(xf[j]);
867                 }
868             }
869
870             exp(_df, _df);
871
872             // ((1+exp(-ax))^-1)'=a*((1+exp(-ax))^-2)*exp(-ax);
873             // ((1-exp(-ax))/(1+exp(-ax)))'=(a*exp(-ax)*(1+exp(-ax)) + a*exp(-ax)*(1-exp(-ax)))/(1+exp(-ax))^2=
874             // 2*a*exp(-ax)/(1+exp(-ax))^2
875             scale *= 2 * f_param2;
876             for (i = 0; i < n; i++)
877             {
878                 double* xf = _xf.ptr<double>(i);
879                 double* df = _df.ptr<double>(i);
880
881                 for (j = 0; j < cols; j++)
882                 {
883                     int s0 = xf[j] > 0 ? 1 : -1;
884                     double t0 = 1. / (1. + df[j]);
885                     double t1 = scale*df[j] * t0*t0;
886                     t0 *= scale2*(1. - df[j])*s0;
887                     df[j] = t1;
888                     xf[j] = t0;
889                 }
890             }
891         }
892     }
893
894     void calc_input_scale( const Mat& inputs, int flags )
895     {
896         bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
897         bool no_scale = (flags & NO_INPUT_SCALE) != 0;
898         double* scale = weights[0].ptr<double>();
899         int count = inputs.rows;
900
901         if( reset_weights )
902         {
903             int i, j, vcount = layer_sizes[0];
904             int type = inputs.type();
905             double a = no_scale ? 1. : 0.;
906
907             for( j = 0; j < vcount; j++ )
908                 scale[2*j] = a, scale[j*2+1] = 0.;
909
910             if( no_scale )
911                 return;
912
913             for( i = 0; i < count; i++ )
914             {
915                 const uchar* p = inputs.ptr(i);
916                 const float* f = (const float*)p;
917                 const double* d = (const double*)p;
918                 for( j = 0; j < vcount; j++ )
919                 {
920                     double t = type == CV_32F ? (double)f[j] : d[j];
921                     scale[j*2] += t;
922                     scale[j*2+1] += t*t;
923                 }
924             }
925
926             for( j = 0; j < vcount; j++ )
927             {
928                 double s = scale[j*2], s2 = scale[j*2+1];
929                 double m = s/count, sigma2 = s2/count - m*m;
930                 scale[j*2] = sigma2 < DBL_EPSILON ? 1 : 1./sqrt(sigma2);
931                 scale[j*2+1] = -m*scale[j*2];
932             }
933         }
934     }
935
936     void calc_output_scale( const Mat& outputs, int flags )
937     {
938         int i, j, vcount = layer_sizes.back();
939         int type = outputs.type();
940         double m = min_val, M = max_val, m1 = min_val1, M1 = max_val1;
941         bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
942         bool no_scale = (flags & NO_OUTPUT_SCALE) != 0;
943         int l_count = layer_count();
944         double* scale = weights[l_count].ptr<double>();
945         double* inv_scale = weights[l_count+1].ptr<double>();
946         int count = outputs.rows;
947
948         if( reset_weights )
949         {
950             double a0 = no_scale ? 1 : DBL_MAX, b0 = no_scale ? 0 : -DBL_MAX;
951
952             for( j = 0; j < vcount; j++ )
953             {
954                 scale[2*j] = inv_scale[2*j] = a0;
955                 scale[j*2+1] = inv_scale[2*j+1] = b0;
956             }
957
958             if( no_scale )
959                 return;
960         }
961
962         for( i = 0; i < count; i++ )
963         {
964             const uchar* p = outputs.ptr(i);
965             const float* f = (const float*)p;
966             const double* d = (const double*)p;
967
968             for( j = 0; j < vcount; j++ )
969             {
970                 double t = type == CV_32F ? (double)f[j] : d[j];
971
972                 if( reset_weights )
973                 {
974                     double mj = scale[j*2], Mj = scale[j*2+1];
975                     if( mj > t ) mj = t;
976                     if( Mj < t ) Mj = t;
977
978                     scale[j*2] = mj;
979                     scale[j*2+1] = Mj;
980                 }
981                 else if( !no_scale )
982                 {
983                     t = t*inv_scale[j*2] + inv_scale[2*j+1];
984                     if( t < m1 || t > M1 )
985                         CV_Error( CV_StsOutOfRange,
986                                  "Some of new output training vector components run exceed the original range too much" );
987                 }
988             }
989         }
990
991         if( reset_weights )
992             for( j = 0; j < vcount; j++ )
993             {
994                 // map mj..Mj to m..M
995                 double mj = scale[j*2], Mj = scale[j*2+1];
996                 double a, b;
997                 double delta = Mj - mj;
998                 if( delta < DBL_EPSILON )
999                     a = 1, b = (M + m - Mj - mj)*0.5;
1000                 else
1001                     a = (M - m)/delta, b = m - mj*a;
1002                 inv_scale[j*2] = a; inv_scale[j*2+1] = b;
1003                 a = 1./a; b = -b*a;
1004                 scale[j*2] = a; scale[j*2+1] = b;
1005             }
1006     }
1007
1008     void prepare_to_train( const Mat& inputs, const Mat& outputs,
1009                            Mat& sample_weights, int flags )
1010     {
1011         if( layer_sizes.empty() )
1012             CV_Error( CV_StsError,
1013                      "The network has not been created. Use method create or the appropriate constructor" );
1014
1015         if( (inputs.type() != CV_32F && inputs.type() != CV_64F) ||
1016             inputs.cols != layer_sizes[0] )
1017             CV_Error( CV_StsBadArg,
1018                      "input training data should be a floating-point matrix with "
1019                      "the number of rows equal to the number of training samples and "
1020                      "the number of columns equal to the size of 0-th (input) layer" );
1021
1022         if( (outputs.type() != CV_32F && outputs.type() != CV_64F) ||
1023             outputs.cols != layer_sizes.back() )
1024             CV_Error( CV_StsBadArg,
1025                      "output training data should be a floating-point matrix with "
1026                      "the number of rows equal to the number of training samples and "
1027                      "the number of columns equal to the size of last (output) layer" );
1028
1029         if( inputs.rows != outputs.rows )
1030             CV_Error( CV_StsUnmatchedSizes, "The numbers of input and output samples do not match" );
1031
1032         Mat temp;
1033         double s = sum(sample_weights)[0];
1034         sample_weights.convertTo(temp, CV_64F, 1./s);
1035         sample_weights = temp;
1036
1037         calc_input_scale( inputs, flags );
1038         calc_output_scale( outputs, flags );
1039     }
1040
1041     bool train( const Ptr<TrainData>& trainData, int flags )
1042     {
1043         const int MAX_ITER = 1000;
1044         const double DEFAULT_EPSILON = FLT_EPSILON;
1045
1046         // initialize training data
1047         Mat inputs = trainData->getTrainSamples();
1048         Mat outputs = trainData->getTrainResponses();
1049         Mat sw = trainData->getTrainSampleWeights();
1050         prepare_to_train( inputs, outputs, sw, flags );
1051
1052         // ... and link weights
1053         if( !(flags & UPDATE_WEIGHTS) )
1054             init_weights();
1055
1056         TermCriteria termcrit;
1057         termcrit.type = TermCriteria::COUNT + TermCriteria::EPS;
1058         termcrit.maxCount = std::max((params.termCrit.type & CV_TERMCRIT_ITER ? params.termCrit.maxCount : MAX_ITER), 1);
1059         termcrit.epsilon = std::max((params.termCrit.type & CV_TERMCRIT_EPS ? params.termCrit.epsilon : DEFAULT_EPSILON), DBL_EPSILON);
1060
1061         int iter = 0;
1062         switch(params.trainMethod){
1063         case ANN_MLP::BACKPROP:
1064             iter = train_backprop(inputs, outputs, sw, termcrit);
1065             break;
1066         case ANN_MLP::RPROP:
1067             iter = train_rprop(inputs, outputs, sw, termcrit);
1068             break;
1069         case ANN_MLP::ANNEAL:
1070             iter = train_anneal(trainData);
1071             break;
1072         }
1073         trained = iter > 0;
1074         return trained;
1075     }
1076     int train_anneal(const Ptr<TrainData>& trainData)
1077     {
1078         SimulatedAnnealingSolver t(Ptr<SimulatedAnnealingANN_MLP>(new SimulatedAnnealingANN_MLP(*this, trainData)));
1079         t.setEnergyRNG(params.rEnergy);
1080         t.setFinalTemperature(params.finalT);
1081         t.setInitialTemperature(params.initialT);
1082         t.setCoolingRatio(params.coolingRatio);
1083         t.setIterPerStep(params.itePerStep);
1084         trained = true; // Enable call to CalcError
1085         int iter =  t.run();
1086         trained =false;
1087         return iter;
1088     }
1089
1090     int train_backprop( const Mat& inputs, const Mat& outputs, const Mat& _sw, TermCriteria termCrit )
1091     {
1092         int i, j, k;
1093         double prev_E = DBL_MAX*0.5, E = 0;
1094         int itype = inputs.type(), otype = outputs.type();
1095
1096         int count = inputs.rows;
1097
1098         int iter = -1, max_iter = termCrit.maxCount*count;
1099         double epsilon = termCrit.epsilon*count;
1100
1101         int l_count = layer_count();
1102         int ivcount = layer_sizes[0];
1103         int ovcount = layer_sizes.back();
1104
1105         // allocate buffers
1106         vector<vector<double> > x(l_count);
1107         vector<vector<double> > df(l_count);
1108         vector<Mat> dw(l_count);
1109
1110         for( i = 0; i < l_count; i++ )
1111         {
1112             int n = layer_sizes[i];
1113             x[i].resize(n+1);
1114             df[i].resize(n);
1115             dw[i] = Mat::zeros(weights[i].size(), CV_64F);
1116         }
1117
1118         Mat _idx_m(1, count, CV_32S);
1119         int* _idx = _idx_m.ptr<int>();
1120         for( i = 0; i < count; i++ )
1121             _idx[i] = i;
1122
1123         AutoBuffer<double> _buf(max_lsize*2);
1124         double* buf[] = { _buf, (double*)_buf + max_lsize };
1125
1126         const double* sw = _sw.empty() ? 0 : _sw.ptr<double>();
1127
1128         // run back-propagation loop
1129         /*
1130          y_i = w_i*x_{i-1}
1131          x_i = f(y_i)
1132          E = 1/2*||u - x_N||^2
1133          grad_N = (x_N - u)*f'(y_i)
1134          dw_i(t) = momentum*dw_i(t-1) + dw_scale*x_{i-1}*grad_i
1135          w_i(t+1) = w_i(t) + dw_i(t)
1136          grad_{i-1} = w_i^t*grad_i
1137         */
1138         for( iter = 0; iter < max_iter; iter++ )
1139         {
1140             int idx = iter % count;
1141             double sweight = sw ? count*sw[idx] : 1.;
1142
1143             if( idx == 0 )
1144             {
1145                 //printf("%d. E = %g\n", iter/count, E);
1146                 if( fabs(prev_E - E) < epsilon )
1147                     break;
1148                 prev_E = E;
1149                 E = 0;
1150
1151                 // shuffle indices
1152                 for( i = 0; i <count; i++ )
1153                 {
1154                     j = rng.uniform(0, count);
1155                     k = rng.uniform(0, count);
1156                     std::swap(_idx[j], _idx[k]);
1157                 }
1158             }
1159
1160             idx = _idx[idx];
1161
1162             const uchar* x0data_p = inputs.ptr(idx);
1163             const float* x0data_f = (const float*)x0data_p;
1164             const double* x0data_d = (const double*)x0data_p;
1165
1166             double* w = weights[0].ptr<double>();
1167             for( j = 0; j < ivcount; j++ )
1168                 x[0][j] = (itype == CV_32F ? (double)x0data_f[j] : x0data_d[j])*w[j*2] + w[j*2 + 1];
1169
1170             Mat x1( 1, ivcount, CV_64F, &x[0][0] );
1171
1172             // forward pass, compute y[i]=w*x[i-1], x[i]=f(y[i]), df[i]=f'(y[i])
1173             for( i = 1; i < l_count; i++ )
1174             {
1175                 int n = layer_sizes[i];
1176                 Mat x2(1, n, CV_64F, &x[i][0] );
1177                 Mat _w = weights[i].rowRange(0, x1.cols);
1178                 gemm(x1, _w, 1, noArray(), 0, x2);
1179                 Mat _df(1, n, CV_64F, &df[i][0] );
1180                 calc_activ_func_deriv( x2, _df, weights[i] );
1181                 x1 = x2;
1182             }
1183
1184             Mat grad1( 1, ovcount, CV_64F, buf[l_count&1] );
1185             w = weights[l_count+1].ptr<double>();
1186
1187             // calculate error
1188             const uchar* udata_p = outputs.ptr(idx);
1189             const float* udata_f = (const float*)udata_p;
1190             const double* udata_d = (const double*)udata_p;
1191
1192             double* gdata = grad1.ptr<double>();
1193             for( k = 0; k < ovcount; k++ )
1194             {
1195                 double t = (otype == CV_32F ? (double)udata_f[k] : udata_d[k])*w[k*2] + w[k*2+1] - x[l_count-1][k];
1196                 gdata[k] = t*sweight;
1197                 E += t*t;
1198             }
1199             E *= sweight;
1200
1201             // backward pass, update weights
1202             for( i = l_count-1; i > 0; i-- )
1203             {
1204                 int n1 = layer_sizes[i-1], n2 = layer_sizes[i];
1205                 Mat _df(1, n2, CV_64F, &df[i][0]);
1206                 multiply( grad1, _df, grad1 );
1207                 Mat _x(n1+1, 1, CV_64F, &x[i-1][0]);
1208                 x[i-1][n1] = 1.;
1209                 gemm( _x, grad1, params.bpDWScale, dw[i], params.bpMomentScale, dw[i] );
1210                 add( weights[i], dw[i], weights[i] );
1211                 if( i > 1 )
1212                 {
1213                     Mat grad2(1, n1, CV_64F, buf[i&1]);
1214                     Mat _w = weights[i].rowRange(0, n1);
1215                     gemm( grad1, _w, 1, noArray(), 0, grad2, GEMM_2_T );
1216                     grad1 = grad2;
1217                 }
1218             }
1219         }
1220
1221         iter /= count;
1222         return iter;
1223     }
1224
1225     struct RPropLoop : public ParallelLoopBody
1226     {
1227         RPropLoop(ANN_MLPImpl* _ann,
1228                   const Mat& _inputs, const Mat& _outputs, const Mat& _sw,
1229                   int _dcount0, vector<Mat>& _dEdw, double* _E)
1230         {
1231             ann = _ann;
1232             inputs = _inputs;
1233             outputs = _outputs;
1234             sw = _sw.ptr<double>();
1235             dcount0 = _dcount0;
1236             dEdw = &_dEdw;
1237             pE = _E;
1238         }
1239
1240         ANN_MLPImpl* ann;
1241         vector<Mat>* dEdw;
1242         Mat inputs, outputs;
1243         const double* sw;
1244         int dcount0;
1245         double* pE;
1246
1247         void operator()( const Range& range ) const
1248         {
1249             double inv_count = 1./inputs.rows;
1250             int ivcount = ann->layer_sizes.front();
1251             int ovcount = ann->layer_sizes.back();
1252             int itype = inputs.type(), otype = outputs.type();
1253             int count = inputs.rows;
1254             int i, j, k, l_count = ann->layer_count();
1255             vector<vector<double> > x(l_count);
1256             vector<vector<double> > df(l_count);
1257             vector<double> _buf(ann->max_lsize*dcount0*2);
1258             double* buf[] = { &_buf[0], &_buf[ann->max_lsize*dcount0] };
1259             double E = 0;
1260
1261             for( i = 0; i < l_count; i++ )
1262             {
1263                 x[i].resize(ann->layer_sizes[i]*dcount0);
1264                 df[i].resize(ann->layer_sizes[i]*dcount0);
1265             }
1266
1267             for( int si = range.start; si < range.end; si++ )
1268             {
1269                 int i0 = si*dcount0, i1 = std::min((si + 1)*dcount0, count);
1270                 int dcount = i1 - i0;
1271                 const double* w = ann->weights[0].ptr<double>();
1272
1273                 // grab and preprocess input data
1274                 for( i = 0; i < dcount; i++ )
1275                 {
1276                     const uchar* x0data_p = inputs.ptr(i0 + i);
1277                     const float* x0data_f = (const float*)x0data_p;
1278                     const double* x0data_d = (const double*)x0data_p;
1279
1280                     double* xdata = &x[0][i*ivcount];
1281                     for( j = 0; j < ivcount; j++ )
1282                         xdata[j] = (itype == CV_32F ? (double)x0data_f[j] : x0data_d[j])*w[j*2] + w[j*2+1];
1283                 }
1284                 Mat x1(dcount, ivcount, CV_64F, &x[0][0]);
1285
1286                 // forward pass, compute y[i]=w*x[i-1], x[i]=f(y[i]), df[i]=f'(y[i])
1287                 for( i = 1; i < l_count; i++ )
1288                 {
1289                     Mat x2( dcount, ann->layer_sizes[i], CV_64F, &x[i][0] );
1290                     Mat _w = ann->weights[i].rowRange(0, x1.cols);
1291                     gemm( x1, _w, 1, noArray(), 0, x2 );
1292                     Mat _df( x2.size(), CV_64F, &df[i][0] );
1293                     ann->calc_activ_func_deriv( x2, _df, ann->weights[i] );
1294                     x1 = x2;
1295                 }
1296
1297                 Mat grad1(dcount, ovcount, CV_64F, buf[l_count & 1]);
1298
1299                 w = ann->weights[l_count+1].ptr<double>();
1300
1301                 // calculate error
1302                 for( i = 0; i < dcount; i++ )
1303                 {
1304                     const uchar* udata_p = outputs.ptr(i0+i);
1305                     const float* udata_f = (const float*)udata_p;
1306                     const double* udata_d = (const double*)udata_p;
1307
1308                     const double* xdata = &x[l_count-1][i*ovcount];
1309                     double* gdata = grad1.ptr<double>(i);
1310                     double sweight = sw ? sw[si+i] : inv_count, E1 = 0;
1311
1312                     for( j = 0; j < ovcount; j++ )
1313                     {
1314                         double t = (otype == CV_32F ? (double)udata_f[j] : udata_d[j])*w[j*2] + w[j*2+1] - xdata[j];
1315                         gdata[j] = t*sweight;
1316                         E1 += t*t;
1317                     }
1318                     E += sweight*E1;
1319                 }
1320
1321                 for( i = l_count-1; i > 0; i-- )
1322                 {
1323                     int n1 = ann->layer_sizes[i-1], n2 = ann->layer_sizes[i];
1324                     Mat _df(dcount, n2, CV_64F, &df[i][0]);
1325                     multiply(grad1, _df, grad1);
1326
1327                     {
1328                         AutoLock lock(ann->mtx);
1329                         Mat _dEdw = dEdw->at(i).rowRange(0, n1);
1330                         x1 = Mat(dcount, n1, CV_64F, &x[i-1][0]);
1331                         gemm(x1, grad1, 1, _dEdw, 1, _dEdw, GEMM_1_T);
1332
1333                         // update bias part of dEdw
1334                         double* dst = dEdw->at(i).ptr<double>(n1);
1335                         for( k = 0; k < dcount; k++ )
1336                         {
1337                             const double* src = grad1.ptr<double>(k);
1338                             for( j = 0; j < n2; j++ )
1339                                 dst[j] += src[j];
1340                         }
1341                     }
1342
1343                     Mat grad2( dcount, n1, CV_64F, buf[i&1] );
1344                     if( i > 1 )
1345                     {
1346                         Mat _w = ann->weights[i].rowRange(0, n1);
1347                         gemm(grad1, _w, 1, noArray(), 0, grad2, GEMM_2_T);
1348                     }
1349                     grad1 = grad2;
1350                 }
1351             }
1352             {
1353                 AutoLock lock(ann->mtx);
1354                 *pE += E;
1355             }
1356         }
1357     };
1358
1359     int train_rprop( const Mat& inputs, const Mat& outputs, const Mat& _sw, TermCriteria termCrit )
1360     {
1361         const int max_buf_size = 1 << 16;
1362         int i, iter = -1, count = inputs.rows;
1363
1364         double prev_E = DBL_MAX*0.5;
1365
1366         int max_iter = termCrit.maxCount;
1367         double epsilon = termCrit.epsilon;
1368         double dw_plus = params.rpDWPlus;
1369         double dw_minus = params.rpDWMinus;
1370         double dw_min = params.rpDWMin;
1371         double dw_max = params.rpDWMax;
1372
1373         int l_count = layer_count();
1374
1375         // allocate buffers
1376         vector<Mat> dw(l_count), dEdw(l_count), prev_dEdw_sign(l_count);
1377
1378         int total = 0;
1379         for( i = 0; i < l_count; i++ )
1380         {
1381             total += layer_sizes[i];
1382             dw[i].create(weights[i].size(), CV_64F);
1383             dw[i].setTo(Scalar::all(params.rpDW0));
1384             prev_dEdw_sign[i] = Mat::zeros(weights[i].size(), CV_8S);
1385             dEdw[i] = Mat::zeros(weights[i].size(), CV_64F);
1386         }
1387
1388         int dcount0 = max_buf_size/(2*total);
1389         dcount0 = std::max( dcount0, 1 );
1390         dcount0 = std::min( dcount0, count );
1391         int chunk_count = (count + dcount0 - 1)/dcount0;
1392
1393         // run rprop loop
1394         /*
1395          y_i(t) = w_i(t)*x_{i-1}(t)
1396          x_i(t) = f(y_i(t))
1397          E = sum_over_all_samples(1/2*||u - x_N||^2)
1398          grad_N = (x_N - u)*f'(y_i)
1399
1400          std::min(dw_i{jk}(t)*dw_plus, dw_max), if dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) > 0
1401          dw_i{jk}(t) = std::max(dw_i{jk}(t)*dw_minus, dw_min), if dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) < 0
1402          dw_i{jk}(t-1) else
1403
1404          if (dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) < 0)
1405          dE/dw_i{jk}(t)<-0
1406          else
1407          w_i{jk}(t+1) = w_i{jk}(t) + dw_i{jk}(t)
1408          grad_{i-1}(t) = w_i^t(t)*grad_i(t)
1409          */
1410         for( iter = 0; iter < max_iter; iter++ )
1411         {
1412             double E = 0;
1413
1414             for( i = 0; i < l_count; i++ )
1415                 dEdw[i].setTo(Scalar::all(0));
1416
1417             // first, iterate through all the samples and compute dEdw
1418             RPropLoop invoker(this, inputs, outputs, _sw, dcount0, dEdw, &E);
1419             parallel_for_(Range(0, chunk_count), invoker);
1420             //invoker(Range(0, chunk_count));
1421
1422             // now update weights
1423             for( i = 1; i < l_count; i++ )
1424             {
1425                 int n1 = layer_sizes[i-1], n2 = layer_sizes[i];
1426                 for( int k = 0; k <= n1; k++ )
1427                 {
1428                     CV_Assert(weights[i].size() == Size(n2, n1+1));
1429                     double* wk = weights[i].ptr<double>(k);
1430                     double* dwk = dw[i].ptr<double>(k);
1431                     double* dEdwk = dEdw[i].ptr<double>(k);
1432                     schar* prevEk = prev_dEdw_sign[i].ptr<schar>(k);
1433
1434                     for( int j = 0; j < n2; j++ )
1435                     {
1436                         double Eval = dEdwk[j];
1437                         double dval = dwk[j];
1438                         double wval = wk[j];
1439                         int s = CV_SIGN(Eval);
1440                         int ss = prevEk[j]*s;
1441                         if( ss > 0 )
1442                         {
1443                             dval *= dw_plus;
1444                             dval = std::min( dval, dw_max );
1445                             dwk[j] = dval;
1446                             wk[j] = wval + dval*s;
1447                         }
1448                         else if( ss < 0 )
1449                         {
1450                             dval *= dw_minus;
1451                             dval = std::max( dval, dw_min );
1452                             prevEk[j] = 0;
1453                             dwk[j] = dval;
1454                             wk[j] = wval + dval*s;
1455                         }
1456                         else
1457                         {
1458                             prevEk[j] = (schar)s;
1459                             wk[j] = wval + dval*s;
1460                         }
1461                         dEdwk[j] = 0.;
1462                     }
1463                 }
1464             }
1465
1466             //printf("%d. E = %g\n", iter, E);
1467             if( fabs(prev_E - E) < epsilon )
1468                 break;
1469             prev_E = E;
1470         }
1471
1472         return iter;
1473     }
1474
1475     void write_params( FileStorage& fs ) const
1476     {
1477         const char* activ_func_name = activ_func == IDENTITY ? "IDENTITY" :
1478                                       activ_func == SIGMOID_SYM ? "SIGMOID_SYM" :
1479                                       activ_func == GAUSSIAN ? "GAUSSIAN" :
1480                                       activ_func == RELU ? "RELU" :
1481                                       activ_func == LEAKYRELU ? "LEAKYRELU" : 0;
1482
1483         if( activ_func_name )
1484             fs << "activation_function" << activ_func_name;
1485         else
1486             fs << "activation_function_id" << activ_func;
1487
1488         if( activ_func != IDENTITY )
1489         {
1490             fs << "f_param1" << f_param1;
1491             fs << "f_param2" << f_param2;
1492         }
1493
1494         fs << "min_val" << min_val << "max_val" << max_val << "min_val1" << min_val1 << "max_val1" << max_val1;
1495
1496         fs << "training_params" << "{";
1497         if( params.trainMethod == ANN_MLP::BACKPROP )
1498         {
1499             fs << "train_method" << "BACKPROP";
1500             fs << "dw_scale" << params.bpDWScale;
1501             fs << "moment_scale" << params.bpMomentScale;
1502         }
1503         else if (params.trainMethod == ANN_MLP::RPROP)
1504         {
1505             fs << "train_method" << "RPROP";
1506             fs << "dw0" << params.rpDW0;
1507             fs << "dw_plus" << params.rpDWPlus;
1508             fs << "dw_minus" << params.rpDWMinus;
1509             fs << "dw_min" << params.rpDWMin;
1510             fs << "dw_max" << params.rpDWMax;
1511         }
1512         else if (params.trainMethod == ANN_MLP::ANNEAL)
1513         {
1514             fs << "train_method" << "ANNEAL";
1515             fs << "initialT" << params.initialT;
1516             fs << "finalT" << params.finalT;
1517             fs << "coolingRatio" << params.coolingRatio;
1518             fs << "itePerStep" << params.itePerStep;
1519         }
1520         else
1521             CV_Error(CV_StsError, "Unknown training method");
1522
1523         fs << "term_criteria" << "{";
1524         if( params.termCrit.type & TermCriteria::EPS )
1525             fs << "epsilon" << params.termCrit.epsilon;
1526         if( params.termCrit.type & TermCriteria::COUNT )
1527             fs << "iterations" << params.termCrit.maxCount;
1528         fs << "}" << "}";
1529     }
1530
1531     void write( FileStorage& fs ) const
1532     {
1533         if( layer_sizes.empty() )
1534             return;
1535         int i, l_count = layer_count();
1536
1537         writeFormat(fs);
1538         fs << "layer_sizes" << layer_sizes;
1539
1540         write_params( fs );
1541
1542         size_t esz = weights[0].elemSize();
1543
1544         fs << "input_scale" << "[";
1545         fs.writeRaw("d", weights[0].ptr(), weights[0].total()*esz);
1546
1547         fs << "]" << "output_scale" << "[";
1548         fs.writeRaw("d", weights[l_count].ptr(), weights[l_count].total()*esz);
1549
1550         fs << "]" << "inv_output_scale" << "[";
1551         fs.writeRaw("d", weights[l_count+1].ptr(), weights[l_count+1].total()*esz);
1552
1553         fs << "]" << "weights" << "[";
1554         for( i = 1; i < l_count; i++ )
1555         {
1556             fs << "[";
1557             fs.writeRaw("d", weights[i].ptr(), weights[i].total()*esz);
1558             fs << "]";
1559         }
1560         fs << "]";
1561     }
1562
1563     void read_params( const FileNode& fn )
1564     {
1565         String activ_func_name = (String)fn["activation_function"];
1566         if( !activ_func_name.empty() )
1567         {
1568             activ_func = activ_func_name == "SIGMOID_SYM" ? SIGMOID_SYM :
1569                          activ_func_name == "IDENTITY" ? IDENTITY :
1570                          activ_func_name == "RELU" ? RELU :
1571                          activ_func_name == "LEAKYRELU" ? LEAKYRELU :
1572                          activ_func_name == "GAUSSIAN" ? GAUSSIAN : -1;
1573             CV_Assert( activ_func >= 0 );
1574         }
1575         else
1576             activ_func = (int)fn["activation_function_id"];
1577
1578         f_param1 = (double)fn["f_param1"];
1579         f_param2 = (double)fn["f_param2"];
1580
1581         setActivationFunction( activ_func, f_param1, f_param2);
1582
1583         min_val = (double)fn["min_val"];
1584         max_val = (double)fn["max_val"];
1585         min_val1 = (double)fn["min_val1"];
1586         max_val1 = (double)fn["max_val1"];
1587
1588         FileNode tpn = fn["training_params"];
1589         params = AnnParams();
1590
1591         if( !tpn.empty() )
1592         {
1593             String tmethod_name = (String)tpn["train_method"];
1594
1595             if( tmethod_name == "BACKPROP" )
1596             {
1597                 params.trainMethod = ANN_MLP::BACKPROP;
1598                 params.bpDWScale = (double)tpn["dw_scale"];
1599                 params.bpMomentScale = (double)tpn["moment_scale"];
1600             }
1601             else if (tmethod_name == "RPROP")
1602             {
1603                 params.trainMethod = ANN_MLP::RPROP;
1604                 params.rpDW0 = (double)tpn["dw0"];
1605                 params.rpDWPlus = (double)tpn["dw_plus"];
1606                 params.rpDWMinus = (double)tpn["dw_minus"];
1607                 params.rpDWMin = (double)tpn["dw_min"];
1608                 params.rpDWMax = (double)tpn["dw_max"];
1609             }
1610             else if (tmethod_name == "ANNEAL")
1611             {
1612                 params.trainMethod = ANN_MLP::ANNEAL;
1613                 params.initialT = (double)tpn["initialT"];
1614                 params.finalT = (double)tpn["finalT"];
1615                 params.coolingRatio = (double)tpn["coolingRatio"];
1616                 params.itePerStep = tpn["itePerStep"];
1617             }
1618             else
1619                 CV_Error(CV_StsParseError, "Unknown training method (should be BACKPROP or RPROP)");
1620
1621             FileNode tcn = tpn["term_criteria"];
1622             if( !tcn.empty() )
1623             {
1624                 FileNode tcn_e = tcn["epsilon"];
1625                 FileNode tcn_i = tcn["iterations"];
1626                 params.termCrit.type = 0;
1627                 if( !tcn_e.empty() )
1628                 {
1629                     params.termCrit.type |= TermCriteria::EPS;
1630                     params.termCrit.epsilon = (double)tcn_e;
1631                 }
1632                 if( !tcn_i.empty() )
1633                 {
1634                     params.termCrit.type |= TermCriteria::COUNT;
1635                     params.termCrit.maxCount = (int)tcn_i;
1636                 }
1637             }
1638         }
1639     }
1640
1641     void read( const FileNode& fn )
1642     {
1643         clear();
1644
1645         vector<int> _layer_sizes;
1646         readVectorOrMat(fn["layer_sizes"], _layer_sizes);
1647         setLayerSizes( _layer_sizes );
1648
1649         int i, l_count = layer_count();
1650         read_params(fn);
1651
1652         size_t esz = weights[0].elemSize();
1653
1654         FileNode w = fn["input_scale"];
1655         w.readRaw("d", weights[0].ptr(), weights[0].total()*esz);
1656
1657         w = fn["output_scale"];
1658         w.readRaw("d", weights[l_count].ptr(), weights[l_count].total()*esz);
1659
1660         w = fn["inv_output_scale"];
1661         w.readRaw("d", weights[l_count+1].ptr(), weights[l_count+1].total()*esz);
1662
1663         FileNodeIterator w_it = fn["weights"].begin();
1664
1665         for( i = 1; i < l_count; i++, ++w_it )
1666             (*w_it).readRaw("d", weights[i].ptr(), weights[i].total()*esz);
1667         trained = true;
1668     }
1669
1670     Mat getWeights(int layerIdx) const
1671     {
1672         CV_Assert( 0 <= layerIdx && layerIdx < (int)weights.size() );
1673         return weights[layerIdx];
1674     }
1675
1676     bool isTrained() const
1677     {
1678         return trained;
1679     }
1680
1681     bool isClassifier() const
1682     {
1683         return false;
1684     }
1685
1686     int getVarCount() const
1687     {
1688         return layer_sizes.empty() ? 0 : layer_sizes[0];
1689     }
1690
1691     String getDefaultName() const
1692     {
1693         return "opencv_ml_ann_mlp";
1694     }
1695
1696     vector<int> layer_sizes;
1697     vector<Mat> weights;
1698     double f_param1, f_param2;
1699     double min_val, max_val, min_val1, max_val1;
1700     int activ_func;
1701     int max_lsize, max_buf_sz;
1702     AnnParams params;
1703     RNG rng;
1704     Mutex mtx;
1705     bool trained;
1706 };
1707
1708
1709
1710
1711 Ptr<ANN_MLP> ANN_MLP::create()
1712 {
1713     return makePtr<ANN_MLPImpl>();
1714 }
1715
1716 Ptr<ANN_MLP> ANN_MLP::load(const String& filepath)
1717 {
1718     FileStorage fs;
1719     fs.open(filepath, FileStorage::READ);
1720     CV_Assert(fs.isOpened());
1721     Ptr<ANN_MLP> ann = makePtr<ANN_MLPImpl>();
1722     ((ANN_MLPImpl*)ann.get())->read(fs.getFirstTopLevelNode());
1723     return ann;
1724 }
1725
1726 }}
1727
1728 /* End of file. */