1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
13 // Third party copyrights are property of their respective owners.
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
18 // * Redistribution's of source code must retain the above copyright notice,
19 // this list of conditions and the following disclaimer.
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.
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.
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.
41 #include "precomp.hpp"
43 namespace cv { namespace ml {
50 termCrit = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 1000, 0.01 );
51 trainMethod = ANN_MLP::RPROP;
52 bpDWScale = bpMomentScale = 0.1;
53 rpDW0 = 0.1; rpDWPlus = 1.2; rpDWMinus = 0.5;
54 rpDWMin = FLT_EPSILON; rpDWMax = 50.;
55 initialT=10;finalT=0.1,coolingRatio=0.95;itePerStep=10;
59 TermCriteria termCrit;
78 inline T inBounds(T val, T min_val, T max_val)
80 return std::min(std::max(val, min_val), max_val);
83 SimulatedAnnealingSolver::~SimulatedAnnealingSolver()
85 if (impl) delete impl;
88 void SimulatedAnnealingSolver::init()
90 impl = new SimulatedAnnealingSolver::Impl();
93 void SimulatedAnnealingSolver::setIterPerStep(int ite)
96 impl->iterPerStep = ite;
99 int SimulatedAnnealingSolver::run()
101 CV_Assert(impl->initialT>impl->finalT);
102 double Ti = impl->initialT;
103 double previousEnergy = energy();
105 while (Ti > impl->finalT)
107 for (int i = 0; i < impl->iterPerStep; i++)
110 double newEnergy = energy();
111 if (newEnergy < previousEnergy)
113 previousEnergy = newEnergy;
117 double r = impl->rEnergy.uniform(double(0.0), double(1.0));
118 if (r < exp(-(newEnergy - previousEnergy) / Ti))
120 previousEnergy = newEnergy;
124 reverseChangedState();
128 Ti *= impl->coolingRatio;
134 void SimulatedAnnealingSolver::setInitialTemperature(double x)
140 void SimulatedAnnealingSolver::setFinalTemperature(double x)
146 double SimulatedAnnealingSolver::getFinalTemperature()
151 void SimulatedAnnealingSolver::setCoolingRatio(double x)
153 CV_Assert(x>0 && x<1);
154 impl->coolingRatio = x;
157 class SimulatedAnnealingANN_MLP : public ml::SimulatedAnnealingSolver
161 Ptr<ml::TrainData> data;
163 vector<double*> adrVariables;
169 SimulatedAnnealingANN_MLP(ml::ANN_MLP *x, Ptr<ml::TrainData> d) : nn(x), data(d)
175 index = rIndex.uniform(0, nbVariables);
176 double dv = rVar.uniform(-1.0, 1.0);
177 varTmp = *adrVariables[index];
178 *adrVariables[index] = dv;
180 void reverseChangedState()
182 *adrVariables[index] = varTmp;
184 double energy() { return nn->calcError(data, false, noArray()); }
188 Mat l = nn->getLayerSizes();
190 adrVariables.clear();
191 for (int i = 1; i < l.rows-1; i++)
193 Mat w = nn->getWeights(i);
194 for (int j = 0; j < w.rows; j++)
196 for (int k = 0; k < w.cols; k++, nbVariables++)
200 adrVariables.push_back(&w.at<double>(w.rows - 1, k));
204 adrVariables.push_back(&w.at<double>(j, k));
213 double ANN_MLP::getAnnealInitialT() const
215 const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
217 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
218 return this_->getAnnealInitialT();
221 void ANN_MLP::setAnnealInitialT(double val)
223 ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
225 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
226 this_->setAnnealInitialT(val);
229 double ANN_MLP::getAnnealFinalT() const
231 const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
233 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
234 return this_->getAnnealFinalT();
237 void ANN_MLP::setAnnealFinalT(double val)
239 ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
241 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
242 this_->setAnnealFinalT(val);
245 double ANN_MLP::getAnnealCoolingRatio() const
247 const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
249 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
250 return this_->getAnnealCoolingRatio();
253 void ANN_MLP::setAnnealCoolingRatio(double val)
255 ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
257 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
258 this_->setAnnealCoolingRatio(val);
261 int ANN_MLP::getAnnealItePerStep() const
263 const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
265 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
266 return this_->getAnnealItePerStep();
269 void ANN_MLP::setAnnealItePerStep(int val)
271 ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
273 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
274 this_->setAnnealItePerStep(val);
278 class ANN_MLPImpl : public ANN_MLP_ANNEAL
284 setActivationFunction( SIGMOID_SYM, 0, 0);
285 setLayerSizes(Mat());
286 setTrainMethod(ANN_MLP::RPROP, 0.1, FLT_EPSILON);
289 virtual ~ANN_MLPImpl() {}
291 CV_IMPL_PROPERTY(TermCriteria, TermCriteria, params.termCrit)
292 CV_IMPL_PROPERTY(double, BackpropWeightScale, params.bpDWScale)
293 CV_IMPL_PROPERTY(double, BackpropMomentumScale, params.bpMomentScale)
294 CV_IMPL_PROPERTY(double, RpropDW0, params.rpDW0)
295 CV_IMPL_PROPERTY(double, RpropDWPlus, params.rpDWPlus)
296 CV_IMPL_PROPERTY(double, RpropDWMinus, params.rpDWMinus)
297 CV_IMPL_PROPERTY(double, RpropDWMin, params.rpDWMin)
298 CV_IMPL_PROPERTY(double, RpropDWMax, params.rpDWMax)
299 CV_IMPL_PROPERTY(double, AnnealInitialT, params.initialT)
300 CV_IMPL_PROPERTY(double, AnnealFinalT, params.finalT)
301 CV_IMPL_PROPERTY(double, AnnealCoolingRatio, params.coolingRatio)
302 CV_IMPL_PROPERTY(int, AnnealItePerStep, params.itePerStep)
306 min_val = max_val = min_val1 = max_val1 = 0.;
307 rng = RNG((uint64)-1);
310 max_buf_sz = 1 << 12;
313 int layer_count() const { return (int)layer_sizes.size(); }
315 void setTrainMethod(int method, double param1, double param2)
317 if (method != ANN_MLP::RPROP && method != ANN_MLP::BACKPROP && method != ANN_MLP::ANNEAL)
318 method = ANN_MLP::RPROP;
319 params.trainMethod = method;
320 if(method == ANN_MLP::RPROP )
322 if( param1 < FLT_EPSILON )
324 params.rpDW0 = param1;
325 params.rpDWMin = std::max( param2, 0. );
327 else if (method == ANN_MLP::BACKPROP)
331 params.bpDWScale = inBounds<double>(param1, 1e-3, 1.);
334 params.bpMomentScale = std::min(param2, 1.);
336 /* else if (method == ANN_MLP::ANNEAL)
340 if (param2 <= 0 || param2>param1)
342 if (param3 <= 0 || param3 >=1)
346 params.initialT = param1;
347 params.finalT = param2;
348 params.coolingRatio = param3;
349 params.itePerStep = param4;
353 int getTrainMethod() const
355 return params.trainMethod;
358 void setActivationFunction(int _activ_func, double _f_param1, double _f_param2)
360 if( _activ_func < 0 || _activ_func > LEAKYRELU)
361 CV_Error( CV_StsOutOfRange, "Unknown activation function" );
363 activ_func = _activ_func;
368 max_val = 0.95; min_val = -max_val;
369 max_val1 = 0.98; min_val1 = -max_val1;
370 if( fabs(_f_param1) < FLT_EPSILON )
372 if( fabs(_f_param2) < FLT_EPSILON )
376 max_val = 1.; min_val = 0.05;
377 max_val1 = 1.; min_val1 = 0.02;
378 if (fabs(_f_param1) < FLT_EPSILON)
380 if (fabs(_f_param2) < FLT_EPSILON)
384 if (fabs(_f_param1) < FLT_EPSILON)
386 min_val = max_val = min_val1 = max_val1 = 0.;
390 if (fabs(_f_param1) < FLT_EPSILON)
392 min_val = max_val = min_val1 = max_val1 = 0.;
396 min_val = max_val = min_val1 = max_val1 = 0.;
401 f_param1 = _f_param1;
402 f_param2 = _f_param2;
408 int i, j, k, l_count = layer_count();
410 for( i = 1; i < l_count; i++ )
412 int n1 = layer_sizes[i-1];
413 int n2 = layer_sizes[i];
414 double val = 0, G = n2 > 2 ? 0.7*pow((double)n1,1./(n2-1)) : 1.;
415 double* w = weights[i].ptr<double>();
417 // initialize weights using Nguyen-Widrow algorithm
418 for( j = 0; j < n2; j++ )
421 for( k = 0; k <= n1; k++ )
423 val = rng.uniform(0., 1.)*2-1.;
428 if( i < l_count - 1 )
430 s = 1./(s - fabs(val));
431 for( k = 0; k <= n1; k++ )
433 w[n1*n2 + j] *= G*(-1+j*2./n2);
439 Mat getLayerSizes() const
441 return Mat_<int>(layer_sizes, true);
444 void setLayerSizes( InputArray _layer_sizes )
448 _layer_sizes.copyTo(layer_sizes);
449 int l_count = layer_count();
451 weights.resize(l_count + 2);
456 for( int i = 0; i < l_count; i++ )
458 int n = layer_sizes[i];
459 if( n < 1 + (0 < i && i < l_count-1))
460 CV_Error( CV_StsOutOfRange,
461 "there should be at least one input and one output "
462 "and every hidden layer must have more than 1 neuron" );
463 max_lsize = std::max( max_lsize, n );
465 weights[i].create(layer_sizes[i-1]+1, n, CV_64F);
468 int ninputs = layer_sizes.front();
469 int noutputs = layer_sizes.back();
470 weights[0].create(1, ninputs*2, CV_64F);
471 weights[l_count].create(1, noutputs*2, CV_64F);
472 weights[l_count+1].create(1, noutputs*2, CV_64F);
476 float predict( InputArray _inputs, OutputArray _outputs, int ) const
479 CV_Error( CV_StsError, "The network has not been trained or loaded" );
481 Mat inputs = _inputs.getMat();
482 int type = inputs.type(), l_count = layer_count();
483 int n = inputs.rows, dn0 = n;
485 CV_Assert( (type == CV_32F || type == CV_64F) && inputs.cols == layer_sizes[0] );
486 int noutputs = layer_sizes[l_count-1];
489 int min_buf_sz = 2*max_lsize;
490 int buf_sz = n*min_buf_sz;
492 if( buf_sz > max_buf_sz )
494 dn0 = max_buf_sz/min_buf_sz;
495 dn0 = std::max( dn0, 1 );
496 buf_sz = dn0*min_buf_sz;
499 cv::AutoBuffer<double> _buf(buf_sz+noutputs);
502 if( !_outputs.needed() )
505 outputs = Mat(n, noutputs, type, buf + buf_sz);
509 _outputs.create(n, noutputs, type);
510 outputs = _outputs.getMat();
514 for( int i = 0; i < n; i += dn )
516 dn = std::min( dn0, n - i );
518 Mat layer_in = inputs.rowRange(i, i + dn);
519 Mat layer_out( dn, layer_in.cols, CV_64F, buf);
521 scale_input( layer_in, layer_out );
522 layer_in = layer_out;
524 for( int j = 1; j < l_count; j++ )
526 double* data = buf + ((j&1) ? max_lsize*dn0 : 0);
527 int cols = layer_sizes[j];
529 layer_out = Mat(dn, cols, CV_64F, data);
530 Mat w = weights[j].rowRange(0, layer_in.cols);
531 gemm(layer_in, w, 1, noArray(), 0, layer_out);
532 calc_activ_func( layer_out, weights[j] );
534 layer_in = layer_out;
537 layer_out = outputs.rowRange(i, i + dn);
538 scale_output( layer_in, layer_out );
543 int maxIdx[] = {0, 0};
544 minMaxIdx(outputs, 0, 0, 0, maxIdx);
545 return (float)(maxIdx[0] + maxIdx[1]);
551 void scale_input( const Mat& _src, Mat& _dst ) const
553 int cols = _src.cols;
554 const double* w = weights[0].ptr<double>();
556 if( _src.type() == CV_32F )
558 for( int i = 0; i < _src.rows; i++ )
560 const float* src = _src.ptr<float>(i);
561 double* dst = _dst.ptr<double>(i);
562 for( int j = 0; j < cols; j++ )
563 dst[j] = src[j]*w[j*2] + w[j*2+1];
568 for( int i = 0; i < _src.rows; i++ )
570 const double* src = _src.ptr<double>(i);
571 double* dst = _dst.ptr<double>(i);
572 for( int j = 0; j < cols; j++ )
573 dst[j] = src[j]*w[j*2] + w[j*2+1];
578 void scale_output( const Mat& _src, Mat& _dst ) const
580 int cols = _src.cols;
581 const double* w = weights[layer_count()].ptr<double>();
583 if( _dst.type() == CV_32F )
585 for( int i = 0; i < _src.rows; i++ )
587 const double* src = _src.ptr<double>(i);
588 float* dst = _dst.ptr<float>(i);
589 for( int j = 0; j < cols; j++ )
590 dst[j] = (float)(src[j]*w[j*2] + w[j*2+1]);
595 for( int i = 0; i < _src.rows; i++ )
597 const double* src = _src.ptr<double>(i);
598 double* dst = _dst.ptr<double>(i);
599 for( int j = 0; j < cols; j++ )
600 dst[j] = src[j]*w[j*2] + w[j*2+1];
605 void calc_activ_func(Mat& sums, const Mat& w) const
607 const double* bias = w.ptr<double>(w.rows - 1);
608 int i, j, n = sums.rows, cols = sums.cols;
609 double scale = 0, scale2 = f_param2;
620 scale = -f_param1*f_param1;
632 CV_Assert(sums.isContinuous());
634 if (activ_func != GAUSSIAN)
636 for (i = 0; i < n; i++)
638 double* data = sums.ptr<double>(i);
639 for (j = 0; j < cols; j++)
641 data[j] = (data[j] + bias[j])*scale;
642 if (activ_func == RELU)
645 if (activ_func == LEAKYRELU)
651 if (activ_func == IDENTITY || activ_func == RELU || activ_func == LEAKYRELU)
656 for (i = 0; i < n; i++)
658 double* data = sums.ptr<double>(i);
659 for (j = 0; j < cols; j++)
661 double t = data[j] + bias[j];
669 if (sums.isContinuous())
678 for (i = 0; i < n; i++)
680 double* data = sums.ptr<double>(i);
681 for (j = 0; j < cols; j++)
683 if (!cvIsInf(data[j]))
685 double t = scale2*(1. - data[j]) / (1. + data[j]);
697 for (i = 0; i < n; i++)
699 double* data = sums.ptr<double>(i);
700 for (j = 0; j < cols; j++)
701 data[j] = scale2*data[j];
710 void calc_activ_func_deriv(Mat& _xf, Mat& _df, const Mat& w) const
712 const double* bias = w.ptr<double>(w.rows - 1);
713 int i, j, n = _xf.rows, cols = _xf.cols;
715 if (activ_func == IDENTITY)
717 for (i = 0; i < n; i++)
719 double* xf = _xf.ptr<double>(i);
720 double* df = _df.ptr<double>(i);
722 for (j = 0; j < cols; j++)
729 else if (activ_func == RELU)
731 for (i = 0; i < n; i++)
733 double* xf = _xf.ptr<double>(i);
734 double* df = _df.ptr<double>(i);
736 for (j = 0; j < cols; j++)
749 else if (activ_func == LEAKYRELU)
751 for (i = 0; i < n; i++)
753 double* xf = _xf.ptr<double>(i);
754 double* df = _df.ptr<double>(i);
756 for (j = 0; j < cols; j++)
761 xf[j] = f_param1*xf[j];
769 else if (activ_func == GAUSSIAN)
771 double scale = -f_param1*f_param1;
772 double scale2 = scale*f_param2;
773 for (i = 0; i < n; i++)
775 double* xf = _xf.ptr<double>(i);
776 double* df = _df.ptr<double>(i);
778 for (j = 0; j < cols; j++)
780 double t = xf[j] + bias[j];
781 df[j] = t * 2 * scale2;
787 for (i = 0; i < n; i++)
789 double* xf = _xf.ptr<double>(i);
790 double* df = _df.ptr<double>(i);
792 for (j = 0; j < cols; j++)
798 double scale = f_param1;
799 double scale2 = f_param2;
801 for (i = 0; i < n; i++)
803 double* xf = _xf.ptr<double>(i);
804 double* df = _df.ptr<double>(i);
806 for (j = 0; j < cols; j++)
808 xf[j] = (xf[j] + bias[j])*scale;
809 df[j] = -fabs(xf[j]);
815 // ((1+exp(-ax))^-1)'=a*((1+exp(-ax))^-2)*exp(-ax);
816 // ((1-exp(-ax))/(1+exp(-ax)))'=(a*exp(-ax)*(1+exp(-ax)) + a*exp(-ax)*(1-exp(-ax)))/(1+exp(-ax))^2=
817 // 2*a*exp(-ax)/(1+exp(-ax))^2
818 scale *= 2 * f_param2;
819 for (i = 0; i < n; i++)
821 double* xf = _xf.ptr<double>(i);
822 double* df = _df.ptr<double>(i);
824 for (j = 0; j < cols; j++)
826 int s0 = xf[j] > 0 ? 1 : -1;
827 double t0 = 1. / (1. + df[j]);
828 double t1 = scale*df[j] * t0*t0;
829 t0 *= scale2*(1. - df[j])*s0;
837 void calc_input_scale( const Mat& inputs, int flags )
839 bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
840 bool no_scale = (flags & NO_INPUT_SCALE) != 0;
841 double* scale = weights[0].ptr<double>();
842 int count = inputs.rows;
846 int i, j, vcount = layer_sizes[0];
847 int type = inputs.type();
848 double a = no_scale ? 1. : 0.;
850 for( j = 0; j < vcount; j++ )
851 scale[2*j] = a, scale[j*2+1] = 0.;
856 for( i = 0; i < count; i++ )
858 const uchar* p = inputs.ptr(i);
859 const float* f = (const float*)p;
860 const double* d = (const double*)p;
861 for( j = 0; j < vcount; j++ )
863 double t = type == CV_32F ? (double)f[j] : d[j];
869 for( j = 0; j < vcount; j++ )
871 double s = scale[j*2], s2 = scale[j*2+1];
872 double m = s/count, sigma2 = s2/count - m*m;
873 scale[j*2] = sigma2 < DBL_EPSILON ? 1 : 1./sqrt(sigma2);
874 scale[j*2+1] = -m*scale[j*2];
879 void calc_output_scale( const Mat& outputs, int flags )
881 int i, j, vcount = layer_sizes.back();
882 int type = outputs.type();
883 double m = min_val, M = max_val, m1 = min_val1, M1 = max_val1;
884 bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
885 bool no_scale = (flags & NO_OUTPUT_SCALE) != 0;
886 int l_count = layer_count();
887 double* scale = weights[l_count].ptr<double>();
888 double* inv_scale = weights[l_count+1].ptr<double>();
889 int count = outputs.rows;
893 double a0 = no_scale ? 1 : DBL_MAX, b0 = no_scale ? 0 : -DBL_MAX;
895 for( j = 0; j < vcount; j++ )
897 scale[2*j] = inv_scale[2*j] = a0;
898 scale[j*2+1] = inv_scale[2*j+1] = b0;
905 for( i = 0; i < count; i++ )
907 const uchar* p = outputs.ptr(i);
908 const float* f = (const float*)p;
909 const double* d = (const double*)p;
911 for( j = 0; j < vcount; j++ )
913 double t = type == CV_32F ? (double)f[j] : d[j];
917 double mj = scale[j*2], Mj = scale[j*2+1];
926 t = t*inv_scale[j*2] + inv_scale[2*j+1];
927 if( t < m1 || t > M1 )
928 CV_Error( CV_StsOutOfRange,
929 "Some of new output training vector components run exceed the original range too much" );
935 for( j = 0; j < vcount; j++ )
937 // map mj..Mj to m..M
938 double mj = scale[j*2], Mj = scale[j*2+1];
940 double delta = Mj - mj;
941 if( delta < DBL_EPSILON )
942 a = 1, b = (M + m - Mj - mj)*0.5;
944 a = (M - m)/delta, b = m - mj*a;
945 inv_scale[j*2] = a; inv_scale[j*2+1] = b;
947 scale[j*2] = a; scale[j*2+1] = b;
951 void prepare_to_train( const Mat& inputs, const Mat& outputs,
952 Mat& sample_weights, int flags )
954 if( layer_sizes.empty() )
955 CV_Error( CV_StsError,
956 "The network has not been created. Use method create or the appropriate constructor" );
958 if( (inputs.type() != CV_32F && inputs.type() != CV_64F) ||
959 inputs.cols != layer_sizes[0] )
960 CV_Error( CV_StsBadArg,
961 "input training data should be a floating-point matrix with "
962 "the number of rows equal to the number of training samples and "
963 "the number of columns equal to the size of 0-th (input) layer" );
965 if( (outputs.type() != CV_32F && outputs.type() != CV_64F) ||
966 outputs.cols != layer_sizes.back() )
967 CV_Error( CV_StsBadArg,
968 "output training data should be a floating-point matrix with "
969 "the number of rows equal to the number of training samples and "
970 "the number of columns equal to the size of last (output) layer" );
972 if( inputs.rows != outputs.rows )
973 CV_Error( CV_StsUnmatchedSizes, "The numbers of input and output samples do not match" );
976 double s = sum(sample_weights)[0];
977 sample_weights.convertTo(temp, CV_64F, 1./s);
978 sample_weights = temp;
980 calc_input_scale( inputs, flags );
981 calc_output_scale( outputs, flags );
984 bool train( const Ptr<TrainData>& trainData, int flags )
986 const int MAX_ITER = 1000;
987 const double DEFAULT_EPSILON = FLT_EPSILON;
989 // initialize training data
990 Mat inputs = trainData->getTrainSamples();
991 Mat outputs = trainData->getTrainResponses();
992 Mat sw = trainData->getTrainSampleWeights();
993 prepare_to_train( inputs, outputs, sw, flags );
995 // ... and link weights
996 if( !(flags & UPDATE_WEIGHTS) )
999 TermCriteria termcrit;
1000 termcrit.type = TermCriteria::COUNT + TermCriteria::EPS;
1001 termcrit.maxCount = std::max((params.termCrit.type & CV_TERMCRIT_ITER ? params.termCrit.maxCount : MAX_ITER), 1);
1002 termcrit.epsilon = std::max((params.termCrit.type & CV_TERMCRIT_EPS ? params.termCrit.epsilon : DEFAULT_EPSILON), DBL_EPSILON);
1005 switch(params.trainMethod){
1006 case ANN_MLP::BACKPROP:
1007 iter = train_backprop(inputs, outputs, sw, termcrit);
1009 case ANN_MLP::RPROP:
1010 iter = train_rprop(inputs, outputs, sw, termcrit);
1012 case ANN_MLP::ANNEAL:
1013 iter = train_anneal(trainData);
1019 int train_anneal(const Ptr<TrainData>& trainData)
1021 SimulatedAnnealingANN_MLP t(this, trainData);
1022 t.setFinalTemperature(params.finalT);
1023 t.setInitialTemperature(params.initialT);
1024 t.setCoolingRatio(params.coolingRatio);
1025 t.setIterPerStep(params.itePerStep);
1026 trained = true; // Enable call to CalcError
1032 int train_backprop( const Mat& inputs, const Mat& outputs, const Mat& _sw, TermCriteria termCrit )
1035 double prev_E = DBL_MAX*0.5, E = 0;
1036 int itype = inputs.type(), otype = outputs.type();
1038 int count = inputs.rows;
1040 int iter = -1, max_iter = termCrit.maxCount*count;
1041 double epsilon = termCrit.epsilon*count;
1043 int l_count = layer_count();
1044 int ivcount = layer_sizes[0];
1045 int ovcount = layer_sizes.back();
1048 vector<vector<double> > x(l_count);
1049 vector<vector<double> > df(l_count);
1050 vector<Mat> dw(l_count);
1052 for( i = 0; i < l_count; i++ )
1054 int n = layer_sizes[i];
1057 dw[i] = Mat::zeros(weights[i].size(), CV_64F);
1060 Mat _idx_m(1, count, CV_32S);
1061 int* _idx = _idx_m.ptr<int>();
1062 for( i = 0; i < count; i++ )
1065 AutoBuffer<double> _buf(max_lsize*2);
1066 double* buf[] = { _buf, (double*)_buf + max_lsize };
1068 const double* sw = _sw.empty() ? 0 : _sw.ptr<double>();
1070 // run back-propagation loop
1074 E = 1/2*||u - x_N||^2
1075 grad_N = (x_N - u)*f'(y_i)
1076 dw_i(t) = momentum*dw_i(t-1) + dw_scale*x_{i-1}*grad_i
1077 w_i(t+1) = w_i(t) + dw_i(t)
1078 grad_{i-1} = w_i^t*grad_i
1080 for( iter = 0; iter < max_iter; iter++ )
1082 int idx = iter % count;
1083 double sweight = sw ? count*sw[idx] : 1.;
1087 //printf("%d. E = %g\n", iter/count, E);
1088 if( fabs(prev_E - E) < epsilon )
1094 for( i = 0; i <count; i++ )
1096 j = rng.uniform(0, count);
1097 k = rng.uniform(0, count);
1098 std::swap(_idx[j], _idx[k]);
1104 const uchar* x0data_p = inputs.ptr(idx);
1105 const float* x0data_f = (const float*)x0data_p;
1106 const double* x0data_d = (const double*)x0data_p;
1108 double* w = weights[0].ptr<double>();
1109 for( j = 0; j < ivcount; j++ )
1110 x[0][j] = (itype == CV_32F ? (double)x0data_f[j] : x0data_d[j])*w[j*2] + w[j*2 + 1];
1112 Mat x1( 1, ivcount, CV_64F, &x[0][0] );
1114 // forward pass, compute y[i]=w*x[i-1], x[i]=f(y[i]), df[i]=f'(y[i])
1115 for( i = 1; i < l_count; i++ )
1117 int n = layer_sizes[i];
1118 Mat x2(1, n, CV_64F, &x[i][0] );
1119 Mat _w = weights[i].rowRange(0, x1.cols);
1120 gemm(x1, _w, 1, noArray(), 0, x2);
1121 Mat _df(1, n, CV_64F, &df[i][0] );
1122 calc_activ_func_deriv( x2, _df, weights[i] );
1126 Mat grad1( 1, ovcount, CV_64F, buf[l_count&1] );
1127 w = weights[l_count+1].ptr<double>();
1130 const uchar* udata_p = outputs.ptr(idx);
1131 const float* udata_f = (const float*)udata_p;
1132 const double* udata_d = (const double*)udata_p;
1134 double* gdata = grad1.ptr<double>();
1135 for( k = 0; k < ovcount; k++ )
1137 double t = (otype == CV_32F ? (double)udata_f[k] : udata_d[k])*w[k*2] + w[k*2+1] - x[l_count-1][k];
1138 gdata[k] = t*sweight;
1143 // backward pass, update weights
1144 for( i = l_count-1; i > 0; i-- )
1146 int n1 = layer_sizes[i-1], n2 = layer_sizes[i];
1147 Mat _df(1, n2, CV_64F, &df[i][0]);
1148 multiply( grad1, _df, grad1 );
1149 Mat _x(n1+1, 1, CV_64F, &x[i-1][0]);
1151 gemm( _x, grad1, params.bpDWScale, dw[i], params.bpMomentScale, dw[i] );
1152 add( weights[i], dw[i], weights[i] );
1155 Mat grad2(1, n1, CV_64F, buf[i&1]);
1156 Mat _w = weights[i].rowRange(0, n1);
1157 gemm( grad1, _w, 1, noArray(), 0, grad2, GEMM_2_T );
1167 struct RPropLoop : public ParallelLoopBody
1169 RPropLoop(ANN_MLPImpl* _ann,
1170 const Mat& _inputs, const Mat& _outputs, const Mat& _sw,
1171 int _dcount0, vector<Mat>& _dEdw, double* _E)
1176 sw = _sw.ptr<double>();
1184 Mat inputs, outputs;
1189 void operator()( const Range& range ) const
1191 double inv_count = 1./inputs.rows;
1192 int ivcount = ann->layer_sizes.front();
1193 int ovcount = ann->layer_sizes.back();
1194 int itype = inputs.type(), otype = outputs.type();
1195 int count = inputs.rows;
1196 int i, j, k, l_count = ann->layer_count();
1197 vector<vector<double> > x(l_count);
1198 vector<vector<double> > df(l_count);
1199 vector<double> _buf(ann->max_lsize*dcount0*2);
1200 double* buf[] = { &_buf[0], &_buf[ann->max_lsize*dcount0] };
1203 for( i = 0; i < l_count; i++ )
1205 x[i].resize(ann->layer_sizes[i]*dcount0);
1206 df[i].resize(ann->layer_sizes[i]*dcount0);
1209 for( int si = range.start; si < range.end; si++ )
1211 int i0 = si*dcount0, i1 = std::min((si + 1)*dcount0, count);
1212 int dcount = i1 - i0;
1213 const double* w = ann->weights[0].ptr<double>();
1215 // grab and preprocess input data
1216 for( i = 0; i < dcount; i++ )
1218 const uchar* x0data_p = inputs.ptr(i0 + i);
1219 const float* x0data_f = (const float*)x0data_p;
1220 const double* x0data_d = (const double*)x0data_p;
1222 double* xdata = &x[0][i*ivcount];
1223 for( j = 0; j < ivcount; j++ )
1224 xdata[j] = (itype == CV_32F ? (double)x0data_f[j] : x0data_d[j])*w[j*2] + w[j*2+1];
1226 Mat x1(dcount, ivcount, CV_64F, &x[0][0]);
1228 // forward pass, compute y[i]=w*x[i-1], x[i]=f(y[i]), df[i]=f'(y[i])
1229 for( i = 1; i < l_count; i++ )
1231 Mat x2( dcount, ann->layer_sizes[i], CV_64F, &x[i][0] );
1232 Mat _w = ann->weights[i].rowRange(0, x1.cols);
1233 gemm( x1, _w, 1, noArray(), 0, x2 );
1234 Mat _df( x2.size(), CV_64F, &df[i][0] );
1235 ann->calc_activ_func_deriv( x2, _df, ann->weights[i] );
1239 Mat grad1(dcount, ovcount, CV_64F, buf[l_count & 1]);
1241 w = ann->weights[l_count+1].ptr<double>();
1244 for( i = 0; i < dcount; i++ )
1246 const uchar* udata_p = outputs.ptr(i0+i);
1247 const float* udata_f = (const float*)udata_p;
1248 const double* udata_d = (const double*)udata_p;
1250 const double* xdata = &x[l_count-1][i*ovcount];
1251 double* gdata = grad1.ptr<double>(i);
1252 double sweight = sw ? sw[si+i] : inv_count, E1 = 0;
1254 for( j = 0; j < ovcount; j++ )
1256 double t = (otype == CV_32F ? (double)udata_f[j] : udata_d[j])*w[j*2] + w[j*2+1] - xdata[j];
1257 gdata[j] = t*sweight;
1263 for( i = l_count-1; i > 0; i-- )
1265 int n1 = ann->layer_sizes[i-1], n2 = ann->layer_sizes[i];
1266 Mat _df(dcount, n2, CV_64F, &df[i][0]);
1267 multiply(grad1, _df, grad1);
1270 AutoLock lock(ann->mtx);
1271 Mat _dEdw = dEdw->at(i).rowRange(0, n1);
1272 x1 = Mat(dcount, n1, CV_64F, &x[i-1][0]);
1273 gemm(x1, grad1, 1, _dEdw, 1, _dEdw, GEMM_1_T);
1275 // update bias part of dEdw
1276 double* dst = dEdw->at(i).ptr<double>(n1);
1277 for( k = 0; k < dcount; k++ )
1279 const double* src = grad1.ptr<double>(k);
1280 for( j = 0; j < n2; j++ )
1285 Mat grad2( dcount, n1, CV_64F, buf[i&1] );
1288 Mat _w = ann->weights[i].rowRange(0, n1);
1289 gemm(grad1, _w, 1, noArray(), 0, grad2, GEMM_2_T);
1295 AutoLock lock(ann->mtx);
1301 int train_rprop( const Mat& inputs, const Mat& outputs, const Mat& _sw, TermCriteria termCrit )
1303 const int max_buf_size = 1 << 16;
1304 int i, iter = -1, count = inputs.rows;
1306 double prev_E = DBL_MAX*0.5;
1308 int max_iter = termCrit.maxCount;
1309 double epsilon = termCrit.epsilon;
1310 double dw_plus = params.rpDWPlus;
1311 double dw_minus = params.rpDWMinus;
1312 double dw_min = params.rpDWMin;
1313 double dw_max = params.rpDWMax;
1315 int l_count = layer_count();
1318 vector<Mat> dw(l_count), dEdw(l_count), prev_dEdw_sign(l_count);
1321 for( i = 0; i < l_count; i++ )
1323 total += layer_sizes[i];
1324 dw[i].create(weights[i].size(), CV_64F);
1325 dw[i].setTo(Scalar::all(params.rpDW0));
1326 prev_dEdw_sign[i] = Mat::zeros(weights[i].size(), CV_8S);
1327 dEdw[i] = Mat::zeros(weights[i].size(), CV_64F);
1330 int dcount0 = max_buf_size/(2*total);
1331 dcount0 = std::max( dcount0, 1 );
1332 dcount0 = std::min( dcount0, count );
1333 int chunk_count = (count + dcount0 - 1)/dcount0;
1337 y_i(t) = w_i(t)*x_{i-1}(t)
1339 E = sum_over_all_samples(1/2*||u - x_N||^2)
1340 grad_N = (x_N - u)*f'(y_i)
1342 std::min(dw_i{jk}(t)*dw_plus, dw_max), if dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) > 0
1343 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
1346 if (dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) < 0)
1349 w_i{jk}(t+1) = w_i{jk}(t) + dw_i{jk}(t)
1350 grad_{i-1}(t) = w_i^t(t)*grad_i(t)
1352 for( iter = 0; iter < max_iter; iter++ )
1356 for( i = 0; i < l_count; i++ )
1357 dEdw[i].setTo(Scalar::all(0));
1359 // first, iterate through all the samples and compute dEdw
1360 RPropLoop invoker(this, inputs, outputs, _sw, dcount0, dEdw, &E);
1361 parallel_for_(Range(0, chunk_count), invoker);
1362 //invoker(Range(0, chunk_count));
1364 // now update weights
1365 for( i = 1; i < l_count; i++ )
1367 int n1 = layer_sizes[i-1], n2 = layer_sizes[i];
1368 for( int k = 0; k <= n1; k++ )
1370 CV_Assert(weights[i].size() == Size(n2, n1+1));
1371 double* wk = weights[i].ptr<double>(k);
1372 double* dwk = dw[i].ptr<double>(k);
1373 double* dEdwk = dEdw[i].ptr<double>(k);
1374 schar* prevEk = prev_dEdw_sign[i].ptr<schar>(k);
1376 for( int j = 0; j < n2; j++ )
1378 double Eval = dEdwk[j];
1379 double dval = dwk[j];
1380 double wval = wk[j];
1381 int s = CV_SIGN(Eval);
1382 int ss = prevEk[j]*s;
1386 dval = std::min( dval, dw_max );
1388 wk[j] = wval + dval*s;
1393 dval = std::max( dval, dw_min );
1396 wk[j] = wval + dval*s;
1400 prevEk[j] = (schar)s;
1401 wk[j] = wval + dval*s;
1408 //printf("%d. E = %g\n", iter, E);
1409 if( fabs(prev_E - E) < epsilon )
1417 void write_params( FileStorage& fs ) const
1419 const char* activ_func_name = activ_func == IDENTITY ? "IDENTITY" :
1420 activ_func == SIGMOID_SYM ? "SIGMOID_SYM" :
1421 activ_func == GAUSSIAN ? "GAUSSIAN" :
1422 activ_func == RELU ? "RELU" :
1423 activ_func == LEAKYRELU ? "LEAKYRELU" : 0;
1425 if( activ_func_name )
1426 fs << "activation_function" << activ_func_name;
1428 fs << "activation_function_id" << activ_func;
1430 if( activ_func != IDENTITY )
1432 fs << "f_param1" << f_param1;
1433 fs << "f_param2" << f_param2;
1436 fs << "min_val" << min_val << "max_val" << max_val << "min_val1" << min_val1 << "max_val1" << max_val1;
1438 fs << "training_params" << "{";
1439 if( params.trainMethod == ANN_MLP::BACKPROP )
1441 fs << "train_method" << "BACKPROP";
1442 fs << "dw_scale" << params.bpDWScale;
1443 fs << "moment_scale" << params.bpMomentScale;
1445 else if (params.trainMethod == ANN_MLP::RPROP)
1447 fs << "train_method" << "RPROP";
1448 fs << "dw0" << params.rpDW0;
1449 fs << "dw_plus" << params.rpDWPlus;
1450 fs << "dw_minus" << params.rpDWMinus;
1451 fs << "dw_min" << params.rpDWMin;
1452 fs << "dw_max" << params.rpDWMax;
1454 else if (params.trainMethod == ANN_MLP::ANNEAL)
1456 fs << "train_method" << "ANNEAL";
1457 fs << "initialT" << params.initialT;
1458 fs << "finalT" << params.finalT;
1459 fs << "coolingRatio" << params.coolingRatio;
1460 fs << "itePerStep" << params.itePerStep;
1463 CV_Error(CV_StsError, "Unknown training method");
1465 fs << "term_criteria" << "{";
1466 if( params.termCrit.type & TermCriteria::EPS )
1467 fs << "epsilon" << params.termCrit.epsilon;
1468 if( params.termCrit.type & TermCriteria::COUNT )
1469 fs << "iterations" << params.termCrit.maxCount;
1473 void write( FileStorage& fs ) const
1475 if( layer_sizes.empty() )
1477 int i, l_count = layer_count();
1480 fs << "layer_sizes" << layer_sizes;
1484 size_t esz = weights[0].elemSize();
1486 fs << "input_scale" << "[";
1487 fs.writeRaw("d", weights[0].ptr(), weights[0].total()*esz);
1489 fs << "]" << "output_scale" << "[";
1490 fs.writeRaw("d", weights[l_count].ptr(), weights[l_count].total()*esz);
1492 fs << "]" << "inv_output_scale" << "[";
1493 fs.writeRaw("d", weights[l_count+1].ptr(), weights[l_count+1].total()*esz);
1495 fs << "]" << "weights" << "[";
1496 for( i = 1; i < l_count; i++ )
1499 fs.writeRaw("d", weights[i].ptr(), weights[i].total()*esz);
1505 void read_params( const FileNode& fn )
1507 String activ_func_name = (String)fn["activation_function"];
1508 if( !activ_func_name.empty() )
1510 activ_func = activ_func_name == "SIGMOID_SYM" ? SIGMOID_SYM :
1511 activ_func_name == "IDENTITY" ? IDENTITY :
1512 activ_func_name == "RELU" ? RELU :
1513 activ_func_name == "LEAKYRELU" ? LEAKYRELU :
1514 activ_func_name == "GAUSSIAN" ? GAUSSIAN : -1;
1515 CV_Assert( activ_func >= 0 );
1518 activ_func = (int)fn["activation_function_id"];
1520 f_param1 = (double)fn["f_param1"];
1521 f_param2 = (double)fn["f_param2"];
1523 setActivationFunction( activ_func, f_param1, f_param2);
1525 min_val = (double)fn["min_val"];
1526 max_val = (double)fn["max_val"];
1527 min_val1 = (double)fn["min_val1"];
1528 max_val1 = (double)fn["max_val1"];
1530 FileNode tpn = fn["training_params"];
1531 params = AnnParams();
1535 String tmethod_name = (String)tpn["train_method"];
1537 if( tmethod_name == "BACKPROP" )
1539 params.trainMethod = ANN_MLP::BACKPROP;
1540 params.bpDWScale = (double)tpn["dw_scale"];
1541 params.bpMomentScale = (double)tpn["moment_scale"];
1543 else if (tmethod_name == "RPROP")
1545 params.trainMethod = ANN_MLP::RPROP;
1546 params.rpDW0 = (double)tpn["dw0"];
1547 params.rpDWPlus = (double)tpn["dw_plus"];
1548 params.rpDWMinus = (double)tpn["dw_minus"];
1549 params.rpDWMin = (double)tpn["dw_min"];
1550 params.rpDWMax = (double)tpn["dw_max"];
1552 else if (tmethod_name == "ANNEAL")
1554 params.trainMethod = ANN_MLP::ANNEAL;
1555 params.initialT = (double)tpn["initialT"];
1556 params.finalT = (double)tpn["finalT"];
1557 params.coolingRatio = (double)tpn["coolingRatio"];
1558 params.itePerStep = tpn["itePerStep"];
1561 CV_Error(CV_StsParseError, "Unknown training method (should be BACKPROP or RPROP)");
1563 FileNode tcn = tpn["term_criteria"];
1566 FileNode tcn_e = tcn["epsilon"];
1567 FileNode tcn_i = tcn["iterations"];
1568 params.termCrit.type = 0;
1569 if( !tcn_e.empty() )
1571 params.termCrit.type |= TermCriteria::EPS;
1572 params.termCrit.epsilon = (double)tcn_e;
1574 if( !tcn_i.empty() )
1576 params.termCrit.type |= TermCriteria::COUNT;
1577 params.termCrit.maxCount = (int)tcn_i;
1583 void read( const FileNode& fn )
1587 vector<int> _layer_sizes;
1588 readVectorOrMat(fn["layer_sizes"], _layer_sizes);
1589 setLayerSizes( _layer_sizes );
1591 int i, l_count = layer_count();
1594 size_t esz = weights[0].elemSize();
1596 FileNode w = fn["input_scale"];
1597 w.readRaw("d", weights[0].ptr(), weights[0].total()*esz);
1599 w = fn["output_scale"];
1600 w.readRaw("d", weights[l_count].ptr(), weights[l_count].total()*esz);
1602 w = fn["inv_output_scale"];
1603 w.readRaw("d", weights[l_count+1].ptr(), weights[l_count+1].total()*esz);
1605 FileNodeIterator w_it = fn["weights"].begin();
1607 for( i = 1; i < l_count; i++, ++w_it )
1608 (*w_it).readRaw("d", weights[i].ptr(), weights[i].total()*esz);
1612 Mat getWeights(int layerIdx) const
1614 CV_Assert( 0 <= layerIdx && layerIdx < (int)weights.size() );
1615 return weights[layerIdx];
1618 bool isTrained() const
1623 bool isClassifier() const
1628 int getVarCount() const
1630 return layer_sizes.empty() ? 0 : layer_sizes[0];
1633 String getDefaultName() const
1635 return "opencv_ml_ann_mlp";
1638 vector<int> layer_sizes;
1639 vector<Mat> weights;
1640 double f_param1, f_param2;
1641 double min_val, max_val, min_val1, max_val1;
1643 int max_lsize, max_buf_sz;
1653 Ptr<ANN_MLP> ANN_MLP::create()
1655 return makePtr<ANN_MLPImpl>();
1658 Ptr<ANN_MLP> ANN_MLP::load(const String& filepath)
1661 fs.open(filepath, FileStorage::READ);
1662 CV_Assert(fs.isOpened());
1663 Ptr<ANN_MLP> ann = makePtr<ANN_MLPImpl>();
1664 ((ANN_MLPImpl*)ann.get())->read(fs.getFirstTopLevelNode());
1668 double ANN_MLP_ANNEAL::getAnnealInitialT() const
1670 const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
1672 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1673 return this_->getAnnealInitialT();
1676 void ANN_MLP_ANNEAL::setAnnealInitialT(double val)
1678 ANN_MLPImpl* this_ = dynamic_cast< ANN_MLPImpl*>(this);
1680 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1681 this_->setAnnealInitialT(val);
1684 double ANN_MLP_ANNEAL::getAnnealFinalT() const
1686 const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
1688 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1689 return this_->getAnnealFinalT();
1692 void ANN_MLP_ANNEAL::setAnnealFinalT(double val)
1694 ANN_MLPImpl* this_ = dynamic_cast<ANN_MLPImpl*>(this);
1696 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1697 this_->setAnnealFinalT(val);
1700 double ANN_MLP_ANNEAL::getAnnealCoolingRatio() const
1702 const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
1704 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1705 return this_->getAnnealCoolingRatio();
1708 void ANN_MLP_ANNEAL::setAnnealCoolingRatio(double val)
1710 ANN_MLPImpl* this_ = dynamic_cast< ANN_MLPImpl*>(this);
1712 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1713 this_->setAnnealInitialT(val);
1716 int ANN_MLP_ANNEAL::getAnnealItePerStep() const
1718 const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
1720 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1721 return this_->getAnnealItePerStep();
1724 void ANN_MLP_ANNEAL::setAnnealItePerStep(int val)
1726 ANN_MLPImpl* this_ = dynamic_cast<ANN_MLPImpl*>(this);
1728 CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
1729 this_->setAnnealInitialT(val);