diff --git a/src/shogun/lib/SGVector.cpp b/src/shogun/lib/SGVector.cpp index 0156aa4755c..be2f48cf46d 100644 --- a/src/shogun/lib/SGVector.cpp +++ b/src/shogun/lib/SGVector.cpp @@ -994,7 +994,7 @@ template void SGVector::save(CFile* saver) saver->set_vector(vector, vlen); SG_RESET_LOCALE; } - + #define MATHOP(op) \ template void SGVector::op() \ { \ @@ -1030,6 +1030,21 @@ template void SGVector::pow(T q) vector[i]=(T) CMath::pow((double) vector[i], (double) q); } +template +SGVector SGVector::linspace_vec(T start, T end, int32_t n) +{ + return SGVector(linspace(start, end, n), n); +} + +template +float64_t* SGVector::linspace(T start, T end, int32_t n) +{ + float64_t* output = SG_MALLOC(float64_t, n); + CMath::linspace(output, start, end, n); + + return output; +} + template class SGVector; template class SGVector; template class SGVector; diff --git a/src/shogun/lib/SGVector.h b/src/shogun/lib/SGVector.h index da7745ef849..1dad4622ac1 100644 --- a/src/shogun/lib/SGVector.h +++ b/src/shogun/lib/SGVector.h @@ -88,6 +88,24 @@ template class SGVector : public SGReferencedData */ static T* randperm(int32_t n); + /** Returns a vector with n linearly spaced elements between start and end. + * + * @param start beginning of the interval to divide + * @param end upper bound of the interval to divide + * @param n number of elements used to divide the interval + * @return vector with linearly spaced elements within the interval + */ + static SGVector linspace_vec(T start, T end, int32_t n); + + /** Returns an array with n linearly spaced elements between start and end. + * + * @param start beginning of the interval to divide + * @param end upper bound of the interval to divide + * @param n number of elements used to divide the interval + * @return array with linearly spaced elements within the interval + */ + static float64_t* linspace(T start, T end, int32_t n); + /** For a sorted (ascending) vector, gets the index after the first * element that is smaller than the given one * diff --git a/src/shogun/mathematics/Math.cpp b/src/shogun/mathematics/Math.cpp index 7df72623f2f..7b230799e5b 100644 --- a/src/shogun/mathematics/Math.cpp +++ b/src/shogun/mathematics/Math.cpp @@ -183,3 +183,16 @@ float64_t CMath::Align( // return the final cost return actCost; } + +void CMath::linspace(float64_t* output, float64_t start, float64_t end, int32_t n) +{ + float64_t delta = (end-start) / (n-1); + float64_t v = start; + index_t i = 0; + while ( v <= end ) + { + output[i++] = v; + v += delta; + } + output[n-1] = end; +} diff --git a/src/shogun/mathematics/Math.h b/src/shogun/mathematics/Math.h index fb8fe8f85d1..a99b4e1e3b8 100644 --- a/src/shogun/mathematics/Math.h +++ b/src/shogun/mathematics/Math.h @@ -577,6 +577,15 @@ class CMath : public CSGObject return res/factorial(k); } + /** Builds an array with n linearly spaced elements between start and end. + * + * @param output array with linearly spaced elements within the interval + * @param start beginning of the interval to divide + * @param end upper bound of the interval to divide + * @param n number of elements used to divide the interval + */ + static void linspace(float64_t* output, float64_t start, float64_t end, int32_t n = 100); + /** performs a bubblesort on a given matrix a. * it is sorted in ascending order from top to bottom * and left to right */ diff --git a/src/shogun/structure/DualLibQPBMSOSVM.cpp b/src/shogun/structure/DualLibQPBMSOSVM.cpp index adbec11e1ff..3909bce0fda 100644 --- a/src/shogun/structure/DualLibQPBMSOSVM.cpp +++ b/src/shogun/structure/DualLibQPBMSOSVM.cpp @@ -88,6 +88,8 @@ bool CDualLibQPBMSOSVM::train_machine(CFeatures* data) if (data) set_features(data); + // Initialize the model for training + m_model->init_training(); // call the solver switch(m_solver) { diff --git a/src/shogun/structure/HMSVMModel.cpp b/src/shogun/structure/HMSVMModel.cpp index dfb0c6ddac4..e7bdb01e442 100644 --- a/src/shogun/structure/HMSVMModel.cpp +++ b/src/shogun/structure/HMSVMModel.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace shogun; @@ -20,17 +21,13 @@ CHMSVMModel::CHMSVMModel() init(); } -CHMSVMModel::CHMSVMModel(CFeatures* features, CStructuredLabels* labels, EStateModelType smt, int32_t num_obs) +CHMSVMModel::CHMSVMModel(CFeatures* features, CStructuredLabels* labels, EStateModelType smt, int32_t num_obs, bool use_plifs) : CStructuredModel(features, labels) { init(); - m_num_obs = num_obs; - // Shorthand for the number of free states - int32_t free_states = ((CSequenceLabels*) m_labels)->get_num_states(); - // Shorthand for the number of features of the feature vector - int32_t D = ((CMatrixFeatures< float64_t >*) m_features)->get_num_features(); - m_num_aux = free_states*D*(num_obs-1); + m_num_plif_nodes = 20; + m_use_plifs = use_plifs; switch (smt) { @@ -41,25 +38,25 @@ CHMSVMModel::CHMSVMModel(CFeatures* features, CStructuredLabels* labels, EStateM default: SG_ERROR("The EStateModelType given is not valid\n") } - - int32_t S = m_state_model->get_num_states(); - m_transmission_weights = SGMatrix< float64_t >(S,S); - m_emission_weights = SGVector< float64_t >(S*D*m_num_obs); } CHMSVMModel::~CHMSVMModel() { SG_UNREF(m_state_model); + SG_UNREF(m_plif_matrix); } int32_t CHMSVMModel::get_dim() const { - // Shorthand for the number of states - int32_t S = ((CSequenceLabels*) m_labels)->get_num_states(); - // Shorthand for the number of features of the feature vector - int32_t D = ((CMatrixFeatures< float64_t >*) m_features)->get_num_features(); + // Shorthands for the number of states, the matrix features and their dimension + int32_t S = m_state_model->get_num_states(); + CMatrixFeatures< float64_t >* mf = (CMatrixFeatures< float64_t >*) m_features; + int32_t D = mf->get_num_features(); - return S*(S + D*m_num_obs); + if ( m_use_plifs ) + return S*(S + D*m_num_plif_nodes); + else + return S*(S + D*m_num_obs); } SGVector< float64_t > CHMSVMModel::get_joint_feature_vector( @@ -89,19 +86,73 @@ SGVector< float64_t > CHMSVMModel::get_joint_feature_vector( m_emission_weights.zero(); index_t aux_idx, weight_idx; - for ( int32_t f = 0 ; f < D ; ++f ) + if ( !m_use_plifs ) // Do not use PLiFs { - aux_idx = f*m_num_obs; - - for ( int32_t j = 0 ; j < state_seq.vlen ; ++j ) + for ( int32_t f = 0 ; f < D ; ++f ) { - weight_idx = aux_idx + state_seq[j]*D*m_num_obs + obs(f,j); - m_emission_weights[weight_idx] += 1; + aux_idx = f*m_num_obs; + + for ( int32_t j = 0 ; j < state_seq.vlen ; ++j ) + { + weight_idx = aux_idx + state_seq[j]*D*m_num_obs + obs(f,j); + m_emission_weights[weight_idx] += 1; + } } + + m_state_model->weights_to_vector(psi, m_transmission_weights, m_emission_weights, + D, m_num_obs); } + else // Use PLiFs + { + int32_t S = m_state_model->get_num_states(); + CPlif* plif; + float64_t* limits; + // The observation value + float64_t value; + // The number of supporting points smaller or equal than value + int32_t count; + + for ( int32_t f = 0 ; f < D ; ++f ) + { + aux_idx = f*m_num_plif_nodes; - m_state_model->weights_to_vector(psi, m_transmission_weights, m_emission_weights, - D, m_num_obs); + for ( int32_t j = 0 ; j < state_seq.vlen ; ++j ) + { + plif = (CPlif*) m_plif_matrix->get_element(S*f + state_seq[j]); + limits = plif->get_plif_limits(); + count = 0; + value = obs(f,j); + + for ( int32_t i = 0 ; i < m_num_plif_nodes ; ++i ) + { + if ( limits[i] <= value ) + ++count; + else + break; + } + + weight_idx = aux_idx + state_seq[j]*D*m_num_plif_nodes; + + if ( count == 0 ) + m_emission_weights[weight_idx] += 1; + else if ( count == m_num_plif_nodes ) + m_emission_weights[weight_idx + m_num_plif_nodes-1] += 1; + else + { + m_emission_weights[weight_idx + count] += + (value-limits[count-1]) / (limits[count]-limits[count-1]); + + m_emission_weights[weight_idx + count-1] += + (limits[count]-value) / (limits[count]-limits[count-1]); + } + + SG_UNREF(plif); + } + } + + m_state_model->weights_to_vector(psi, m_transmission_weights, m_emission_weights, + D, m_num_plif_nodes); + } return psi; } @@ -120,6 +171,14 @@ CResultSet* CHMSVMModel::argmax( // Shorthand for the number of states int32_t S = m_state_model->get_num_states(); + if ( m_use_plifs ) + { + REQUIRE(m_plif_matrix, "PLiF matrix not allocated, has the SO machine been trained with " + "the use_plifs option?\n"); + REQUIRE(m_plif_matrix->get_num_elements() == S*D, "Dimension mismatch in PLiF matrix, have the " + "feature dimension and/or number of states changed from training to prediction?\n"); + } + // Distribution of start states SGVector< float64_t > p = m_state_model->get_start_states(); // Distribution of stop states @@ -133,22 +192,44 @@ CResultSet* CHMSVMModel::argmax( int32_t T = x.num_cols; SGMatrix< float64_t > E(S, T); E.zero(); - index_t em_idx; - m_state_model->reshape_emission_params(m_emission_weights, w, D, m_num_obs); - for ( int32_t i = 0 ; i < T ; ++i ) + if ( !m_use_plifs ) // Do not use PLiFs { - for ( int32_t j = 0 ; j < D ; ++j ) + index_t em_idx; + m_state_model->reshape_emission_params(m_emission_weights, w, D, m_num_obs); + + for ( int32_t i = 0 ; i < T ; ++i ) { - //FIXME make independent of observation values - em_idx = j*m_num_obs + (index_t)CMath::round(x(j,i)); + for ( int32_t j = 0 ; j < D ; ++j ) + { + //FIXME make independent of observation values + em_idx = j*m_num_obs + (index_t)CMath::round(x(j,i)); + for ( int32_t s = 0 ; s < S ; ++s ) + E(s,i) += m_emission_weights[s*D*m_num_obs + em_idx]; + } + } + } + else // Use PLiFs + { + m_state_model->reshape_emission_params(m_plif_matrix, w, D, m_num_plif_nodes); + + CPlif* plif; + for ( int32_t f = 0 ; f < D ; ++f ) + { for ( int32_t s = 0 ; s < S ; ++s ) - E(s,i) += m_emission_weights[s*D*m_num_obs + em_idx]; + { + plif = (CPlif*) m_plif_matrix->get_element(S*f + s); + + for ( int32_t i = 0 ; i < T ; ++i ) + E(s,i) += plif->lookup( x(f,i) ); + + SG_UNREF(plif); + } } } - // If argmax used while training, add to E the loss matrix + // If argmax used while training, add to E the loss matrix (loss-augmented inference) if ( training ) { CSequence* ytrue = @@ -280,7 +361,8 @@ void CHMSVMModel::init_opt( SGVector< float64_t > ub, SGMatrix< float64_t > & C) { - // Shorthand for the number of free states + // Shorthand for the number of free states (i.e. states that have all their + // parameters learnt) int32_t S = ((CSequenceLabels*) m_labels)->get_num_states(); // Shorthand for the number of features of the feature vector int32_t D = ((CMatrixFeatures< float64_t >*) m_features)->get_num_features(); @@ -310,12 +392,13 @@ void CHMSVMModel::init_opt( // Indices to the beginning of the blocks of scores. Each block is // formed by the scores of a pair (state, feature) SGVector< int32_t > score_starts(S*D); - for ( int32_t idx = S*S, k = 0 ; k < S*D ; idx += m_num_obs, ++k ) + int32_t delta = m_use_plifs ? m_num_plif_nodes : m_num_obs; + for ( int32_t idx = S*S, k = 0 ; k < S*D ; idx += delta, ++k ) score_starts[k] = idx; // Indices to the beginning of the blocks of variables for smoothness SGVector< int32_t > aux_starts_smooth(S*D); - for ( int32_t idx = get_dim(), k = 0 ; k < S*D ; idx += m_num_obs-1, ++k ) + for ( int32_t idx = get_dim(), k = 0 ; k < S*D ; idx += delta-1, ++k ) aux_starts_smooth[k] = idx; // Bound the difference between adjacent score values from above and @@ -329,7 +412,7 @@ void CHMSVMModel::init_opt( scr_idx = score_starts[i]; aux_idx = aux_starts_smooth[i]; - for ( int32_t j = 0 ; j < m_num_obs-1 ; ++j ) + for ( int32_t j = 0 ; j < delta-1 ; ++j ) { A(con_idx, scr_idx) = 1; A(con_idx, scr_idx+1) = -1; @@ -403,17 +486,21 @@ bool CHMSVMModel::check_training_setup() const void CHMSVMModel::init() { - SG_ADD(&m_num_states, "m_num_states", "The number of states", MS_NOT_AVAILABLE); SG_ADD((CSGObject**) &m_state_model, "m_state_model", "The state model", MS_NOT_AVAILABLE); SG_ADD(&m_transmission_weights, "m_transmission_weights", "Transmission weights used in Viterbi", MS_NOT_AVAILABLE); SG_ADD(&m_emission_weights, "m_emission_weights", "Emission weights used in Viterbi", MS_NOT_AVAILABLE); + SG_ADD(&m_num_plif_nodes, "m_num_plif_nodes", "The number of points per PLiF", + MS_NOT_AVAILABLE); // FIXME It would actually make sense to do MS for this parameter + SG_ADD(&m_use_plifs, "m_use_plifs", "Whether to use plifs", MS_NOT_AVAILABLE); - m_num_states = 0; - m_num_obs = 0; - m_num_aux = 0; + m_num_obs = 0; + m_num_aux = 0; + m_use_plifs = false; m_state_model = NULL; + m_plif_matrix = NULL; + m_num_plif_nodes = 0; } int32_t CHMSVMModel::get_num_aux() const @@ -425,3 +512,84 @@ int32_t CHMSVMModel::get_num_aux_con() const { return 2*m_num_aux; } + +void CHMSVMModel::set_use_plifs(bool use_plifs) +{ + m_use_plifs = use_plifs; +} + +void CHMSVMModel::init_training() +{ + // Shorthands for the number of states, the matrix features and their dimension + int32_t S = m_state_model->get_num_states(); + CMatrixFeatures< float64_t >* mf = (CMatrixFeatures< float64_t >*) m_features; + int32_t D = mf->get_num_features(); + + // Transmission and emission weights allocation + m_transmission_weights = SGMatrix< float64_t >(S,S); + if ( m_use_plifs ) + m_emission_weights = SGVector< float64_t >(S*D*m_num_plif_nodes); + else + m_emission_weights = SGVector< float64_t >(S*D*m_num_obs); + + // Auxiliary variables + + // Shorthand for the number of free states + int32_t free_states = ((CSequenceLabels*) m_labels)->get_num_states(); + if ( m_use_plifs ) + m_num_aux = free_states*D*(m_num_plif_nodes-1); + else + m_num_aux = free_states*D*(m_num_obs-1); + + if ( m_use_plifs ) + { + // Initialize PLiF matrix + m_plif_matrix = new CDynamicObjectArray(S*D); + SG_REF(m_plif_matrix); + + // Determine the x values for the supporting points of the PLiFs + + // Count the number of points per feature, using all the feature vectors + int32_t N = 0; + for ( int32_t i = 0 ; i < mf->get_num_vectors() ; ++i ) + { + SGMatrix feat_vec = mf->get_feature_vector(i); + N += feat_vec.num_cols; + } + + // Choose the supporting points so that roughly the same number of points fall in each bin + SGVector< float64_t > a = SGVector< float64_t >::linspace_vec(1, N, m_num_plif_nodes+1); + SGVector< index_t > signal_idxs(m_num_plif_nodes); + for ( int32_t i = 0 ; i < signal_idxs.vlen ; ++i ) + signal_idxs[i] = (index_t) CMath::round( (a[i] + a[i+1]) / 2 ) - 1; + + SGVector< float64_t > signal(N); + index_t idx; // used to populate signal + for ( int32_t f = 0 ; f < D ; ++f ) + { + // Get the points of feature f of all the feature vectors + idx = 0; + for ( int32_t i = 0 ; i < mf->get_num_vectors() ; ++i ) + { + SGMatrix feat_vec = mf->get_feature_vector(i); + for ( int32_t j = 0 ; j < feat_vec.num_cols ; ++j ) + signal[idx++] = feat_vec(f,j); + } + + signal.qsort(); + SGVector< float64_t > limits(m_num_plif_nodes); + for ( int32_t i = 0 ; i < m_num_plif_nodes ; ++i ) + limits[i] = signal[ signal_idxs[i] ]; + + // Set the PLiFs' supporting points + for ( int32_t s = 0 ; s < S ; ++s ) + { + CPlif* plif = new CPlif(m_num_plif_nodes); + plif->set_plif_limits(limits); + plif->set_min_value(-CMath::INFTY); + plif->set_max_value(CMath::INFTY); + m_plif_matrix->push_back(plif); + } + } + } +} diff --git a/src/shogun/structure/HMSVMModel.h b/src/shogun/structure/HMSVMModel.h index 7ca8d7eef27..51de6818fbb 100644 --- a/src/shogun/structure/HMSVMModel.h +++ b/src/shogun/structure/HMSVMModel.h @@ -38,8 +38,9 @@ class CHMSVMModel : public CStructuredModel * @param labels sequence labels * @param smt internal state representation * @param num_obs number of observations + * @param use_plifs whether to model the observations using PLiFs */ - CHMSVMModel(CFeatures* features, CStructuredLabels* labels, EStateModelType smt, int32_t num_obs); + CHMSVMModel(CFeatures* features, CStructuredLabels* labels, EStateModelType smt, int32_t num_obs=0, bool use_plifs=false); /** destructor */ virtual ~CHMSVMModel(); @@ -129,15 +130,25 @@ class CHMSVMModel : public CStructuredModel */ virtual int32_t get_num_aux_con() const; + /** setter for use_plifs + * + * @param use_plifs whether PLiFs shall be used + */ + void set_use_plifs(bool use_plifs); + + /** + * initializes the emission and transmission vectors of weights used in Viterbi + * decoding. In case PLiFs are used, it also initializes the matrix of PLiFs and + * automatically selects the supporting points based on the feature values + */ + virtual void init_training(); + private: /* internal initialization */ void init(); private: - /** the number of states */ - int32_t m_num_states; - - /** the number of observations */ + /** in case of discrete observations, the cardinality of the space of observations */ int32_t m_num_obs; /** the number of auxiliary variables */ @@ -152,6 +163,15 @@ class CHMSVMModel : public CStructuredModel /** emission weights used in Viterbi */ SGVector< float64_t > m_emission_weights; + /** number of supporting points for each PLiF */ + int32_t m_num_plif_nodes; + + /** PLiF matrix of dimensions (num_states, num_features) */ + CDynamicObjectArray* m_plif_matrix; + + /** whether to use PLiFs. Otherwise, the observations must be discrete and finite */ + bool m_use_plifs; + }; /* class CHMSVMModel */ } /* namespace shogun */ diff --git a/src/shogun/structure/PrimalMosekSOSVM.cpp b/src/shogun/structure/PrimalMosekSOSVM.cpp index 94c70040080..4976dd014ca 100644 --- a/src/shogun/structure/PrimalMosekSOSVM.cpp +++ b/src/shogun/structure/PrimalMosekSOSVM.cpp @@ -50,6 +50,8 @@ bool CPrimalMosekSOSVM::train_machine(CFeatures* data) set_features(data); CFeatures* model_features = get_features(); + // Initialize the model for training + m_model->init_training(); // Check that the scenary is correct to start with training m_model->check_training_setup(); SG_DEBUG("The training setup is correct.\n"); diff --git a/src/shogun/structure/StateModel.h b/src/shogun/structure/StateModel.h index 22f6969db30..550521e5f79 100644 --- a/src/shogun/structure/StateModel.h +++ b/src/shogun/structure/StateModel.h @@ -64,7 +64,7 @@ class CStateModel : public CSGObject virtual float64_t loss(CSequence* label_seq_lhs, CSequence* label_seq_rhs) = 0; /** - * arranges the emission parameterss of the weight vector into a vector + * arranges the emission parameters of the weight vector into a vector * adding zero elements for the states whose parameters are not learnt. * This vector is suitable to iterate through when constructing the * emission matrix used in Viterbi decoding @@ -78,7 +78,20 @@ class CStateModel : public CSGObject SGVector< float64_t > w, int32_t num_feats, int32_t num_obs) = 0; /** - * arranges the tranmission parameterss of the weight vector into a matrix + * arranges the emission parameters of the weight vector into a matrix + * of PLiFs adding zero elements for the states whose parameters are not + * learnt. + * + * @param plif_matrix matrix of PLiFs outputted + * @param w the weight vector + * @param num_feats number of features + * @param num_plif_nodes number of nodes in the PLiFs + */ + virtual void reshape_emission_params(CDynamicObjectArray* plif_matrix, + SGVector< float64_t > w, int32_t num_feats, int32_t num_plif_nodes) = 0; + + /** + * arranges the transmission parameters of the weight vector into a matrix * adding zero elements for the states whose parameters are not learnt. * This matrix is suitable to iterate during Viterbi decoding * diff --git a/src/shogun/structure/StructuredModel.cpp b/src/shogun/structure/StructuredModel.cpp index 79d5712ccf8..8a1fd444ce0 100644 --- a/src/shogun/structure/StructuredModel.cpp +++ b/src/shogun/structure/StructuredModel.cpp @@ -39,6 +39,9 @@ CStructuredModel::CStructuredModel( CStructuredLabels* labels) : CSGObject() { +#ifdef USE_SWIG_DIRECTORS + m_use_director_risk=false; +#endif init(); m_features = features; @@ -144,6 +147,11 @@ void CStructuredModel::init() m_labels = NULL; } +void CStructuredModel::init_training() +{ + // Nothing to do here +} + bool CStructuredModel::check_training_setup() const { // Nothing to do here diff --git a/src/shogun/structure/StructuredModel.h b/src/shogun/structure/StructuredModel.h index 5e43d9044af..f9e63e1da52 100644 --- a/src/shogun/structure/StructuredModel.h +++ b/src/shogun/structure/StructuredModel.h @@ -208,6 +208,12 @@ class CStructuredModel : public CSGObject /** @return name of SGSerializable */ virtual const char* get_name() const { return "StructuredModel"; } + /** initializes the part of the model that needs to be used during training. + * In this class this method is empty and it can be re-implemented for any + * particular StructuredModel + */ + virtual void init_training(); + /** * method to be called from a SO machine before training * to ensure that the training data is valid (e.g. check that diff --git a/src/shogun/structure/TwoStateModel.cpp b/src/shogun/structure/TwoStateModel.cpp index ebcda87ce45..b343c32d003 100644 --- a/src/shogun/structure/TwoStateModel.cpp +++ b/src/shogun/structure/TwoStateModel.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace shogun; @@ -143,6 +144,28 @@ void CTwoStateModel::reshape_emission_params(SGVector< float64_t >& emission_wei } } +void CTwoStateModel::reshape_emission_params(CDynamicObjectArray* plif_matrix, + SGVector< float64_t > w, int32_t num_feats, int32_t num_plif_nodes) +{ + CPlif* plif; + index_t p_idx, w_idx = m_num_transmission_params; + for ( int32_t s = 2 ; s < m_num_states ; ++s ) + { + for ( int32_t f = 0 ; f < num_feats ; ++f ) + { + SGVector< float64_t > penalties(num_plif_nodes); + p_idx = 0; + + for ( int32_t i = 0 ; i < num_plif_nodes ; ++i ) + penalties[p_idx++] = w[w_idx++]; + + plif = (CPlif*) plif_matrix->get_element(m_num_states*f + s); + plif->set_plif_penalty(penalties); + SG_UNREF(plif); + } + } +} + void CTwoStateModel::reshape_transmission_params( SGMatrix< float64_t >& transmission_weights, SGVector< float64_t > w) { @@ -213,18 +236,11 @@ SGVector< int32_t > CTwoStateModel::get_monotonicity(int32_t num_free_states, return monotonicity; } -CHMSVMModel* CTwoStateModel::simulate_two_state_data() +CHMSVMModel* CTwoStateModel::simulate_data(int32_t num_exm, int32_t exm_len, + int32_t num_features, int32_t num_noise_features) { - // Number of examples - int32_t num_exm = 1000; - // Length of each example sequence - int32_t exm_len = 250; // Number of different states int32_t num_states = 2; - // Total number of features - int32_t num_features = 10; - // Number of features to be pure noise - int32_t num_noise_features = 2; // Min and max length of positive block int32_t block_len[] = {10, 100}; // Min and max number of positive blocks per example @@ -310,5 +326,7 @@ CHMSVMModel* CTwoStateModel::simulate_two_state_data() CMatrixFeatures< float64_t >* features = new CMatrixFeatures< float64_t >(signal, exm_len, num_exm); - return new CHMSVMModel(features, labels, SMT_TWO_STATE, 3); + int32_t num_obs = 0; // continuous observations, dummy value + bool use_plifs = true; + return new CHMSVMModel(features, labels, SMT_TWO_STATE, num_obs, use_plifs); } diff --git a/src/shogun/structure/TwoStateModel.h b/src/shogun/structure/TwoStateModel.h index 7673fe54cf5..b33a626b222 100644 --- a/src/shogun/structure/TwoStateModel.h +++ b/src/shogun/structure/TwoStateModel.h @@ -68,7 +68,21 @@ class CTwoStateModel : public CStateModel SGVector< float64_t > w, int32_t num_feats, int32_t num_obs); /** - * arranges the tranmission parameterss of the weight vector into a matrix + * arranges the emission parameters of the weight vector into a matrix + * of PLiFs adding zero elements for the states whose parameters are not + * learnt. + * + * @param plif_matrix matrix of PLiFs outputted + * @param w the weight vector + * @param num_feats number of features + * @param num_obs number of emission scores per feature and state + * @param num_plif_nodes number of nodes in the PLiFs + */ + virtual void reshape_emission_params(CDynamicObjectArray* plif_matrix, + SGVector< float64_t > w, int32_t num_feats, int32_t num_plif_nodes); + + /** + * arranges the transmission parameters of the weight vector into a matrix * adding zero elements for the states whose parameters are not learnt. * This matrix is suitable to iterate during Viterbi decoding * @@ -132,9 +146,14 @@ class CTwoStateModel : public CStateModel * generates simulated data. The features are generated from the label * sequence swapping some of the labels and adding noise * + * @param num_exm number of sample pairs (sequence of features, sequence of labels) to generate + * @param exm_len length of each sample sequence + * @param num_features features dimension + * @param num_noise_features number of features to be pure noise + * * @return a model that contains the data simulated */ - static CHMSVMModel* simulate_two_state_data(); + static CHMSVMModel* simulate_data(int32_t num_exm, int32_t exm_len, int32_t num_features, int32_t num_noise_features); /** @return name of SGSerializable */ virtual const char* get_name() const { return "TwoStateModel"; }