#ifndef XGBOOST_FMAP_H #define XGBOOST_FMAP_H /*! * \file xgboost_fmap.h * \brief helper class that holds the feature names and interpretations * \author Tianqi Chen: tianqi.tchen@gmail.com */ #include #include #include #include "xgboost_utils.h" namespace xgboost{ namespace utils{ /*! \brief helper class that holds the feature names and interpretations */ class FeatMap{ public: enum Type{ kIndicator = 0, kQuantitive = 1, kInteger = 2, kFloat = 3 }; public: /*! \brief load feature map from text format */ inline void LoadText( const char *fname ){ FILE *fi = utils::FopenCheck( fname, "r" ); this->LoadText( fi ); fclose( fi ); } /*! \brief load feature map from text format */ inline void LoadText( FILE *fi ){ int fid; char fname[256], ftype[256]; while( fscanf( fi, "%d%s%s", &fid, fname, ftype ) == 3 ){ utils::Assert( fid == (int)names_.size(), "invalid fmap format" ); names_.push_back( std::string(fname) ); types_.push_back( GetType( ftype ) ); } } /*! \brief number of known features */ size_t size( void ) const{ return names_.size(); } /*! \brief return name of specific feature */ const char* name( size_t idx ) const{ utils::Assert( idx < names_.size(), "utils::FMap::name feature index exceed bound" ); return names_[ idx ].c_str(); } /*! \brief return type of specific feature */ const Type& type( size_t idx ) const{ utils::Assert( idx < names_.size(), "utils::FMap::name feature index exceed bound" ); return types_[ idx ]; } private: inline static Type GetType( const char *tname ){ if( !strcmp( "i", tname ) ) return kIndicator; if( !strcmp( "q", tname ) ) return kQuantitive; if( !strcmp( "int", tname ) ) return kInteger; if( !strcmp( "float", tname ) ) return kFloat; utils::Error("unknown feature type, use i for indicator and q for quantity"); return kIndicator; } private: /*! \brief name of the feature */ std::vector names_; /*! \brief type of the feature */ std::vector types_; }; }; // namespace utils namespace utils{ /*! \brief feature constraint, allow or disallow some feature during training */ class FeatConstrain{ public: FeatConstrain( void ){ default_state_ = +1; } /*!\brief set parameters */ inline void SetParam( const char *name, const char *val ){ int a, b; if( !strcmp( name, "fban") ){ this->ParseRange( val, a, b ); this->SetRange( a, b, -1 ); } if( !strcmp( name, "fpass") ){ this->ParseRange( val, a, b ); this->SetRange( a, b, +1 ); } if( !strcmp( name, "fdefault") ){ default_state_ = atoi( val ); } } /*! \brief whether constrain is specified */ inline bool HasConstrain( void ) const { return state_.size() != 0 && default_state_ == 1; } /*! \brief whether a feature index is banned or not */ inline bool NotBanned( unsigned index ) const{ int rt = index < state_.size() ? state_[index] : default_state_; if( rt == 0 ) rt = default_state_; return rt == 1; } private: inline void SetRange( int a, int b, int st ){ if( b > (int)state_.size() ) state_.resize( b, 0 ); for( int i = a; i < b; ++ i ){ state_[i] = st; } } inline void ParseRange( const char *val, int &a, int &b ){ if( sscanf( val, "%d-%d", &a, &b ) == 2 ) return; utils::Assert( sscanf( val, "%d", &a ) == 1 ); b = a + 1; } /*! \brief default state */ int default_state_; /*! \brief whether the state here is, +1:pass, -1: ban, 0:default */ std::vector state_; }; }; // namespace utils }; // namespace xgboost #endif // XGBOOST_FMAP_H