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 CvANN_MLP_TrainParams::CvANN_MLP_TrainParams()
45 term_crit = cvTermCriteria( CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 1000, 0.01 );
47 bp_dw_scale = bp_moment_scale = 0.1;
48 rp_dw0 = 0.1; rp_dw_plus = 1.2; rp_dw_minus = 0.5;
49 rp_dw_min = FLT_EPSILON; rp_dw_max = 50.;
53 CvANN_MLP_TrainParams::CvANN_MLP_TrainParams( CvTermCriteria _term_crit,
55 double _param1, double _param2 )
57 term_crit = _term_crit;
58 train_method = _train_method;
59 bp_dw_scale = bp_moment_scale = 0.1;
60 rp_dw0 = 1.; rp_dw_plus = 1.2; rp_dw_minus = 0.5;
61 rp_dw_min = FLT_EPSILON; rp_dw_max = 50.;
63 if( train_method == RPROP )
66 if( rp_dw0 < FLT_EPSILON )
69 rp_dw_min = MAX( rp_dw_min, 0 );
71 else if( train_method == BACKPROP )
73 bp_dw_scale = _param1;
74 if( bp_dw_scale <= 0 )
76 bp_dw_scale = MAX( bp_dw_scale, 1e-3 );
77 bp_dw_scale = MIN( bp_dw_scale, 1 );
78 bp_moment_scale = _param2;
79 if( bp_moment_scale < 0 )
80 bp_moment_scale = 0.1;
81 bp_moment_scale = MIN( bp_moment_scale, 1 );
88 CvANN_MLP_TrainParams::~CvANN_MLP_TrainParams()
93 CvANN_MLP::CvANN_MLP()
95 layer_sizes = wbuf = 0;
96 min_val = max_val = min_val1 = max_val1 = 0.;
99 default_model_name = "my_nn";
104 CvANN_MLP::CvANN_MLP( const CvMat* _layer_sizes,
106 double _f_param1, double _f_param2 )
108 layer_sizes = wbuf = 0;
109 min_val = max_val = min_val1 = max_val1 = 0.;
112 default_model_name = "my_nn";
113 create( _layer_sizes, _activ_func, _f_param1, _f_param2 );
117 CvANN_MLP::~CvANN_MLP()
123 void CvANN_MLP::clear()
125 cvReleaseMat( &layer_sizes );
126 cvReleaseMat( &wbuf );
128 activ_func = SIGMOID_SYM;
129 f_param1 = f_param2 = 1;
130 max_buf_sz = 1 << 12;
134 void CvANN_MLP::set_activ_func( int _activ_func, double _f_param1, double _f_param2 )
136 CV_FUNCNAME( "CvANN_MLP::set_activ_func" );
140 if( _activ_func < 0 || _activ_func > GAUSSIAN )
141 CV_ERROR( CV_StsOutOfRange, "Unknown activation function" );
143 activ_func = _activ_func;
148 max_val = 0.95; min_val = -max_val;
149 max_val1 = 0.98; min_val1 = -max_val1;
150 if( fabs(_f_param1) < FLT_EPSILON )
152 if( fabs(_f_param2) < FLT_EPSILON )
156 max_val = 1.; min_val = 0.05;
157 max_val1 = 1.; min_val1 = 0.02;
158 if( fabs(_f_param1) < FLT_EPSILON )
160 if( fabs(_f_param2) < FLT_EPSILON )
164 min_val = max_val = min_val1 = max_val1 = 0.;
169 f_param1 = _f_param1;
170 f_param2 = _f_param2;
176 void CvANN_MLP::init_weights()
180 for( i = 1; i < layer_sizes->cols; i++ )
182 int n1 = layer_sizes->data.i[i-1];
183 int n2 = layer_sizes->data.i[i];
184 double val = 0, G = n2 > 2 ? 0.7*pow((double)n1,1./(n2-1)) : 1.;
185 double* w = weights[i];
187 // initialize weights using Nguyen-Widrow algorithm
188 for( j = 0; j < n2; j++ )
191 for( k = 0; k <= n1; k++ )
193 val = rng->uniform(0., 1.)*2-1.;
198 if( i < layer_sizes->cols - 1 )
200 s = 1./(s - fabs(val));
201 for( k = 0; k <= n1; k++ )
203 w[n1*n2 + j] *= G*(-1+j*2./n2);
210 void CvANN_MLP::create( const CvMat* _layer_sizes, int _activ_func,
211 double _f_param1, double _f_param2 )
213 CV_FUNCNAME( "CvANN_MLP::create" );
217 int i, l_step, l_count, buf_sz = 0;
222 if( !CV_IS_MAT(_layer_sizes) ||
223 (_layer_sizes->cols != 1 && _layer_sizes->rows != 1) ||
224 CV_MAT_TYPE(_layer_sizes->type) != CV_32SC1 )
225 CV_ERROR( CV_StsBadArg,
226 "The array of layer neuron counters must be an integer vector" );
228 CV_CALL( set_activ_func( _activ_func, _f_param1, _f_param2 ));
230 l_count = _layer_sizes->rows + _layer_sizes->cols - 1;
231 l_src = _layer_sizes->data.i;
232 l_step = CV_IS_MAT_CONT(_layer_sizes->type) ? 1 :
233 _layer_sizes->step / sizeof(l_src[0]);
234 CV_CALL( layer_sizes = cvCreateMat( 1, l_count, CV_32SC1 ));
235 l_dst = layer_sizes->data.i;
238 for( i = 0; i < l_count; i++ )
240 int n = l_src[i*l_step];
241 if( n < 1 + (0 < i && i < l_count-1))
242 CV_ERROR( CV_StsOutOfRange,
243 "there should be at least one input and one output "
244 "and every hidden layer must have more than 1 neuron" );
246 max_count = MAX( max_count, n );
248 buf_sz += (l_dst[i-1]+1)*n;
251 buf_sz += (l_dst[0] + l_dst[l_count-1]*2)*2;
253 CV_CALL( wbuf = cvCreateMat( 1, buf_sz, CV_64F ));
254 CV_CALL( weights = (double**)cvAlloc( (l_count+2)*sizeof(weights[0]) ));
256 weights[0] = wbuf->data.db;
257 weights[1] = weights[0] + l_dst[0]*2;
258 for( i = 1; i < l_count; i++ )
259 weights[i+1] = weights[i] + (l_dst[i-1] + 1)*l_dst[i];
260 weights[l_count+1] = weights[l_count] + l_dst[l_count-1]*2;
266 float CvANN_MLP::predict( const CvMat* _inputs, CvMat* _outputs ) const
268 int i, j, n, dn = 0, l_count, dn0, buf_sz, min_buf_sz;
271 CV_Error( CV_StsError, "The network has not been initialized" );
273 if( !CV_IS_MAT(_inputs) || !CV_IS_MAT(_outputs) ||
274 !CV_ARE_TYPES_EQ(_inputs,_outputs) ||
275 (CV_MAT_TYPE(_inputs->type) != CV_32FC1 &&
276 CV_MAT_TYPE(_inputs->type) != CV_64FC1) ||
277 _inputs->rows != _outputs->rows )
278 CV_Error( CV_StsBadArg, "Both input and output must be floating-point matrices "
279 "of the same type and have the same number of rows" );
281 if( _inputs->cols != layer_sizes->data.i[0] )
282 CV_Error( CV_StsBadSize, "input matrix must have the same number of columns as "
283 "the number of neurons in the input layer" );
285 if( _outputs->cols != layer_sizes->data.i[layer_sizes->cols - 1] )
286 CV_Error( CV_StsBadSize, "output matrix must have the same number of columns as "
287 "the number of neurons in the output layer" );
288 n = dn0 = _inputs->rows;
289 min_buf_sz = 2*max_count;
290 buf_sz = n*min_buf_sz;
292 if( buf_sz > max_buf_sz )
294 dn0 = max_buf_sz/min_buf_sz;
296 buf_sz = dn0*min_buf_sz;
299 cv::AutoBuffer<double> buf(buf_sz);
300 l_count = layer_sizes->cols;
302 for( i = 0; i < n; i += dn )
304 CvMat hdr[2], _w, *layer_in = &hdr[0], *layer_out = &hdr[1], *temp;
305 dn = MIN( dn0, n - i );
307 cvGetRows( _inputs, layer_in, i, i + dn );
308 cvInitMatHeader( layer_out, dn, layer_in->cols, CV_64F, &buf[0] );
310 scale_input( layer_in, layer_out );
311 CV_SWAP( layer_in, layer_out, temp );
313 for( j = 1; j < l_count; j++ )
315 double* data = buf + (j&1 ? max_count*dn0 : 0);
316 int cols = layer_sizes->data.i[j];
318 cvInitMatHeader( layer_out, dn, cols, CV_64F, data );
319 cvInitMatHeader( &_w, layer_in->cols, layer_out->cols, CV_64F, weights[j] );
320 cvGEMM( layer_in, &_w, 1, 0, 0, layer_out );
321 calc_activ_func( layer_out, _w.data.db + _w.rows*_w.cols );
323 CV_SWAP( layer_in, layer_out, temp );
326 cvGetRows( _outputs, layer_out, i, i + dn );
327 scale_output( layer_in, layer_out );
334 void CvANN_MLP::scale_input( const CvMat* _src, CvMat* _dst ) const
336 int i, j, cols = _src->cols;
337 double* dst = _dst->data.db;
338 const double* w = weights[0];
339 int step = _src->step;
341 if( CV_MAT_TYPE( _src->type ) == CV_32F )
343 const float* src = _src->data.fl;
344 step /= sizeof(src[0]);
346 for( i = 0; i < _src->rows; i++, src += step, dst += cols )
347 for( j = 0; j < cols; j++ )
348 dst[j] = src[j]*w[j*2] + w[j*2+1];
352 const double* src = _src->data.db;
353 step /= sizeof(src[0]);
355 for( i = 0; i < _src->rows; i++, src += step, dst += cols )
356 for( j = 0; j < cols; j++ )
357 dst[j] = src[j]*w[j*2] + w[j*2+1];
362 void CvANN_MLP::scale_output( const CvMat* _src, CvMat* _dst ) const
364 int i, j, cols = _src->cols;
365 const double* src = _src->data.db;
366 const double* w = weights[layer_sizes->cols];
367 int step = _dst->step;
369 if( CV_MAT_TYPE( _dst->type ) == CV_32F )
371 float* dst = _dst->data.fl;
372 step /= sizeof(dst[0]);
374 for( i = 0; i < _src->rows; i++, src += cols, dst += step )
375 for( j = 0; j < cols; j++ )
376 dst[j] = (float)(src[j]*w[j*2] + w[j*2+1]);
380 double* dst = _dst->data.db;
381 step /= sizeof(dst[0]);
383 for( i = 0; i < _src->rows; i++, src += cols, dst += step )
384 for( j = 0; j < cols; j++ )
385 dst[j] = src[j]*w[j*2] + w[j*2+1];
390 void CvANN_MLP::calc_activ_func( CvMat* sums, const double* bias ) const
392 int i, j, n = sums->rows, cols = sums->cols;
393 double* data = sums->data.db;
394 double scale = 0, scale2 = f_param2;
405 scale = -f_param1*f_param1;
411 assert( CV_IS_MAT_CONT(sums->type) );
413 if( activ_func != GAUSSIAN )
415 for( i = 0; i < n; i++, data += cols )
416 for( j = 0; j < cols; j++ )
417 data[j] = (data[j] + bias[j])*scale;
419 if( activ_func == IDENTITY )
424 for( i = 0; i < n; i++, data += cols )
425 for( j = 0; j < cols; j++ )
427 double t = data[j] + bias[j];
440 for( i = 0; i <= n - 4; i += 4 )
442 double x0 = 1.+data[i], x1 = 1.+data[i+1], x2 = 1.+data[i+2], x3 = 1.+data[i+3];
443 double a = x0*x1, b = x2*x3, d = scale2/(a*b), t0, t1;
445 t0 = (2 - x0)*b*x1; t1 = (2 - x1)*b*x0;
446 data[i] = t0; data[i+1] = t1;
447 t0 = (2 - x2)*a*x3; t1 = (2 - x3)*a*x2;
448 data[i+2] = t0; data[i+3] = t1;
453 double t = scale2*(1. - data[i])/(1. + data[i]);
459 for( i = 0; i < n; i++ )
460 data[i] = scale2*data[i];
469 void CvANN_MLP::calc_activ_func_deriv( CvMat* _xf, CvMat* _df,
470 const double* bias ) const
472 int i, j, n = _xf->rows, cols = _xf->cols;
473 double* xf = _xf->data.db;
474 double* df = _df->data.db;
475 double scale, scale2 = f_param2;
476 assert( CV_IS_MAT_CONT( _xf->type & _df->type ) );
478 if( activ_func == IDENTITY )
480 for( i = 0; i < n; i++, xf += cols, df += cols )
481 for( j = 0; j < cols; j++ )
488 else if( activ_func == GAUSSIAN )
490 scale = -f_param1*f_param1;
492 for( i = 0; i < n; i++, xf += cols, df += cols )
493 for( j = 0; j < cols; j++ )
495 double t = xf[j] + bias[j];
504 for( i = 0; i < n; i++ )
510 for( i = 0; i < n; i++, xf += cols, df += cols )
511 for( j = 0; j < cols; j++ )
513 xf[j] = (xf[j] + bias[j])*scale;
514 df[j] = -fabs(xf[j]);
522 // ((1+exp(-ax))^-1)'=a*((1+exp(-ax))^-2)*exp(-ax);
523 // ((1-exp(-ax))/(1+exp(-ax)))'=(a*exp(-ax)*(1+exp(-ax)) + a*exp(-ax)*(1-exp(-ax)))/(1+exp(-ax))^2=
524 // 2*a*exp(-ax)/(1+exp(-ax))^2
526 for( i = 0; i < n; i++ )
528 int s0 = xf[i] > 0 ? 1 : -1;
529 double t0 = 1./(1. + df[i]);
530 double t1 = scale*df[i]*t0*t0;
531 t0 *= scale2*(1. - df[i])*s0;
539 void CvANN_MLP::calc_input_scale( const CvVectors* vecs, int flags )
541 bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
542 bool no_scale = (flags & NO_INPUT_SCALE) != 0;
543 double* scale = weights[0];
544 int count = vecs->count;
548 int i, j, vcount = layer_sizes->data.i[0];
549 int type = vecs->type;
550 double a = no_scale ? 1. : 0.;
552 for( j = 0; j < vcount; j++ )
553 scale[2*j] = a, scale[j*2+1] = 0.;
558 for( i = 0; i < count; i++ )
560 const float* f = vecs->data.fl[i];
561 const double* d = vecs->data.db[i];
562 for( j = 0; j < vcount; j++ )
564 double t = type == CV_32F ? (double)f[j] : d[j];
570 for( j = 0; j < vcount; j++ )
572 double s = scale[j*2], s2 = scale[j*2+1];
573 double m = s/count, sigma2 = s2/count - m*m;
574 scale[j*2] = sigma2 < DBL_EPSILON ? 1 : 1./sqrt(sigma2);
575 scale[j*2+1] = -m*scale[j*2];
581 void CvANN_MLP::calc_output_scale( const CvVectors* vecs, int flags )
583 int i, j, vcount = layer_sizes->data.i[layer_sizes->cols-1];
584 int type = vecs->type;
585 double m = min_val, M = max_val, m1 = min_val1, M1 = max_val1;
586 bool reset_weights = (flags & UPDATE_WEIGHTS) == 0;
587 bool no_scale = (flags & NO_OUTPUT_SCALE) != 0;
588 int l_count = layer_sizes->cols;
589 double* scale = weights[l_count];
590 double* inv_scale = weights[l_count+1];
591 int count = vecs->count;
593 CV_FUNCNAME( "CvANN_MLP::calc_output_scale" );
599 double a0 = no_scale ? 1 : DBL_MAX, b0 = no_scale ? 0 : -DBL_MAX;
601 for( j = 0; j < vcount; j++ )
603 scale[2*j] = inv_scale[2*j] = a0;
604 scale[j*2+1] = inv_scale[2*j+1] = b0;
611 for( i = 0; i < count; i++ )
613 const float* f = vecs->data.fl[i];
614 const double* d = vecs->data.db[i];
616 for( j = 0; j < vcount; j++ )
618 double t = type == CV_32F ? (double)f[j] : d[j];
622 double mj = scale[j*2], Mj = scale[j*2+1];
631 t = t*inv_scale[j*2] + inv_scale[2*j+1];
632 if( t < m1 || t > M1 )
633 CV_ERROR( CV_StsOutOfRange,
634 "Some of new output training vector components run exceed the original range too much" );
640 for( j = 0; j < vcount; j++ )
642 // map mj..Mj to m..M
643 double mj = scale[j*2], Mj = scale[j*2+1];
645 double delta = Mj - mj;
646 if( delta < DBL_EPSILON )
647 a = 1, b = (M + m - Mj - mj)*0.5;
649 a = (M - m)/delta, b = m - mj*a;
650 inv_scale[j*2] = a; inv_scale[j*2+1] = b;
652 scale[j*2] = a; scale[j*2+1] = b;
659 bool CvANN_MLP::prepare_to_train( const CvMat* _inputs, const CvMat* _outputs,
660 const CvMat* _sample_weights, const CvMat* _sample_idx,
661 CvVectors* _ivecs, CvVectors* _ovecs, double** _sw, int _flags )
664 CvMat* sample_idx = 0;
665 CvVectors ivecs, ovecs;
669 CV_FUNCNAME( "CvANN_MLP::prepare_to_train" );
671 ivecs.data.ptr = ovecs.data.ptr = 0;
672 assert( _ivecs && _ovecs );
677 int i, sw_type = 0, sw_count = 0;
682 CV_ERROR( CV_StsError,
683 "The network has not been created. Use method create or the appropriate constructor" );
685 if( !CV_IS_MAT(_inputs) || (CV_MAT_TYPE(_inputs->type) != CV_32FC1 &&
686 CV_MAT_TYPE(_inputs->type) != CV_64FC1) || _inputs->cols != layer_sizes->data.i[0] )
687 CV_ERROR( CV_StsBadArg,
688 "input training data should be a floating-point matrix with"
689 "the number of rows equal to the number of training samples and "
690 "the number of columns equal to the size of 0-th (input) layer" );
692 if( !CV_IS_MAT(_outputs) || (CV_MAT_TYPE(_outputs->type) != CV_32FC1 &&
693 CV_MAT_TYPE(_outputs->type) != CV_64FC1) ||
694 _outputs->cols != layer_sizes->data.i[layer_sizes->cols - 1] )
695 CV_ERROR( CV_StsBadArg,
696 "output training data should be a floating-point matrix with"
697 "the number of rows equal to the number of training samples and "
698 "the number of columns equal to the size of last (output) layer" );
700 if( _inputs->rows != _outputs->rows )
701 CV_ERROR( CV_StsUnmatchedSizes, "The numbers of input and output samples do not match" );
705 CV_CALL( sample_idx = cvPreprocessIndexArray( _sample_idx, _inputs->rows ));
706 sidx = sample_idx->data.i;
707 count = sample_idx->cols + sample_idx->rows - 1;
710 count = _inputs->rows;
712 if( _sample_weights )
714 if( !CV_IS_MAT(_sample_weights) )
715 CV_ERROR( CV_StsBadArg, "sample_weights (if passed) must be a valid matrix" );
717 sw_type = CV_MAT_TYPE(_sample_weights->type);
718 sw_count = _sample_weights->cols + _sample_weights->rows - 1;
720 if( (sw_type != CV_32FC1 && sw_type != CV_64FC1) ||
721 (_sample_weights->cols != 1 && _sample_weights->rows != 1) ||
722 (sw_count != count && sw_count != _inputs->rows) )
723 CV_ERROR( CV_StsBadArg,
724 "sample_weights must be 1d floating-point vector containing weights "
725 "of all or selected training samples" );
727 sw_step = CV_IS_MAT_CONT(_sample_weights->type) ? 1 :
728 _sample_weights->step/CV_ELEM_SIZE(sw_type);
730 CV_CALL( sw = (double*)cvAlloc( count*sizeof(sw[0]) ));
733 CV_CALL( ivecs.data.ptr = (uchar**)cvAlloc( count*sizeof(ivecs.data.ptr[0]) ));
734 CV_CALL( ovecs.data.ptr = (uchar**)cvAlloc( count*sizeof(ovecs.data.ptr[0]) ));
736 ivecs.type = CV_MAT_TYPE(_inputs->type);
737 ovecs.type = CV_MAT_TYPE(_outputs->type);
738 ivecs.count = ovecs.count = count;
740 for( i = 0; i < count; i++ )
742 int idx = sidx ? sidx[i] : i;
743 ivecs.data.ptr[i] = _inputs->data.ptr + idx*_inputs->step;
744 ovecs.data.ptr[i] = _outputs->data.ptr + idx*_outputs->step;
747 int si = sw_count == count ? i : idx;
748 double w = sw_type == CV_32FC1 ?
749 (double)_sample_weights->data.fl[si*sw_step] :
750 _sample_weights->data.db[si*sw_step];
753 CV_ERROR( CV_StsOutOfRange, "some of sample weights are negative" );
761 sw_sum = sw_sum > DBL_EPSILON ? 1./sw_sum : 0;
762 for( i = 0; i < count; i++ )
766 calc_input_scale( &ivecs, _flags );
767 CV_CALL( calc_output_scale( &ovecs, _flags ));
775 cvFree( &ivecs.data.ptr );
776 cvFree( &ovecs.data.ptr );
780 cvReleaseMat( &sample_idx );
789 int CvANN_MLP::train( const CvMat* _inputs, const CvMat* _outputs,
790 const CvMat* _sample_weights, const CvMat* _sample_idx,
791 CvANN_MLP_TrainParams _params, int flags )
793 const int MAX_ITER = 1000;
794 const double DEFAULT_EPSILON = FLT_EPSILON;
800 x0.data.ptr = u.data.ptr = 0;
802 CV_FUNCNAME( "CvANN_MLP::train" );
811 // initialize training data
812 CV_CALL( prepare_to_train( _inputs, _outputs, _sample_weights,
813 _sample_idx, &x0, &u, &sw, flags ));
815 // ... and link weights
816 if( !(flags & UPDATE_WEIGHTS) )
819 max_iter = params.term_crit.type & CV_TERMCRIT_ITER ? params.term_crit.max_iter : MAX_ITER;
820 max_iter = MAX( max_iter, 1 );
822 epsilon = params.term_crit.type & CV_TERMCRIT_EPS ? params.term_crit.epsilon : DEFAULT_EPSILON;
823 epsilon = MAX(epsilon, DBL_EPSILON);
825 params.term_crit.type = CV_TERMCRIT_ITER + CV_TERMCRIT_EPS;
826 params.term_crit.max_iter = max_iter;
827 params.term_crit.epsilon = epsilon;
829 if( params.train_method == CvANN_MLP_TrainParams::BACKPROP )
831 CV_CALL( iter = train_backprop( x0, u, sw ));
835 CV_CALL( iter = train_rprop( x0, u, sw ));
840 cvFree( &x0.data.ptr );
841 cvFree( &u.data.ptr );
848 int CvANN_MLP::train_backprop( CvVectors x0, CvVectors u, const double* sw )
852 double **x = 0, **df = 0;
854 int iter = -1, count = x0.count;
856 CV_FUNCNAME( "CvANN_MLP::train_backprop" );
860 int i, j, k, ivcount, ovcount, l_count, total = 0, max_iter;
862 double prev_E = DBL_MAX*0.5, E = 0, epsilon;
864 max_iter = params.term_crit.max_iter*count;
865 epsilon = params.term_crit.epsilon*count;
867 l_count = layer_sizes->cols;
868 ivcount = layer_sizes->data.i[0];
869 ovcount = layer_sizes->data.i[l_count-1];
872 for( i = 0; i < l_count; i++ )
873 total += layer_sizes->data.i[i] + 1;
875 CV_CALL( dw = cvCreateMat( wbuf->rows, wbuf->cols, wbuf->type ));
877 CV_CALL( buf = cvCreateMat( 1, (total + max_count)*2, CV_64F ));
878 CV_CALL( _idx = cvCreateMat( 1, count, CV_32SC1 ));
879 for( i = 0; i < count; i++ )
882 CV_CALL( x = (double**)cvAlloc( total*2*sizeof(x[0]) ));
884 buf_ptr = buf->data.db;
886 for( j = 0; j < l_count; j++ )
889 df[j] = x[j] + layer_sizes->data.i[j];
890 buf_ptr += (df[j] - x[j])*2;
893 // run back-propagation loop
897 E = 1/2*||u - x_N||^2
898 grad_N = (x_N - u)*f'(y_i)
899 dw_i(t) = momentum*dw_i(t-1) + dw_scale*x_{i-1}*grad_i
900 w_i(t+1) = w_i(t) + dw_i(t)
901 grad_{i-1} = w_i^t*grad_i
903 for( iter = 0; iter < max_iter; iter++ )
905 int idx = iter % count;
906 double* w = weights[0];
907 double sweight = sw ? count*sw[idx] : 1.;
908 CvMat _w, _dw, hdr1, hdr2, ghdr1, ghdr2, _df;
909 CvMat *x1 = &hdr1, *x2 = &hdr2, *grad1 = &ghdr1, *grad2 = &ghdr2, *temp;
913 //printf("%d. E = %g\n", iter/count, E);
914 if( fabs(prev_E - E) < epsilon )
920 for( i = 0; i < count; i++ )
925 CV_SWAP( _idx->data.i[j], _idx->data.i[k], tt );
929 idx = _idx->data.i[idx];
931 if( x0.type == CV_32F )
933 const float* x0data = x0.data.fl[idx];
934 for( j = 0; j < ivcount; j++ )
935 x[0][j] = x0data[j]*w[j*2] + w[j*2 + 1];
939 const double* x0data = x0.data.db[idx];
940 for( j = 0; j < ivcount; j++ )
941 x[0][j] = x0data[j]*w[j*2] + w[j*2 + 1];
944 cvInitMatHeader( x1, 1, ivcount, CV_64F, x[0] );
946 // forward pass, compute y[i]=w*x[i-1], x[i]=f(y[i]), df[i]=f'(y[i])
947 for( i = 1; i < l_count; i++ )
949 cvInitMatHeader( x2, 1, layer_sizes->data.i[i], CV_64F, x[i] );
950 cvInitMatHeader( &_w, x1->cols, x2->cols, CV_64F, weights[i] );
951 cvGEMM( x1, &_w, 1, 0, 0, x2 );
954 calc_activ_func_deriv( x2, &_df, _w.data.db + _w.rows*_w.cols );
955 CV_SWAP( x1, x2, temp );
958 cvInitMatHeader( grad1, 1, ovcount, CV_64F, buf_ptr );
960 grad2->data.db = buf_ptr + max_count;
962 w = weights[l_count+1];
965 if( u.type == CV_32F )
967 const float* udata = u.data.fl[idx];
968 for( k = 0; k < ovcount; k++ )
970 double t = udata[k]*w[k*2] + w[k*2+1] - x[l_count-1][k];
971 grad1->data.db[k] = t*sweight;
977 const double* udata = u.data.db[idx];
978 for( k = 0; k < ovcount; k++ )
980 double t = udata[k]*w[k*2] + w[k*2+1] - x[l_count-1][k];
981 grad1->data.db[k] = t*sweight;
987 // backward pass, update weights
988 for( i = l_count-1; i > 0; i-- )
990 int n1 = layer_sizes->data.i[i-1], n2 = layer_sizes->data.i[i];
991 cvInitMatHeader( &_df, 1, n2, CV_64F, df[i] );
992 cvMul( grad1, &_df, grad1 );
993 cvInitMatHeader( &_w, n1+1, n2, CV_64F, weights[i] );
994 cvInitMatHeader( &_dw, n1+1, n2, CV_64F, dw->data.db + (weights[i] - weights[0]) );
995 cvInitMatHeader( x1, n1+1, 1, CV_64F, x[i-1] );
997 cvGEMM( x1, grad1, params.bp_dw_scale, &_dw, params.bp_moment_scale, &_dw );
998 cvAdd( &_w, &_dw, &_w );
1003 cvGEMM( grad1, &_w, 1, 0, 0, grad2, CV_GEMM_B_T );
1005 CV_SWAP( grad1, grad2, temp );
1013 cvReleaseMat( &dw );
1014 cvReleaseMat( &buf );
1015 cvReleaseMat( &_idx );
1021 struct rprop_loop : cv::ParallelLoopBody {
1022 rprop_loop(const CvANN_MLP* _point, double**& _weights, int& _count, int& _ivcount, CvVectors* _x0,
1023 int& _l_count, CvMat*& _layer_sizes, int& _ovcount, int& _max_count,
1024 CvVectors* _u, const double*& _sw, double& _inv_count, CvMat*& _dEdw, int& _dcount0, double* _E, int _buf_sz)
1032 layer_sizes = _layer_sizes;
1034 max_count = _max_count;
1037 inv_count = _inv_count;
1044 const CvANN_MLP* point;
1062 void operator()( const cv::Range& range ) const
1069 for(int i = 0; i < l_count; i++ )
1070 total += layer_sizes->data.i[i];
1072 buf = cvCreateMat( 1, buf_sz, CV_64F );
1073 x = (double**)cvAlloc( total*2*sizeof(x[0]) );
1075 buf_ptr = buf->data.db;
1076 for(int i = 0; i < l_count; i++ )
1079 df[i] = x[i] + layer_sizes->data.i[i]*dcount0;
1080 buf_ptr += (df[i] - x[i])*2;
1083 for(int si = range.start; si < range.end; si++ )
1085 if (si % dcount0 != 0) continue;
1088 CvMat _w, _dEdw, hdr1, hdr2, ghdr1, ghdr2, _df;
1089 CvMat *x1, *x2, *grad1, *grad2, *temp;
1092 dcount = MIN(count - si , dcount0 );
1094 grad1 = &ghdr1; grad2 = &ghdr2;
1095 x1 = &hdr1; x2 = &hdr2;
1097 // grab and preprocess input data
1098 if( x0->type == CV_32F )
1100 for(int i = 0; i < dcount; i++ )
1102 const float* x0data = x0->data.fl[si+i];
1103 double* xdata = x[0]+i*ivcount;
1104 for(int j = 0; j < ivcount; j++ )
1105 xdata[j] = x0data[j]*w[j*2] + w[j*2+1];
1109 for(int i = 0; i < dcount; i++ )
1111 const double* x0data = x0->data.db[si+i];
1112 double* xdata = x[0]+i*ivcount;
1113 for(int j = 0; j < ivcount; j++ )
1114 xdata[j] = x0data[j]*w[j*2] + w[j*2+1];
1116 cvInitMatHeader( x1, dcount, ivcount, CV_64F, x[0] );
1118 // forward pass, compute y[i]=w*x[i-1], x[i]=f(y[i]), df[i]=f'(y[i])
1119 for(int i = 1; i < l_count; i++ )
1121 cvInitMatHeader( x2, dcount, layer_sizes->data.i[i], CV_64F, x[i] );
1122 cvInitMatHeader( &_w, x1->cols, x2->cols, CV_64F, weights[i] );
1123 cvGEMM( x1, &_w, 1, 0, 0, x2 );
1125 _df.data.db = df[i];
1126 point->calc_activ_func_deriv( x2, &_df, _w.data.db + _w.rows*_w.cols );
1127 CV_SWAP( x1, x2, temp );
1129 cvInitMatHeader( grad1, dcount, ovcount, CV_64F, buf_ptr );
1131 w = weights[l_count+1];
1132 grad2->data.db = buf_ptr + max_count*dcount;
1135 if( u->type == CV_32F )
1136 for(int i = 0; i < dcount; i++ )
1138 const float* udata = u->data.fl[si+i];
1139 const double* xdata = x[l_count-1] + i*ovcount;
1140 double* gdata = grad1->data.db + i*ovcount;
1141 double sweight = sw ? sw[si+i] : inv_count, E1 = 0;
1143 for(int j = 0; j < ovcount; j++ )
1145 double t = udata[j]*w[j*2] + w[j*2+1] - xdata[j];
1146 gdata[j] = t*sweight;
1152 for(int i = 0; i < dcount; i++ )
1154 const double* udata = u->data.db[si+i];
1155 const double* xdata = x[l_count-1] + i*ovcount;
1156 double* gdata = grad1->data.db + i*ovcount;
1157 double sweight = sw ? sw[si+i] : inv_count, E1 = 0;
1159 for(int j = 0; j < ovcount; j++ )
1161 double t = udata[j]*w[j*2] + w[j*2+1] - xdata[j];
1162 gdata[j] = t*sweight;
1168 // backward pass, update dEdw
1169 static cv::Mutex mutex;
1171 for(int i = l_count-1; i > 0; i-- )
1173 n1 = layer_sizes->data.i[i-1]; n2 = layer_sizes->data.i[i];
1174 cvInitMatHeader( &_df, dcount, n2, CV_64F, df[i] );
1175 cvMul( grad1, &_df, grad1 );
1178 cv::AutoLock lock(mutex);
1179 cvInitMatHeader( &_dEdw, n1, n2, CV_64F, dEdw->data.db+(weights[i]-weights[0]) );
1180 cvInitMatHeader( x1, dcount, n1, CV_64F, x[i-1] );
1181 cvGEMM( x1, grad1, 1, &_dEdw, 1, &_dEdw, CV_GEMM_A_T );
1183 // update bias part of dEdw
1184 for( k = 0; k < dcount; k++ )
1186 double* dst = _dEdw.data.db + n1*n2;
1187 const double* src = grad1->data.db + k*n2;
1188 for(int j = 0; j < n2; j++ )
1193 cvInitMatHeader( &_w, n1, n2, CV_64F, weights[i] );
1196 cvInitMatHeader( grad2, dcount, n1, CV_64F, grad2->data.db );
1198 cvGEMM( grad1, &_w, 1, 0, 0, grad2, CV_GEMM_B_T );
1199 CV_SWAP( grad1, grad2, temp );
1203 cvReleaseMat( &buf );
1209 int CvANN_MLP::train_rprop( CvVectors x0, CvVectors u, const double* sw )
1211 const int max_buf_size = 1 << 16;
1214 CvMat* prev_dEdw_sign = 0;
1216 double **x = 0, **df = 0;
1217 int iter = -1, count = x0.count;
1219 CV_FUNCNAME( "CvANN_MLP::train" );
1223 int i, ivcount, ovcount, l_count, total = 0, max_iter, buf_sz, dcount0;
1225 double prev_E = DBL_MAX*0.5, epsilon;
1226 double dw_plus, dw_minus, dw_min, dw_max;
1229 max_iter = params.term_crit.max_iter;
1230 epsilon = params.term_crit.epsilon;
1231 dw_plus = params.rp_dw_plus;
1232 dw_minus = params.rp_dw_minus;
1233 dw_min = params.rp_dw_min;
1234 dw_max = params.rp_dw_max;
1236 l_count = layer_sizes->cols;
1237 ivcount = layer_sizes->data.i[0];
1238 ovcount = layer_sizes->data.i[l_count-1];
1241 for( i = 0; i < l_count; i++ )
1242 total += layer_sizes->data.i[i];
1244 CV_CALL( dw = cvCreateMat( wbuf->rows, wbuf->cols, wbuf->type ));
1245 cvSet( dw, cvScalarAll(params.rp_dw0) );
1246 CV_CALL( dEdw = cvCreateMat( wbuf->rows, wbuf->cols, wbuf->type ));
1248 CV_CALL( prev_dEdw_sign = cvCreateMat( wbuf->rows, wbuf->cols, CV_8SC1 ));
1249 cvZero( prev_dEdw_sign );
1251 inv_count = 1./count;
1252 dcount0 = max_buf_size/(2*total);
1253 dcount0 = MAX( dcount0, 1 );
1254 dcount0 = MIN( dcount0, count );
1255 buf_sz = dcount0*(total + max_count)*2;
1257 CV_CALL( buf = cvCreateMat( 1, buf_sz, CV_64F ));
1259 CV_CALL( x = (double**)cvAlloc( total*2*sizeof(x[0]) ));
1261 buf_ptr = buf->data.db;
1263 for( i = 0; i < l_count; i++ )
1266 df[i] = x[i] + layer_sizes->data.i[i]*dcount0;
1267 buf_ptr += (df[i] - x[i])*2;
1272 y_i(t) = w_i(t)*x_{i-1}(t)
1274 E = sum_over_all_samples(1/2*||u - x_N||^2)
1275 grad_N = (x_N - u)*f'(y_i)
1277 MIN(dw_i{jk}(t)*dw_plus, dw_max), if dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) > 0
1278 dw_i{jk}(t) = MAX(dw_i{jk}(t)*dw_minus, dw_min), if dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) < 0
1281 if (dE/dw_i{jk}(t)*dE/dw_i{jk}(t-1) < 0)
1284 w_i{jk}(t+1) = w_i{jk}(t) + dw_i{jk}(t)
1285 grad_{i-1}(t) = w_i^t(t)*grad_i(t)
1287 for( iter = 0; iter < max_iter; iter++ )
1292 // first, iterate through all the samples and compute dEdw
1293 cv::parallel_for_(cv::Range(0, count),
1294 rprop_loop(this, weights, count, ivcount, &x0, l_count, layer_sizes,
1295 ovcount, max_count, &u, sw, inv_count, dEdw, dcount0, &E, buf_sz)
1298 // now update weights
1299 for( i = 1; i < l_count; i++ )
1301 n1 = layer_sizes->data.i[i-1]; n2 = layer_sizes->data.i[i];
1302 for( k = 0; k <= n1; k++ )
1304 double* wk = weights[i]+k*n2;
1305 size_t delta = wk - weights[0];
1306 double* dwk = dw->data.db + delta;
1307 double* dEdwk = dEdw->data.db + delta;
1308 char* prevEk = (char*)(prev_dEdw_sign->data.ptr + delta);
1310 for( j = 0; j < n2; j++ )
1312 double Eval = dEdwk[j];
1313 double dval = dwk[j];
1314 double wval = wk[j];
1315 int s = CV_SIGN(Eval);
1316 int ss = prevEk[j]*s;
1320 dval = MIN( dval, dw_max );
1322 wk[j] = wval + dval*s;
1327 dval = MAX( dval, dw_min );
1330 wk[j] = wval + dval*s;
1334 prevEk[j] = (char)s;
1335 wk[j] = wval + dval*s;
1342 //printf("%d. E = %g\n", iter, E);
1343 if( fabs(prev_E - E) < epsilon )
1351 cvReleaseMat( &dw );
1352 cvReleaseMat( &dEdw );
1353 cvReleaseMat( &prev_dEdw_sign );
1354 cvReleaseMat( &buf );
1361 void CvANN_MLP::write_params( CvFileStorage* fs ) const
1363 //CV_FUNCNAME( "CvANN_MLP::write_params" );
1367 const char* activ_func_name = activ_func == IDENTITY ? "IDENTITY" :
1368 activ_func == SIGMOID_SYM ? "SIGMOID_SYM" :
1369 activ_func == GAUSSIAN ? "GAUSSIAN" : 0;
1371 if( activ_func_name )
1372 cvWriteString( fs, "activation_function", activ_func_name );
1374 cvWriteInt( fs, "activation_function", activ_func );
1376 if( activ_func != IDENTITY )
1378 cvWriteReal( fs, "f_param1", f_param1 );
1379 cvWriteReal( fs, "f_param2", f_param2 );
1382 cvWriteReal( fs, "min_val", min_val );
1383 cvWriteReal( fs, "max_val", max_val );
1384 cvWriteReal( fs, "min_val1", min_val1 );
1385 cvWriteReal( fs, "max_val1", max_val1 );
1387 cvStartWriteStruct( fs, "training_params", CV_NODE_MAP );
1388 if( params.train_method == CvANN_MLP_TrainParams::BACKPROP )
1390 cvWriteString( fs, "train_method", "BACKPROP" );
1391 cvWriteReal( fs, "dw_scale", params.bp_dw_scale );
1392 cvWriteReal( fs, "moment_scale", params.bp_moment_scale );
1394 else if( params.train_method == CvANN_MLP_TrainParams::RPROP )
1396 cvWriteString( fs, "train_method", "RPROP" );
1397 cvWriteReal( fs, "dw0", params.rp_dw0 );
1398 cvWriteReal( fs, "dw_plus", params.rp_dw_plus );
1399 cvWriteReal( fs, "dw_minus", params.rp_dw_minus );
1400 cvWriteReal( fs, "dw_min", params.rp_dw_min );
1401 cvWriteReal( fs, "dw_max", params.rp_dw_max );
1404 cvStartWriteStruct( fs, "term_criteria", CV_NODE_MAP + CV_NODE_FLOW );
1405 if( params.term_crit.type & CV_TERMCRIT_EPS )
1406 cvWriteReal( fs, "epsilon", params.term_crit.epsilon );
1407 if( params.term_crit.type & CV_TERMCRIT_ITER )
1408 cvWriteInt( fs, "iterations", params.term_crit.max_iter );
1409 cvEndWriteStruct( fs );
1411 cvEndWriteStruct( fs );
1417 void CvANN_MLP::write( CvFileStorage* fs, const char* name ) const
1419 CV_FUNCNAME( "CvANN_MLP::write" );
1423 int i, l_count = layer_sizes->cols;
1426 CV_ERROR( CV_StsError, "The network has not been initialized" );
1428 cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_ML_ANN_MLP );
1430 cvWrite( fs, "layer_sizes", layer_sizes );
1434 cvStartWriteStruct( fs, "input_scale", CV_NODE_SEQ + CV_NODE_FLOW );
1435 cvWriteRawData( fs, weights[0], layer_sizes->data.i[0]*2, "d" );
1436 cvEndWriteStruct( fs );
1438 cvStartWriteStruct( fs, "output_scale", CV_NODE_SEQ + CV_NODE_FLOW );
1439 cvWriteRawData( fs, weights[l_count], layer_sizes->data.i[l_count-1]*2, "d" );
1440 cvEndWriteStruct( fs );
1442 cvStartWriteStruct( fs, "inv_output_scale", CV_NODE_SEQ + CV_NODE_FLOW );
1443 cvWriteRawData( fs, weights[l_count+1], layer_sizes->data.i[l_count-1]*2, "d" );
1444 cvEndWriteStruct( fs );
1446 cvStartWriteStruct( fs, "weights", CV_NODE_SEQ );
1447 for( i = 1; i < l_count; i++ )
1449 cvStartWriteStruct( fs, 0, CV_NODE_SEQ + CV_NODE_FLOW );
1450 cvWriteRawData( fs, weights[i], (layer_sizes->data.i[i-1]+1)*layer_sizes->data.i[i], "d" );
1451 cvEndWriteStruct( fs );
1454 cvEndWriteStruct( fs );
1460 void CvANN_MLP::read_params( CvFileStorage* fs, CvFileNode* node )
1462 //CV_FUNCNAME( "CvANN_MLP::read_params" );
1466 const char* activ_func_name = cvReadStringByName( fs, node, "activation_function", 0 );
1467 CvFileNode* tparams_node;
1469 if( activ_func_name )
1470 activ_func = strcmp( activ_func_name, "SIGMOID_SYM" ) == 0 ? SIGMOID_SYM :
1471 strcmp( activ_func_name, "IDENTITY" ) == 0 ? IDENTITY :
1472 strcmp( activ_func_name, "GAUSSIAN" ) == 0 ? GAUSSIAN : 0;
1474 activ_func = cvReadIntByName( fs, node, "activation_function" );
1476 f_param1 = cvReadRealByName( fs, node, "f_param1", 0 );
1477 f_param2 = cvReadRealByName( fs, node, "f_param2", 0 );
1479 set_activ_func( activ_func, f_param1, f_param2 );
1481 min_val = cvReadRealByName( fs, node, "min_val", 0. );
1482 max_val = cvReadRealByName( fs, node, "max_val", 1. );
1483 min_val1 = cvReadRealByName( fs, node, "min_val1", 0. );
1484 max_val1 = cvReadRealByName( fs, node, "max_val1", 1. );
1486 tparams_node = cvGetFileNodeByName( fs, node, "training_params" );
1487 params = CvANN_MLP_TrainParams();
1491 const char* tmethod_name = cvReadStringByName( fs, tparams_node, "train_method", "" );
1492 CvFileNode* tcrit_node;
1494 if( strcmp( tmethod_name, "BACKPROP" ) == 0 )
1496 params.train_method = CvANN_MLP_TrainParams::BACKPROP;
1497 params.bp_dw_scale = cvReadRealByName( fs, tparams_node, "dw_scale", 0 );
1498 params.bp_moment_scale = cvReadRealByName( fs, tparams_node, "moment_scale", 0 );
1500 else if( strcmp( tmethod_name, "RPROP" ) == 0 )
1502 params.train_method = CvANN_MLP_TrainParams::RPROP;
1503 params.rp_dw0 = cvReadRealByName( fs, tparams_node, "dw0", 0 );
1504 params.rp_dw_plus = cvReadRealByName( fs, tparams_node, "dw_plus", 0 );
1505 params.rp_dw_minus = cvReadRealByName( fs, tparams_node, "dw_minus", 0 );
1506 params.rp_dw_min = cvReadRealByName( fs, tparams_node, "dw_min", 0 );
1507 params.rp_dw_max = cvReadRealByName( fs, tparams_node, "dw_max", 0 );
1510 tcrit_node = cvGetFileNodeByName( fs, tparams_node, "term_criteria" );
1513 params.term_crit.epsilon = cvReadRealByName( fs, tcrit_node, "epsilon", -1 );
1514 params.term_crit.max_iter = cvReadIntByName( fs, tcrit_node, "iterations", -1 );
1515 params.term_crit.type = (params.term_crit.epsilon >= 0 ? CV_TERMCRIT_EPS : 0) +
1516 (params.term_crit.max_iter >= 0 ? CV_TERMCRIT_ITER : 0);
1524 void CvANN_MLP::read( CvFileStorage* fs, CvFileNode* node )
1526 CvMat* _layer_sizes = 0;
1528 CV_FUNCNAME( "CvANN_MLP::read" );
1536 _layer_sizes = (CvMat*)cvReadByName( fs, node, "layer_sizes" );
1537 CV_CALL( create( _layer_sizes, SIGMOID_SYM, 0, 0 ));
1539 cvReleaseMat( &_layer_sizes );
1540 _layer_sizes = NULL;
1542 l_count = layer_sizes->cols;
1544 CV_CALL( read_params( fs, node ));
1546 w = cvGetFileNodeByName( fs, node, "input_scale" );
1547 if( !w || CV_NODE_TYPE(w->tag) != CV_NODE_SEQ ||
1548 w->data.seq->total != layer_sizes->data.i[0]*2 )
1549 CV_ERROR( CV_StsParseError, "input_scale tag is not found or is invalid" );
1551 CV_CALL( cvReadRawData( fs, w, weights[0], "d" ));
1553 w = cvGetFileNodeByName( fs, node, "output_scale" );
1554 if( !w || CV_NODE_TYPE(w->tag) != CV_NODE_SEQ ||
1555 w->data.seq->total != layer_sizes->data.i[l_count-1]*2 )
1556 CV_ERROR( CV_StsParseError, "output_scale tag is not found or is invalid" );
1558 CV_CALL( cvReadRawData( fs, w, weights[l_count], "d" ));
1560 w = cvGetFileNodeByName( fs, node, "inv_output_scale" );
1561 if( !w || CV_NODE_TYPE(w->tag) != CV_NODE_SEQ ||
1562 w->data.seq->total != layer_sizes->data.i[l_count-1]*2 )
1563 CV_ERROR( CV_StsParseError, "inv_output_scale tag is not found or is invalid" );
1565 CV_CALL( cvReadRawData( fs, w, weights[l_count+1], "d" ));
1567 w = cvGetFileNodeByName( fs, node, "weights" );
1568 if( !w || CV_NODE_TYPE(w->tag) != CV_NODE_SEQ ||
1569 w->data.seq->total != l_count - 1 )
1570 CV_ERROR( CV_StsParseError, "weights tag is not found or is invalid" );
1572 cvStartReadSeq( w->data.seq, &reader );
1574 for( i = 1; i < l_count; i++ )
1576 w = (CvFileNode*)reader.ptr;
1577 CV_CALL( cvReadRawData( fs, w, weights[i], "d" ));
1578 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
1586 CvANN_MLP::CvANN_MLP( const Mat& _layer_sizes, int _activ_func,
1587 double _f_param1, double _f_param2 )
1589 layer_sizes = wbuf = 0;
1590 min_val = max_val = min_val1 = max_val1 = 0.;
1592 rng = &cv::theRNG();
1593 default_model_name = "my_nn";
1594 create( _layer_sizes, _activ_func, _f_param1, _f_param2 );
1597 void CvANN_MLP::create( const Mat& _layer_sizes, int _activ_func,
1598 double _f_param1, double _f_param2 )
1600 CvMat cvlayer_sizes = _layer_sizes;
1601 create( &cvlayer_sizes, _activ_func, _f_param1, _f_param2 );
1604 int CvANN_MLP::train( const Mat& _inputs, const Mat& _outputs,
1605 const Mat& _sample_weights, const Mat& _sample_idx,
1606 CvANN_MLP_TrainParams _params, int flags )
1608 CvMat inputs = _inputs, outputs = _outputs, sweights = _sample_weights, sidx = _sample_idx;
1609 return train(&inputs, &outputs, sweights.data.ptr ? &sweights : 0,
1610 sidx.data.ptr ? &sidx : 0, _params, flags);
1613 float CvANN_MLP::predict( const Mat& _inputs, Mat& _outputs ) const
1615 CV_Assert(layer_sizes != 0);
1616 _outputs.create(_inputs.rows, layer_sizes->data.i[layer_sizes->cols-1], _inputs.type());
1617 CvMat inputs = _inputs, outputs = _outputs;
1619 return predict(&inputs, &outputs);