machine_learning.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 
42 #ifndef __INCLUDE_MACHINE_LEARNING__
43 #define __INCLUDE_MACHINE_LEARNING__
44 
45 
46 #ifndef __INCLUDE_MIST_H__
47  #include "mist.h"
48 #endif
49 
50 #ifndef __INCLUDE_MIST_RANDOM__
51  #include "random.h"
52 #endif
53 
54 
55 #include <ctime>
56 #include <vector>
57 #include <map>
58 #include <algorithm>
59 
60 #ifdef _OPENMP
61  #include <omp.h>
62 #endif
63 
64 
65 // mist名前空間の始まり
67 
68 
69 #define __ASYMMETRIC_WEIGHTING__ 0
70 #define __ONE_PER_CLASS_CODE_WORD__ 0
71 #define __RANDOM_CODE_WORD__ 0
72 #define __DEBUG_OUTPUT_LEVEL__ 0
73 #define __NUMBER_OF_INNER_LOOPS__ 10
74 
75 
77 namespace machine_learning
78 {
79  typedef double feature_value_type;
80  typedef double feature_weight_type;
81 
83  struct feature_one
84  {
85  typedef size_t size_type;
86  typedef ptrdiff_t difference_type;
87 
89  bool category;
91 
93  feature_one( ) : value( 0.0 ), category( true ), weight( 0.0 )
94  {
95  }
96 
103  feature_one( feature_value_type val, bool cate, feature_weight_type wei ) : value( val ), category( cate ), weight( wei )
104  {
105  }
106 
108  feature_one( const feature_one &f ): value( f.value ), category( f.category ), weight( f.weight )
109  {
110  }
111 
113  feature_one &operator =( const feature_one &f )
114  {
115  if( &f != this )
116  {
117  value = f.value;
118  category = f.category;
119  weight = f.weight;
120  }
121 
122  return( *this );
123  }
124 
126  bool operator <( const feature_one &f ) const
127  {
128  return( value < f.value );
129  }
130  };
131 
133  struct feature : public std::vector< feature_value_type >
134  {
135  typedef std::vector< feature_value_type > base;
136  typedef base::value_type value_type;
137  typedef base::size_type size_type;
138  typedef base::difference_type difference_type;
139 
140  std::string category;
142  bool valid;
143 
145  feature( ) : base( ), category( "unknown" ), weight( 0.0 ), valid( true )
146  {
147  }
148 
153  feature( size_type dimension ) : base( dimension ), category( "unknown" ), weight( 0.0 ), valid( true )
154  {
155  }
156 
161  feature( const std::string &cate ) : base( ), category( cate ), weight( 0.0 ), valid( true )
162  {
163  }
164 
170  feature( size_type dimension, const std::string &cate ) : base( dimension, 0.0 ), category( cate ), weight( 0.0 ), valid( true )
171  {
172  }
173 
175  feature( const feature &f ): base( f ), category( f.category ), weight( f.weight ), valid( f.valid )
176  {
177  }
178 
180  feature &operator =( const feature &f )
181  {
182  if( &f != this )
183  {
184  base::operator =( f );
185  category = f.category;
186  weight = f.weight;
187  valid = f.valid;
188  }
189 
190  return( *this );
191  }
192  };
193 
195  template < class KEY, class VALUE >
196  struct pair
197  {
198  KEY key;
199  VALUE value;
200 
202  pair( ){ }
203 
205  pair( const KEY &k, const VALUE &val ) : key( k ), value( val ){ }
206 
208  bool operator <( const pair &f ) const
209  {
210  return( key < f.key );
211  }
212 
214  static bool greater( const pair &f1, const pair &f2 )
215  {
216  return( f2 < f1 );
217  }
218  };
219 
220 
228 
230  namespace adaboost
231  {
232  inline size_t __power_of_two__( size_t x )
233  {
234  size_t val = 1;
235  for( size_t i = 0 ; i < x ; i++ )
236  {
237  val *= 2;
238  }
239  return( val );
240  }
241 
244  {
245  public:
246  typedef feature feature_type;
250 
251  private:
252  double sign_;
253  double threshold_;
254  size_type index_;
255 
256  public:
258  threshold_classifier( ) : sign_( 1.0 ), threshold_( 0.0 ), index_( 0 )
259  {
260  }
261 
263  threshold_classifier( const threshold_classifier& w ) : sign_( w.sign_ ), threshold_( w.threshold_ ), index_( w.index_ )
264  {
265  }
266 
268  threshold_classifier& operator =( const threshold_classifier& other )
269  {
270  if( this != &other )
271  {
272  sign_ = other.sign_;
273  threshold_ = other.threshold_;
274  index_ = other.index_;
275  }
276 
277  return( *this );
278  }
279 
280  public:
286  template < template < typename, typename > class FEATURE_LIST, template < typename, typename > class CATEGORY_LIST, class Allocator1, class Allocator2 >
287  bool learn( const FEATURE_LIST< feature_type, Allocator1 > & features, const CATEGORY_LIST< bool, Allocator2 > &categories )
288  {
289  if( features.empty( ) )
290  {
291  return( false );
292  }
293 
294  double _minimum_classification_error_ = 1.0e100;
295 
296  // Positive と Negative それぞれの重みの合計を計算する
297  double overall_sum_of_positive_weights = 0.0;
298  double overall_sum_of_negative_weights = 0.0;
299  for( size_type i = 0 ; i < features.size( ) ; i++ )
300  {
301  const feature_type &f = features[ i ];
302  if( categories[ i ] )
303  {
304  overall_sum_of_positive_weights += f.weight;
305  }
306  else
307  {
308  overall_sum_of_negative_weights += f.weight;
309  }
310  }
311 
312  if( overall_sum_of_positive_weights == 0.0 || overall_sum_of_negative_weights == 0.0 )
313  {
314  return( false );
315  }
316 
317  double max_sigma = -1.0;
318  int nfeatures = static_cast< int >( features[ 0 ].size( ) );
319 
320  // 特徴量のリストを作成する
321  #pragma omp parallel for firstprivate( nfeatures ) schedule( guided )
322  for( int index = 0 ; index < nfeatures ; index++ )
323  {
324  std::vector< feature_one > flist;
325  flist.reserve( features.size( ) );
326  for( size_type i = 0 ; i < features.size( ) ; i++ )
327  {
328  const feature_type &f = features[ i ];
329  if( f.valid )
330  {
331  flist.push_back( feature_one( f[ index ], categories[ i ], f.weight ) );
332  }
333  }
334 
335  // 特徴量をソートする
336  std::sort( flist.begin( ), flist.end( ) );
337 
338  // 各しきい値での重み付き誤差を計算し,誤差最小のしきい値を求める
339  double min_error = 1.0e100, sgn = 1.0, th = 0.0;
340  double sum_of_positive_weights = 0.0;
341  double sum_of_negative_weights = 0.0;
342 
343  for( size_type i = 0 ; i < flist.size( ) ; i++ )
344  {
345  const feature_one &f = flist[ i ];
346  if( f.category )
347  {
348  sum_of_positive_weights += f.weight;
349  }
350  else
351  {
352  sum_of_negative_weights += f.weight;
353  }
354 
355  double e1 = sum_of_positive_weights + overall_sum_of_negative_weights - sum_of_negative_weights;
356  double e2 = sum_of_negative_weights + overall_sum_of_positive_weights - sum_of_positive_weights;
357  double error = e1 < e2 ? e1 : e2;
358 
359  if( error <= min_error )
360  {
361  min_error = error;
362  th = f.value;
363  sgn = e1 < e2 ? -1.0 : 1.0;
364 
365  if( 0 < i && i < flist.size( ) - 2 )
366  {
367  double v1 = std::abs( flist[ i - 1 ].value - flist[ i + 0 ].value );
368  double v2 = std::abs( flist[ i + 1 ].value - flist[ i + 2 ].value );
369  if( std::abs( v1 + v2 ) > 0 )
370  {
371  double t1 = flist[ i + 0 ].value;
372  double t2 = flist[ i + 1 ].value;
373  th = ( t1 * v1 + t2 * v2 ) / ( v1 + v2 );
374  }
375  }
376  else if( i < flist.size( ) - 1 )
377  {
378  th = ( th + flist[ i + 1 ].value ) * 0.5;
379  }
380  }
381  }
382 
383  double e = 0.0;
384  for( size_t i = 0 ; i < features.size( ) ; i++ )
385  {
386  const feature_type &f = features[ i ];
387  if( f.valid )
388  {
389  if( evaluate( f, index, sgn, th ) != categories[ i ] )
390  {
391  e += f.weight;
392  }
393  }
394  }
395 
396  double sigma = 0.0;
397  {
398  double M1 = 0.0;
399  double M2 = 0.0;
400  double S1 = 0.0;
401  double S2 = 0.0;
402 
403  for( size_type i = 0 ; i < flist.size( ) ; i++ )
404  {
405  const feature_type &f = features[ i ];
406  if( categories[ i ] )
407  {
408  M1 += f.weight * f[ index ];
409  }
410  else
411  {
412  M2 += f.weight * f[ index ];
413  }
414  }
415 
416  M1 /= overall_sum_of_positive_weights;
417  M2 /= overall_sum_of_negative_weights;
418 
419  for( size_type i = 0 ; i < features.size( ) ; i++ )
420  {
421  const feature_type &f = features[ i ];
422  if( categories[ i ] )
423  {
424  S1 += f.weight * ( f[ index ] - M1 ) * ( f[ index ] - M1 );
425  }
426  else
427  {
428  S2 += f.weight * ( f[ index ] - M2 ) * ( f[ index ] - M2 );
429  }
430  }
431 
432  S1 /= overall_sum_of_positive_weights;
433  S2 /= overall_sum_of_negative_weights;
434  double V1 = overall_sum_of_positive_weights * overall_sum_of_negative_weights * ( M1 - M2 ) * ( M1 - M2 );
435  double V2 = ( overall_sum_of_positive_weights + overall_sum_of_negative_weights ) * ( overall_sum_of_positive_weights * S1 + overall_sum_of_negative_weights * S2 );
436  sigma = V1 / ( 1.0 + V2 );
437  }
438 
439  #pragma omp critical
440  {
441  if( _minimum_classification_error_ > e )
442  {
443  _minimum_classification_error_ = e;
444  index_ = index;
445  sign_ = sgn;
446  threshold_ = th;
447  max_sigma = sigma;
448  }
449  else if( _minimum_classification_error_ == e && sigma > max_sigma )
450  {
451  _minimum_classification_error_ = e;
452  index_ = index;
453  sign_ = sgn;
454  threshold_ = th;
455  max_sigma = sigma;
456  }
457  }
458  }
459 
460  return( true );
461  }
462 
463  public:
468  template < class FEATURE >
469  bool operator ()( const FEATURE &f ) const
470  {
471  return( evaluate( f ) );
472  }
473 
478  template < class FEATURE >
479  bool evaluate( const FEATURE &f ) const
480  {
481  return( evaluate( f, index_, sign_, threshold_ ) );
482  }
483 
485  template < class FEATURE >
486  bool evaluate( const FEATURE &f, size_type indx, double sgn, double th ) const
487  {
488  return( sgn * f[ indx ] <= sgn * th );
489  }
490 
492  const std::string serialize( ) const
493  {
494  char buff[ 1024 ];
495  sprintf( buff, "%ld,%f,%f", index_, sign_, threshold_ );
496  return( buff );
497  }
498 
500  void deserialize( const std::string &data )
501  {
502  sscanf( data.c_str( ), "%ld,%lf,%lf", &index_, &sign_, &threshold_ );
503  }
504  };
505 
508  {
509  public:
510  typedef feature feature_type;
514 
515  private:
516  double ave_[ 2 ];
517  double sig_[ 2 ];
518  size_type index_;
519 
520  public:
522  mahalanobis_classifier( ) : index_( 0 )
523  {
524  ave_[ 0 ] = ave_[ 1 ] = 0.0;
525  sig_[ 0 ] = sig_[ 1 ] = 1.0;
526  }
527 
529  mahalanobis_classifier( const mahalanobis_classifier& w ) : index_( w.index_ )
530  {
531  memcpy( ave_, w.ave_, sizeof( double ) * 2 );
532  memcpy( sig_, w.sig_, sizeof( double ) * 2 );
533  }
534 
536  mahalanobis_classifier& operator =( const mahalanobis_classifier& other )
537  {
538  if( this != &other )
539  {
540  memcpy( ave_, other.ave_, sizeof( double ) * 2 );
541  memcpy( sig_, other.sig_, sizeof( double ) * 2 );
542  index_ = other.index_;
543  }
544 
545  return( *this );
546  }
547 
548  public:
554  template < template < typename, typename > class FEATURE_LIST, template < typename, typename > class CATEGORY_LIST, class Allocator1, class Allocator2 >
555  bool learn( const FEATURE_LIST< feature_type, Allocator1 > & features, const CATEGORY_LIST< bool, Allocator2 > &categories )
556  {
557  if( features.empty( ) )
558  {
559  return( false );
560  }
561 
562  double _minimum_classification_error_ = 1.0e100;
563 
564  // Positive と Negative それぞれの重みの合計を計算する
565  double overall_sum_of_positive_weights = 0.0;
566  double overall_sum_of_negative_weights = 0.0;
567  for( size_type i = 0 ; i < features.size( ) ; i++ )
568  {
569  const feature_type &f = features[ i ];
570  if( categories[ i ] )
571  {
572  overall_sum_of_positive_weights += f.weight;
573  }
574  else
575  {
576  overall_sum_of_negative_weights += f.weight;
577  }
578  }
579 
580  double max_sigma = -1.0;
581  int nfeatures = static_cast< int >( features[ 0 ].size( ) );
582 
583  // 特徴量のリストを作成する
584  #pragma omp parallel for firstprivate( nfeatures ) schedule( guided )
585  for( int index = 0 ; index < nfeatures ; index++ )
586  {
587  double ave[ 2 ] = { 0.0, 0.0 };
588  double sig[ 2 ] = { 0.0, 0.0 };
589 
590  for( size_type i = 0 ; i < features.size( ) ; i++ )
591  {
592  const feature_type &f = features[ i ];
593  if( categories[ i ] )
594  {
595  ave[ 0 ] += f.weight * f[ index ];
596  }
597  else
598  {
599  ave[ 1 ] += f.weight * f[ index ];
600  }
601  }
602 
603  ave[ 0 ] /= overall_sum_of_positive_weights;
604  ave[ 1 ] /= overall_sum_of_negative_weights;
605 
606  for( size_type i = 0 ; i < features.size( ) ; i++ )
607  {
608  const feature_type &f = features[ i ];
609  if( categories[ i ] )
610  {
611  sig[ 0 ] += f.weight * ( f[ index ] - ave[ 0 ] ) * ( f[ index ] - ave[ 0 ] );
612  }
613  else
614  {
615  sig[ 1 ] += f.weight * ( f[ index ] - ave[ 1 ] ) * ( f[ index ] - ave[ 1 ] );
616  }
617  }
618 
619  sig[ 0 ] /= overall_sum_of_positive_weights;
620  sig[ 1 ] /= overall_sum_of_negative_weights;
621 
622  double e = 0.0;
623  for( size_t i = 0 ; i < features.size( ) ; i++ )
624  {
625  const feature_type &f = features[ i ];
626  if( f.valid )
627  {
628  if( evaluate( f, index, ave, sig ) != categories[ i ] )
629  {
630  e += f.weight;
631  }
632  }
633  }
634 
635  double sigma = 0.0;
636  {
637  double V1 = overall_sum_of_positive_weights * overall_sum_of_negative_weights * ( ave[ 0 ] - ave[ 1 ] ) * ( ave[ 0 ] - ave[ 1 ] );
638  double V2 = ( overall_sum_of_positive_weights + overall_sum_of_negative_weights ) * ( overall_sum_of_positive_weights * sig[ 0 ] + overall_sum_of_negative_weights * sig[ 1 ] );
639  sigma = V1 / V2;
640  }
641 
642  #pragma omp critical
643  {
644  if( _minimum_classification_error_ >= e && sigma > max_sigma )
645  {
646  _minimum_classification_error_ = e;
647  index_ = index;
648  memcpy( ave_, ave, sizeof( double ) * 2 );
649  memcpy( sig_, sig, sizeof( double ) * 2 );
650  }
651  }
652  }
653 
654  return( true );
655  }
656 
657  public:
662  template < class FEATURE >
663  bool operator ()( const FEATURE &f ) const
664  {
665  return( evaluate( f ) );
666  }
667 
672  template < class FEATURE >
673  bool evaluate( const FEATURE &f ) const
674  {
675  return( evaluate( f, index_, ave_, sig_ ) );
676  }
677 
679  template < class FEATURE >
680  bool evaluate( const FEATURE &f, size_type indx, const double ave[ 2 ], const double sig[ 2 ] ) const
681  {
682  double v0 = f[ indx ] - ave[ 0 ];
683  double v1 = f[ indx ] - ave[ 1 ];
684  return( v0 * v0 * sig[ 1 ] <= v1 * v1 * sig[ 0 ] );
685  }
686 
688  const std::string serialize( ) const
689  {
690  char buff[ 1024 ];
691  sprintf( buff, "%ld,%f,%f,%f,%f", index_, ave_[ 0 ], ave_[ 1 ], sig_[ 0 ], sig_[ 1 ] );
692  return( buff );
693  }
694 
696  void deserialize( const std::string &data )
697  {
698  sscanf( data.c_str( ), "%ld,%lf,%lf,%lf,%lf", &index_, &ave_[ 0 ], &ave_[ 1 ], &sig_[ 0 ], &sig_[ 1 ] );
699  }
700  };
701 
704  {
705  public:
706  typedef feature feature_type;
710 
711  _MIST_CONST( size_type, __number_of_bins__, 100 );
712 
713  private:
714  double hist1_[ __number_of_bins__ ];
715  double hist2_[ __number_of_bins__ ];
716  double min_;
717  double max_;
718  size_type index_;
719 
720  public:
722  confidence_rating_classifier( ) : min_( 0 ), max_( 0 ), index_( 0 )
723  {
724  memset( hist1_, 0, sizeof( double ) * __number_of_bins__ );
725  memset( hist2_, 0, sizeof( double ) * __number_of_bins__ );
726  }
727 
729  confidence_rating_classifier( const confidence_rating_classifier& w ) : min_( w.min_ ), max_( w.max_ ), index_( w.index_ )
730  {
731  memcpy( hist1_, w.hist1_, sizeof( double ) * __number_of_bins__ );
732  memcpy( hist2_, w.hist2_, sizeof( double ) * __number_of_bins__ );
733  }
734 
737  {
738  if( this != &other )
739  {
740  memcpy( hist1_, other.hist1_, sizeof( double ) * __number_of_bins__ );
741  memcpy( hist2_, other.hist2_, sizeof( double ) * __number_of_bins__ );
742  index_ = other.index_;
743  min_ = other.min_;
744  max_ = other.max_;
745  }
746 
747  return( *this );
748  }
749 
750  public:
756  template < template < typename, typename > class FEATURE_LIST, template < typename, typename > class CATEGORY_LIST, class Allocator1, class Allocator2 >
757  bool learn( const FEATURE_LIST< feature_type, Allocator1 > & features, const CATEGORY_LIST< bool, Allocator2 > &categories )
758  {
759  if( features.empty( ) )
760  {
761  return( false );
762  }
763 
764  double _minimum_classification_error_ = 1.0e100;
765  int nfeatures = static_cast< int >( features[ 0 ].size( ) );
766 
767  // 特徴量のリストを作成する
768  #pragma omp parallel for firstprivate( nfeatures ) schedule( guided )
769  for( int index = 0 ; index < nfeatures ; index++ )
770  {
771  double min = features[ 0 ][ index ];
772  double max = min;
773 
774  for( size_type i = 0 ; i < features.size( ) ; i++ )
775  {
776  const feature_type &f = features[ i ];
777  if( min > f[ index ] )
778  {
779  min = f[ index ];
780  }
781  else if( max < f[ index ] )
782  {
783  max = f[ index ];
784  }
785  }
786 
787  double hist1[ __number_of_bins__ ];
788  double hist2[ __number_of_bins__ ];
789  for( size_type i = 0 ; i < __number_of_bins__ ; i++ )
790  {
791  hist1[ i ] = hist2[ i ] = 0.0;
792  }
793 
794  for( size_type i = 0 ; i < features.size( ) ; i++ )
795  {
796  const feature_type &f = features[ i ];
797  int bin = ( int )( ( f[ index ] - min ) * __number_of_bins__ / ( max - min + 1 ) + 0.5 );
798  if( bin < 0 )
799  {
800  bin = 0;
801  }
802  else if( bin >= __number_of_bins__ )
803  {
804  bin = __number_of_bins__ - 1;
805  }
806 
807  if( categories[ i ] )
808  {
809  hist1[ bin ] += f.weight;
810  }
811  else
812  {
813  hist2[ bin ] += f.weight;
814  }
815  }
816 
817  double e = 0.0;
818  for( size_t i = 0 ; i < features.size( ) ; i++ )
819  {
820  const feature_type &f = features[ i ];
821  if( f.valid )
822  {
823  if( evaluate( f, index, hist1, hist2, min, max ) != categories[ i ] )
824  {
825  e += f.weight;
826  }
827  }
828  }
829 
830  #pragma omp critical
831  {
832  if( _minimum_classification_error_ >= e )
833  {
834  _minimum_classification_error_ = e;
835  index_ = index;
836  min_ = min;
837  max_ = max;
838  memcpy( hist1_, hist1, sizeof( double ) * __number_of_bins__ );
839  memcpy( hist2_, hist2, sizeof( double ) * __number_of_bins__ );
840  }
841  }
842  }
843 
844  return( true );
845  }
846 
847  public:
852  template < class FEATURE >
853  bool operator ()( const FEATURE &f ) const
854  {
855  return( evaluate( f ) );
856  }
857 
862  template < class FEATURE >
863  bool evaluate( const FEATURE &f ) const
864  {
865  return( evaluate( f, index_, hist1_, hist2_, min_, max_ ) );
866  }
867 
869  template < class FEATURE >
870  bool evaluate( const FEATURE &f, size_type indx, const double hist1[ ], const double hist2[ ], double min, double max ) const
871  {
872  int bin = ( int )( ( f[ indx ] - min ) * __number_of_bins__ / ( max - min + 1 ) + 0.5 );
873  if( bin < 0 )
874  {
875  bin = 0;
876  }
877  else if( bin >= __number_of_bins__ )
878  {
879  bin = __number_of_bins__ - 1;
880  }
881  return( hist1[ bin ] <= hist2[ bin ] );
882  }
883 
885  const std::string serialize( ) const
886  {
887  //char buff[ 1024 ];
888  //sprintf( buff, "%d,%f,%f,%f,%f", index_, ave_[ 0 ], ave_[ 1 ], sig_[ 0 ], sig_[ 1 ] );
889  //return( buff );
890  return( "" );
891  }
892 
894  void deserialize( const std::string & /* data */ )
895  {
896  //sscanf( data.c_str( ), "%d,%lf,%lf,%lf,%lf", &index_, &ave_[ 0 ], &ave_[ 1 ], &sig_[ 0 ], &sig_[ 1 ] );
897  }
898  };
899 
901  template < typename __WEAK_CLASSIFIER__ = threshold_classifier >
903  {
904  public:
905  typedef __WEAK_CLASSIFIER__ weak_classifier_type;
910 
911  private:
912  std::vector< std::string > categories_;
913  std::vector< weak_classifier_type > weak_classifiers_;
914  std::vector< std::vector< bool > > code_word_;
915  std::vector< double > alpha_;
916  std::vector< double > beta_;
917 
918  public:
921  {
922  }
923 
925  classifier( const classifier &cls ) : categories_( cls.categories_ ), weak_classifiers_( cls.weak_classifiers_ ), code_word_( cls.code_word_ ), alpha_( cls.alpha_ ), beta_( cls.beta_ )
926  {
927  }
928 
930  classifier& operator =( const classifier& other )
931  {
932  if( this != &other )
933  {
934  categories_ = other.categories_;
935  weak_classifiers_ = other.weak_classifiers_;
936  code_word_ = other.code_word_;
937  alpha_ = other.alpha_;
938  beta_ = other.beta_;
939  }
940 
941  return( *this );
942  }
943 
944  public:
946  const std::vector< weak_classifier_type > &weak_classifiers( ) const
947  {
948  return( weak_classifiers_ );
949  }
950 
952  std::vector< weak_classifier_type > &weak_classifiers( )
953  {
954  return( weak_classifiers_ );
955  }
956 
958  const std::vector< std::string > &categories( ) const
959  {
960  return( categories_ );
961  }
962 
964  std::vector< std::string > &categories( )
965  {
966  return( categories_ );
967  }
968 
970  const std::vector< std::vector< bool > > &code_word( ) const
971  {
972  return( code_word_ );
973  }
974 
976  std::vector< std::vector< bool > > &code_word( )
977  {
978  return( code_word_ );
979  }
980 
982  const std::vector< double > &alpha( ) const
983  {
984  return( alpha_ );
985  }
986 
988  std::vector< double > &alpha( )
989  {
990  return( alpha_ );
991  }
992 
994  const std::vector< double > &beta( ) const
995  {
996  return( beta_ );
997  }
998 
1000  std::vector< double > &beta( )
1001  {
1002  return( beta_ );
1003  }
1004 
1005  public:
1013  template < template < typename, typename > class FEATURE_LIST, class Allocator >
1014  bool learn( FEATURE_LIST< feature_type, Allocator > & features, size_type number_of_iterations )
1015  {
1016  if( features.empty( ) )
1017  {
1018  std::cerr << "特徴データが指定されていません." << std::endl;
1019  return( false );
1020  }
1021  else if( number_of_iterations == 0 )
1022  {
1023  // 少なくとも1回は実行する
1024  number_of_iterations++;
1025  }
1026 
1027  // 強識別器を初期化する
1028  weak_classifiers_.clear( );
1029  categories_.clear( );
1030  code_word_.clear( );
1031  alpha_.clear( );
1032  beta_.clear( );
1033 
1034 
1035  // カテゴリの数を数える
1036  std::map< std::string, size_type > category_map;
1037  for( size_type i = 0 ; i < features.size( ) ; i++ )
1038  {
1039  category_map[ features[ i ].category ] = 0;
1040  }
1041 
1042  // カテゴリの数を確定する
1043  categories_.reserve( category_map.size( ) );
1044 
1045  // カテゴリのリストを登録する
1046  std::map< std::string, size_type >::iterator ite = category_map.begin( );
1047  for( ; ite != category_map.end( ) ; ++ite )
1048  {
1049  ite->second = categories_.size( );
1050  categories_.push_back( ite->first );
1051  }
1052 
1053  // 重みを初期化する
1054  mist::matrix< double > D( features.size( ), categories_.size( ) );
1055  for( size_type i = 0 ; i < features.size( ) ; i++ )
1056  {
1057  const feature_type &f = features[ i ];
1058  size_type category_index = category_map[ f.category ];
1059  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1060  {
1061  if( l != category_index )
1062  {
1063  D( i, l ) = 1.0 / static_cast< double >( features.size( ) * ( categories_.size( ) - 1 ) );
1064  }
1065  else
1066  {
1067  D( i, l ) = 0.0;
1068  }
1069  }
1070  }
1071 
1072  std::vector< size_type > fcatemap( features.size( ) );
1073  std::vector< bool > fcategories( features.size( ) );
1074  std::vector< double > rpweight( categories_.size( ) );
1075  for( size_type i = 0 ; i < fcatemap.size( ) ; i++ )
1076  {
1077  fcatemap[ i ] = static_cast< typename std::vector< size_type >::value_type >( category_map[ features[ i ].category ] );
1078  }
1079 
1080 #if defined( __ONE_PER_CLASS_CODE_WORD__ ) && __ONE_PER_CLASS_CODE_WORD__ == 1
1081  // 各クラス単位で code word を作る
1082  size_type nhypothesis = categories_.size( );
1083 #elif defined( __RANDOM_CODE_WORD__ ) && __RANDOM_CODE_WORD__ == 1
1084  uniform::random rnd( std::clock( ) );
1085  // code word を ECC ベースで作る
1086  size_type nhypothesis = categories_.size( );
1087 #else
1088  // code word を ECC ベースで作る
1089  size_type nhypothesis = 0;
1090 #endif
1091 
1092  // AdaBoost により強識別器を学習する
1093  for( size_type t = 0 ; t < number_of_iterations ; t++ )
1094  {
1095  // カラーリングを決定する
1096  code_word_.push_back( std::vector< bool >( categories_.size( ) ) );
1097  std::vector< bool > &myu = code_word_.back( );
1098 
1099 #if defined( __ONE_PER_CLASS_CODE_WORD__ ) && __ONE_PER_CLASS_CODE_WORD__ == 1
1100  myu[ t % nhypothesis ] = true;
1101 #elif defined( __RANDOM_CODE_WORD__ ) && __RANDOM_CODE_WORD__ == 1
1102  {
1103  std::vector< pair< double, size_type > > list( nhypothesis );
1104  for( size_type i = 0 ; i < list.size( ) ; i++ )
1105  {
1106  list[ i ].key = rnd.real1( );
1107  list[ i ].value = i;
1108  }
1109  std::sort( list.begin( ), list.end( ) );
1110  for( size_type i = 0 ; i < list.size( ) ; i++ )
1111  {
1112  myu[ list[ i ].value ] = i < list.size( ) / 2;
1113  }
1114  }
1115 #else
1116  if( categories_.size( ) == 2 )
1117  {
1118  myu[ 0 ] = ( t % 2 ) == 0;
1119  myu[ 1 ] = !myu[ 0 ];
1120  }
1121  else
1122  {
1123  myu[ 0 ] = true;
1124  size_type val = nhypothesis++;
1125  bool flag = true;
1126  for( size_type r = categories_.size( ) - 1 ; r > 0 ; r-- )
1127  {
1128  bool b = ( val & 1 ) != 0;
1129  flag = flag && b;
1130  myu[ r ] = b;
1131  val >>= 1;
1132  }
1133 
1134  if( flag )
1135  {
1136  val = nhypothesis++;
1137  for( size_type r = categories_.size( ) - 1 ; r > 0 ; r-- )
1138  {
1139  myu[ r ] = ( val & 1 ) != 0;
1140  val >>= 1;
1141  }
1142  }
1143  }
1144 #endif
1145 
1146 #if defined( __DEBUG_OUTPUT_LEVEL__ ) && __DEBUG_OUTPUT_LEVEL__ >= 3
1147  // 弱識別器の学習用カテゴリデータを作る
1148  for( size_type i = 0 ; i < fcategories.size( ) ; i++ )
1149  {
1150  std::cout << myu[ fcatemap[ i ] ];
1151  }
1152  std::cout << std::endl;
1153 #endif
1154 
1155  // 学習に使う弱識別器を用意する
1156  weak_classifiers_.push_back( weak_classifier_type( ) );
1157  weak_classifier_type &weak = weak_classifiers_.back( );
1158 
1159  for( size_type m = 0 ; m < __NUMBER_OF_INNER_LOOPS__ ; m++ )
1160  {
1161  // 弱識別器の学習用カテゴリデータを作る
1162  for( size_type i = 0 ; i < fcategories.size( ) ; i++ )
1163  {
1164  fcategories[ i ] = myu[ fcatemap[ i ] ];
1165  }
1166 
1167  // 重みを正規化する
1168  double Ut = 0.0;
1169  for( size_type i = 0 ; i < features.size( ) ; i++ )
1170  {
1171  const feature_type &f = features[ i ];
1172  if( f.valid )
1173  {
1174  bool myuY = fcategories[ i ];
1175  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1176  {
1177  if( myuY != myu[ l ] )
1178  {
1179  Ut += D( i, l );
1180  }
1181  }
1182  }
1183  }
1184 
1185  for( size_type i = 0 ; i < D.rows( ) ; i++ )
1186  {
1187  feature_type &f = features[ i ];
1188  if( f.valid )
1189  {
1190  bool myuY = fcategories[ i ];
1191  double sum = 0.0;
1192  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1193  {
1194  if( myuY != myu[ l ] )
1195  {
1196  sum += D( i, l );
1197  }
1198  }
1199 
1200  f.weight = static_cast< feature_value_type >( sum / Ut );
1201  }
1202  }
1203 
1204  // 弱識別器を学習する
1205  weak.learn( features, fcategories );
1206  //std::cout << "しきい値: " << weak.threshold( ) << ", 符号: " << ( weak.sign( ) < 0.0 ? "-" : "+" ) << ", 番号: " << weak.index( ) << std::endl;
1207 
1208  if( m < __NUMBER_OF_INNER_LOOPS__ - 1 )
1209  {
1210  for( size_type i = 0 ; i < rpweight.size( ) ; i++ )
1211  {
1212  rpweight[ i ] = 0.0;
1213  }
1214 
1215  for( size_type i = 0 ; i < features.size( ) ; i++ )
1216  {
1217  feature_type &f = features[ i ];
1218  if( f.valid )
1219  {
1220  double val = weak( f ) ? 1.0 : -1.0;
1221 
1222  double tmp = 0.0;
1223  for( size_type l = 0 ; l < D.cols( ) ; l++ )
1224  {
1225  tmp += D( i, l ) * val;
1226  }
1227 
1228  rpweight[ fcatemap[ i ] ] += tmp;
1229 
1230  for( size_type l = 0 ; l < D.cols( ) ; l++ )
1231  {
1232  rpweight[ l ] -= D( i, l ) * val;
1233  }
1234  }
1235  }
1236 
1237  std::vector< bool > tmyu( myu );
1238  bool isChanged = false;
1239  for( size_type i = 0 ; i < rpweight.size( ) ; i++ )
1240  {
1241  bool nmyu = rpweight[ i ] >= 0.0;
1242  isChanged = isChanged || nmyu != tmyu[ i ];
1243  tmyu[ i ] = nmyu;
1244  }
1245 
1246  if( !isChanged )
1247  {
1248  // 前回とまったく同じなので終了する
1249  break;
1250  }
1251 
1252  // すべて同じコードワードになっていないかをチェックする
1253  {
1254  size_type idx = 1;
1255  for( ; idx < tmyu.size( ) ; idx++ )
1256  {
1257  if( tmyu[ 0 ] != tmyu[ idx ] )
1258  {
1259  break;
1260  }
1261  }
1262 
1263  if( idx < tmyu.size( ) )
1264  {
1265  myu = tmyu;
1266  }
1267  else
1268  {
1269  break;
1270  }
1271  }
1272  }
1273  }
1274 
1275 
1276 #if defined( __DEBUG_OUTPUT_LEVEL__ ) && __DEBUG_OUTPUT_LEVEL__ >= 3
1277  // 学習した弱識別器の分類結果を表示する
1278  for( size_type i = 0 ; i < features.size( ) ; i++ )
1279  {
1280  const feature_type &f = features[ i ];
1281  if( f.valid )
1282  {
1283  std::cout << weak.evaluate( f );
1284  }
1285  }
1286  std::cout << std::endl;
1287 #endif
1288 
1289 #if defined( __ASYMMETRIC_WEIGHTING__ ) && __ASYMMETRIC_WEIGHTING__ == 1
1290  // 重みの更新を非対称に行う
1291  const double eps = 1.0e-16;
1292  double h1u1 = eps;
1293  double h1u0 = eps;
1294  double h0u0 = eps;
1295  double h0u1 = eps;
1296 
1297  for( size_type i = 0 ; i < features.size( ) ; i++ )
1298  {
1299  const feature_type &f = features[ i ];
1300  if( f.valid )
1301  {
1302  bool uY = fcategories[ i ];
1303  bool hX = weak( f );
1304  if( hX && uY )
1305  {
1306  h1u1 += f.weight;
1307  }
1308  else if( hX && !uY )
1309  {
1310  h1u0 += f.weight;
1311  }
1312  else if( !hX && !uY )
1313  {
1314  h0u0 += f.weight;
1315  }
1316  else
1317  {
1318  h0u1 += f.weight;
1319  }
1320  }
1321  }
1322 
1323  double alpha = 0.5 * std::log( h1u1 / h1u0 );
1324  double beta = -0.5 * std::log( h0u0 / h0u1 );
1325 #else
1326  // 重みの更新を対称にする
1327  const double eps = 1.0e-16;
1328  double positives = eps;
1329  double negatives = eps;
1330 
1331  for( size_type i = 0 ; i < features.size( ) ; i++ )
1332  {
1333  const feature_type &f = features[ i ];
1334  if( f.valid )
1335  {
1336  bool uY = fcategories[ i ];
1337  bool hX = weak( f );
1338  if( hX == uY )
1339  {
1340  positives += f.weight;
1341  }
1342  else
1343  {
1344  negatives += f.weight;
1345  }
1346  }
1347  }
1348 
1349  double alpha = 0.5 * std::log( positives / negatives );
1350  double beta = -alpha;
1351 #endif
1352 
1353  alpha_.push_back( alpha );
1354  beta_.push_back( beta );
1355 
1356  double Zt = 0.0;
1357  for( size_type i = 0 ; i < features.size( ) ; i++ )
1358  {
1359  const feature_type &f = features[ i ];
1360  if( f.valid )
1361  {
1362  bool myuY = fcategories[ i ];
1363  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1364  {
1365  double v = ( myu[ l ] - myuY ) * 0.5;
1366  if( weak( f ) )
1367  {
1368  v *= alpha;
1369  }
1370  else
1371  {
1372  v *= beta;
1373  }
1374 
1375  D( i, l ) *= std::exp( v );
1376  Zt += D( i, l );
1377  }
1378  }
1379  }
1380 
1381  for( size_type i = 0 ; i < D.size( ) ; i++ )
1382  {
1383  D[ i ] /= Zt;
1384  }
1385 
1386  if( ( ( t + 1 ) % 5 ) == 0 )
1387  {
1388  double __classification_error__ = error_rate( features );
1389 
1390 #if defined( __DEBUG_OUTPUT_LEVEL__ ) && __DEBUG_OUTPUT_LEVEL__ >= 1
1391  // 1ループ終了
1392  std::cout << "識別器の学習ループ " << t + 1 << " / " << number_of_iterations << " が終了しました。";
1393  std::cout << "分類誤差: " << __classification_error__ << std::endl;
1394 #endif
1395 
1396  if( __classification_error__ == 0.0 )
1397  {
1398  // 分類器の性能に変化が無かった,もしくは,すべて分類できたので終了する
1399  break;
1400  }
1401  }
1402  }
1403 
1404  return( true );
1405  }
1406 
1407  public:
1414  template < class FEATURE >
1415  const std::string operator ()( const FEATURE &f ) const
1416  {
1417  return( evaluate( f ) );
1418  }
1419 
1426  template < class FEATURE >
1427  const std::string evaluate( const FEATURE &f ) const
1428  {
1429 #if 1
1430  std::vector< double > values( categories_.size( ), 0.0 );
1431  for( size_type t = 0 ; t < weak_classifiers_.size( ) ; t++ )
1432  {
1433  const std::vector< bool > &code = code_word_[ t ];
1434  double weight = weak_classifiers_[ t ]( f ) ? alpha_[ t ] : beta_[ t ];
1435 
1436  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1437  {
1438  values[ l ] += code[ l ] * weight;
1439  }
1440  }
1441 
1442  size_type category = 0;
1443  for( size_type l = 1 ; l < categories_.size( ) ; l++ )
1444  {
1445  if( values[ category ] < values[ l ] )
1446  {
1447  category = l;
1448  }
1449  }
1450 #else
1451  double max = 0.0;
1452  size_type category = 0;
1453  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1454  {
1455  double sum = 0.0;
1456  for( size_type t = 0 ; t < weak_classifiers_.size( ) ; t++ )
1457  {
1458  double val = code_word_[ t ][ l ];
1459  if( weak_classifiers_[ t ]( f ) )
1460  {
1461  val *= alpha_[ t ];
1462  }
1463  else
1464  {
1465  val *= beta_[ t ];
1466  }
1467 
1468  sum += val;
1469  }
1470 
1471  if( sum > max )
1472  {
1473  max = sum;
1474  category = l;
1475  }
1476  }
1477 #endif
1478 
1479  return( categories_[ category ] );
1480  }
1481 
1487  template < class FEATURE >
1488  void compute_category_ranks( const FEATURE &f, std::vector< pair< double, std::string > > &ranks ) const
1489  {
1490  std::vector< double > values( categories_.size( ), 0.0 );
1491  for( size_type t = 0 ; t < weak_classifiers_.size( ) ; t++ )
1492  {
1493  const std::vector< bool > &code = code_word_[ t ];
1494  double weight = weak_classifiers_[ t ]( f ) ? alpha_[ t ] : beta_[ t ];
1495 
1496  for( size_type l = 0 ; l < categories_.size( ) ; l++ )
1497  {
1498  values[ l ] += code[ l ] * weight;
1499  }
1500  }
1501 
1502  ranks.clear( );
1503  ranks.reserve( values.size( ) );
1504 
1505  for( size_type l = 0 ; l < values.size( ) ; l++ )
1506  {
1507  ranks.push_back( pair< double, std::string >( values[ l ], categories_[ l ] ) );
1508  }
1509 
1510  std::sort( ranks.begin( ), ranks.end( ), pair< double, std::string >::greater );
1511  }
1512 
1519  template < template < typename, typename > class FEATURE_LIST, class Allocator >
1520  double error_rate( const FEATURE_LIST< feature_type, Allocator > & features ) const
1521  {
1522  if( features.empty( ) )
1523  {
1524  return( 0.0 );
1525  }
1526 
1527  size_type error = 0;
1528  int nfeatures = static_cast< int >( features.size( ) );
1529 
1530  #pragma omp parallel for firstprivate( nfeatures ) reduction( +: error ) schedule( guided )
1531  for( int i = 0 ; i < nfeatures ; i++ )
1532  {
1533  const feature_type &f = features[ i ];
1534  if( f.valid )
1535  {
1536  std::string ret = evaluate( f );
1537 #if defined( __DEBUG_OUTPUT_LEVEL__ ) && __DEBUG_OUTPUT_LEVEL__ >= 3
1538  std::cout << ret;
1539 #endif
1540  if( f.category != ret )
1541  {
1542  error++;
1543  }
1544  }
1545  }
1546 
1547 #if defined( __DEBUG_OUTPUT_LEVEL__ ) && __DEBUG_OUTPUT_LEVEL__ >= 3
1548  std::cout << std::endl;
1549 #endif
1550 
1551  return( static_cast< double >( error ) / static_cast< double >( nfeatures ) );
1552  }
1553 
1554  public:
1555  static const char *get_value( const char *s, const char *e, std::string &val )
1556  {
1557  // 先頭の空白(改行やタブを含む)を飛ばす
1558  while( s < e )
1559  {
1560  if( s[ 0 ] == '\r' )
1561  {
1562  if( s + 1 != e && s[ 1 ] == '\n' )
1563  {
1564  s = s + 2;
1565  }
1566  else
1567  {
1568  s++;
1569  }
1570  }
1571  else if( s[ 0 ] == '\n' )
1572  {
1573  s++;
1574  }
1575  else if( s[ 0 ] == ' ' || s[ 0 ] == '\t' )
1576  {
1577  s++;
1578  }
1579  else
1580  {
1581  break;
1582  }
1583  }
1584 
1585  const char *sp = s;
1586  const char *ep = sp;
1587 
1588  // 次にコンマが来る前まで進める
1589  while( s < e )
1590  {
1591  if( s[ 0 ] == '\r' )
1592  {
1593  if( s + 1 != e && s[ 1 ] == '\n' )
1594  {
1595  s = s + 2;
1596  }
1597  else
1598  {
1599  s++;
1600  }
1601  break;
1602  }
1603  else if( s[ 0 ] == '\n' )
1604  {
1605  s++;
1606  break;
1607  }
1608  else if( s[ 0 ] == ',' )
1609  {
1610  s++;
1611  break;
1612  }
1613 
1614  ep++;
1615  s++;
1616  }
1617 
1618  if( sp < ep )
1619  {
1620  val = std::string( sp, ep );
1621  }
1622 
1623  return( s > e ? e : s );
1624  }
1625 
1626  public:
1635  bool save( const std::string &filename ) const
1636  {
1637  FILE *fp = fopen( filename.c_str( ), "wt" );
1638 
1639  if( fp == NULL )
1640  {
1641  return( false );
1642  }
1643 
1644  // クラス数等の基本情報を書き込む
1645  fprintf( fp, "Category = %ld\n", categories_.size( ) );
1646  fprintf( fp, "Stage = %ld\n", weak_classifiers_.size( ) );
1647 
1648  // クラス名を列挙する
1649  for( size_type i = 0 ; i < categories_.size( ) ; i++ )
1650  {
1651  fprintf( fp, "Class[%ld] : %s\n", i + 1, categories_[ i ].c_str( ) );
1652  }
1653 
1654  // Code Word を列挙する
1655  for( size_type i = 0 ; i < code_word_.size( ) ; i++ )
1656  {
1657  const std::vector< bool > &code = code_word_[ i ];
1658  fprintf( fp, "%d", code[ 0 ] ? 1: 0 );
1659  for( size_type l = 1 ; l < code.size( ) ; l++ )
1660  {
1661  fprintf( fp, ",%d", code[ l ] ? 1: 0 );
1662  }
1663  fprintf( fp, "\n" );
1664  }
1665 
1666  // 弱識別器と Alpha と Beta を列挙する
1667  for( size_type i = 0 ; i < weak_classifiers_.size( ) ; i++ )
1668  {
1669  const weak_classifier_type &weak = weak_classifiers_[ i ];
1670  fprintf( fp, "%s\n", weak.serialize( ).c_str( ) );
1671  fprintf( fp, "%f,%f\n", alpha_[ i ], beta_[ i ] );
1672  }
1673 
1674  fclose( fp );
1675 
1676  return( true );
1677  }
1678 
1687  bool load( const std::string &filename )
1688  {
1689  FILE *fp = fopen( filename.c_str( ), "rt" );
1690 
1691  if( fp == NULL )
1692  {
1693  return( false );
1694  }
1695 
1696  int numClasses = 0, numStages = 0, dmy;
1697  char line[ 4096 ], buff[ 4096 ];
1698 
1699  // クラス数等の基本情報を書き込む
1700  if( fgets( line, 4096, fp ) != NULL )
1701  {
1702  sscanf( line, "Category = %d", &numClasses );
1703  }
1704  if( fgets( line, 4096, fp ) != NULL )
1705  {
1706  sscanf( line, "Stage = %d", &numStages );
1707  }
1708 
1709  // 強識別器を初期化する
1710  weak_classifiers_.resize( numStages );
1711  alpha_.resize( numStages );
1712  beta_.resize( numStages );
1713  code_word_.resize( numStages );
1714  categories_.resize( numClasses );
1715 
1716  // クラス名を読み込む
1717  for( size_type i = 0 ; i < categories_.size( ) ; i++ )
1718  {
1719  if( fgets( line, 4096, fp ) != NULL )
1720  {
1721  memset( buff, '\0', 4096 );
1722  sscanf( line, "Class[%d] : %s", &dmy, buff );
1723  categories_[ i ] = buff;
1724  }
1725  }
1726 
1727  // Code Word を読み込む
1728  for( size_type i = 0 ; i < code_word_.size( ) ; i++ )
1729  {
1730  std::vector< bool > &code = code_word_[ i ];
1731  code.resize( numClasses );
1732 
1733  if( fgets( line, 4096, fp ) == NULL )
1734  {
1735  break;
1736  }
1737 
1738  const char *p = line, *ep = line + 4096;
1739 
1740  for( size_type l = 0 ; l < code.size( ) ; l++ )
1741  {
1742  std::string val;
1743  p = get_value( p, ep, val );
1744  code[ l ] = val == "1" ? true : false;
1745  }
1746  }
1747 
1748  // 弱識別器と Alpha と Beta を列挙する
1749  for( size_type i = 0 ; i < weak_classifiers_.size( ) ; i++ )
1750  {
1751  if( fgets( line, 4096, fp ) != NULL )
1752  {
1753  weak_classifiers_[ i ].deserialize( line );
1754  }
1755 
1756  if( fgets( line, 4096, fp ) != NULL )
1757  {
1758  double alpha, beta;
1759  sscanf( line, "%lf,%lf", &alpha, &beta );
1760  alpha_[ i ] = alpha;
1761  beta_[ i ] = beta;
1762  }
1763  }
1764 
1765  fclose( fp );
1766 
1767  return( true );
1768  }
1769  };
1770  }
1771 
1772 
1774  // 機械学習グループの終わり
1775 }
1776 
1777 
1778 // mist名前空間の終わり
1779 _MIST_END
1780 
1781 
1782 
1783 #endif // __INCLUDE_MACHINE_LEARNING__
1784 

Generated on Wed Nov 12 2014 19:44:17 for MIST by doxygen 1.8.1.2