Skip to content

Commit

Permalink
Merge pull request #1089 from iglesias/feature/hmsvm_plifs
Browse files Browse the repository at this point in the history
Support for continuous features with the HM-SVM using PLiFs
  • Loading branch information
iglesias committed Jun 3, 2013
2 parents 05cbbc7 + 64e789a commit 923f9b3
Show file tree
Hide file tree
Showing 31 changed files with 617 additions and 110 deletions.
10 changes: 5 additions & 5 deletions examples/undocumented/libshogun/so_hmsvm_mosek_simple.cpp
Expand Up @@ -24,11 +24,11 @@ int main(int argc, char ** argv)

// No need for ref_counting in SGVector since the data is allocated
// during compilation time
labels->add_label(SGVector< int32_t >(lab1, 4, false));
labels->add_label(SGVector< int32_t >(lab2, 4, false));
labels->add_label(SGVector< int32_t >(lab3, 4, false));
labels->add_label(SGVector< int32_t >(lab4, 4, false));
labels->add_label(SGVector< int32_t >(lab5, 4, false));
labels->add_vector_label(SGVector< int32_t >(lab1, 4, false));
labels->add_vector_label(SGVector< int32_t >(lab2, 4, false));
labels->add_vector_label(SGVector< int32_t >(lab3, 4, false));
labels->add_vector_label(SGVector< int32_t >(lab4, 4, false));
labels->add_vector_label(SGVector< int32_t >(lab5, 4, false));

// Create features
CMatrixFeatures< float64_t >* features = new CMatrixFeatures< float64_t >(5, 3);
Expand Down
Expand Up @@ -8,7 +8,7 @@

parameter_list=[[data_dict]]

def structure_hmsvm_bmrm (m_data_dict=data_dict):
def structure_discrete_hmsvm_bmrm (m_data_dict=data_dict):
from shogun.Features import RealMatrixFeatures
from shogun.Loss import HingeLoss
from shogun.Structure import SequenceLabels, HMSVMModel, Sequence, TwoStateModel, SMT_TWO_STATE
Expand All @@ -24,19 +24,18 @@ def structure_hmsvm_bmrm (m_data_dict=data_dict):
features = RealMatrixFeatures(m_data_dict['signal'].astype(float), 250, 500)

loss = HingeLoss()
model = HMSVMModel(features, labels, SMT_TWO_STATE, 4)
num_obs = 4 # given by the data file used
model = HMSVMModel(features, labels, SMT_TWO_STATE, num_obs)

sosvm = DualLibQPBMSOSVM(model, loss, labels, 5000.0)
sosvm.train()

#print sosvm.get_w()

predicted = sosvm.apply()
predicted = sosvm.apply(features)
evaluator = StructuredAccuracy()
acc = evaluator.evaluate(predicted, labels)

#print('Accuracy = %.4f' % acc)

if __name__ == '__main__':
print("HMSVM BMRM")
structure_hmsvm_bmrm(*parameter_list[0])
print("Discrete HMSVM BMRM")
structure_discrete_hmsvm_bmrm(*parameter_list[0])
Expand Up @@ -8,7 +8,7 @@

parameter_list=[[data_dict]]

def structure_hmsvm_mosek (m_data_dict=data_dict):
def structure_discrete_hmsvm_mosek (m_data_dict=data_dict):
from shogun.Features import RealMatrixFeatures
from shogun.Loss import HingeLoss
from shogun.Structure import SequenceLabels, HMSVMModel, Sequence, TwoStateModel, SMT_TWO_STATE
Expand All @@ -29,18 +29,18 @@ def structure_hmsvm_mosek (m_data_dict=data_dict):
features = RealMatrixFeatures(m_data_dict['signal'].astype(float), 250, 500)

loss = HingeLoss()
model = HMSVMModel(features, labels, SMT_TWO_STATE, 4)
num_obs = 4 # given by the data file used
model = HMSVMModel(features, labels, SMT_TWO_STATE, num_obs)

sosvm = PrimalMosekSOSVM(model, loss, labels)
sosvm.train()
print(sosvm.get_w())
#print(sosvm.get_w())

predicted = sosvm.apply()
evaluator = StructuredAccuracy()
acc = evaluator.evaluate(predicted, labels)

print('Accuracy = %.4f' % acc)
#print('Accuracy = %.4f' % acc)

if __name__ == '__main__':
print("HMSVM Mosek")
structure_hmsvm_mosek(*parameter_list[0])
print("Discrete HMSVM Mosek")
structure_discrete_hmsvm_mosek(*parameter_list[0])
25 changes: 25 additions & 0 deletions examples/undocumented/python_modular/structure_plif_hmsvm_bmrm.py
@@ -0,0 +1,25 @@
#!/usr/bin/env python

parameter_list=[[100, 250, 10, 2]]

def structure_plif_hmsvm_bmrm (num_examples, example_length, num_features, num_noise_features):
from shogun.Features import RealMatrixFeatures
from shogun.Loss import HingeLoss
from shogun.Structure import TwoStateModel, DualLibQPBMSOSVM
from shogun.Evaluation import StructuredAccuracy

model = TwoStateModel.simulate_data(num_examples, example_length, num_features, num_noise_features)
loss = HingeLoss()
sosvm = DualLibQPBMSOSVM(model, loss, model.get_labels(), 5000.0)

sosvm.train()
#print sosvm.get_w()

predicted = sosvm.apply(model.get_features())
evaluator = StructuredAccuracy()
acc = evaluator.evaluate(predicted, model.get_labels())
#print('Accuracy = %.4f' % acc)

if __name__ == '__main__':
print("PLiF HMSVM BMRM")
structure_plif_hmsvm_bmrm(*parameter_list[0])
31 changes: 31 additions & 0 deletions examples/undocumented/python_modular/structure_plif_hmsvm_mosek.py
@@ -0,0 +1,31 @@
#!/usr/bin/env python

parameter_list=[[100, 250, 10, 2]]

def structure_plif_hmsvm_mosek (num_examples, example_length, num_features, num_noise_features):
from shogun.Features import RealMatrixFeatures
from shogun.Loss import HingeLoss
from shogun.Structure import TwoStateModel
from shogun.Evaluation import StructuredAccuracy

try:
from shogun.Structure import PrimalMosekSOSVM
except ImportError:
print("Mosek not available")
return

model = TwoStateModel.simulate_data(num_examples, example_length, num_features, num_noise_features)
loss = HingeLoss()
sosvm = PrimalMosekSOSVM(model, loss, model.get_labels())

sosvm.train()
#print(sosvm.get_w())

predicted = sosvm.apply(model.get_features())
evaluator = StructuredAccuracy()
acc = evaluator.evaluate(predicted, model.get_labels())
#print('Accuracy = %.4f' % acc)

if __name__ == '__main__':
print("PLiF HMSVM Mosek")
structure_plif_hmsvm_mosek(*parameter_list[0])
2 changes: 1 addition & 1 deletion src/shogun/features/MatrixFeatures.cpp
Expand Up @@ -117,7 +117,7 @@ template< class ST > void CMatrixFeatures< ST >::get_feature_vector_col(
}

template< class ST > void CMatrixFeatures< ST >::set_feature_vector(
SGMatrix< ST > const & vec,
SGMatrix< ST > const vec,
int32_t num)
{
if ( num < 0 || num >= get_num_vectors() )
Expand Down
2 changes: 1 addition & 1 deletion src/shogun/features/MatrixFeatures.h
Expand Up @@ -109,7 +109,7 @@ template< class ST > class CMatrixFeatures : public CFeatures
* @param vec feature vector
* @param num index of vector to set
*/
void set_feature_vector(SGMatrix< ST > const & vec, int32_t num);
void set_feature_vector(SGMatrix< ST > const vec, int32_t num);

/** get features
*
Expand Down
17 changes: 16 additions & 1 deletion src/shogun/lib/SGVector.cpp
Expand Up @@ -994,7 +994,7 @@ template<class T> void SGVector<T>::save(CFile* saver)
saver->set_vector(vector, vlen);
SG_RESET_LOCALE;
}

#define MATHOP(op) \
template <class T> void SGVector<T>::op() \
{ \
Expand Down Expand Up @@ -1030,6 +1030,21 @@ template <class T> void SGVector<T>::pow(T q)
vector[i]=(T) CMath::pow((double) vector[i], (double) q);
}

template <class T>
SGVector<float64_t> SGVector<T>::linspace_vec(T start, T end, int32_t n)
{
return SGVector<float64_t>(linspace(start, end, n), n);
}

template <class T>
float64_t* SGVector<T>::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<bool>;
template class SGVector<char>;
template class SGVector<int8_t>;
Expand Down
18 changes: 18 additions & 0 deletions src/shogun/lib/SGVector.h
Expand Up @@ -88,6 +88,24 @@ template<class T> 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<float64_t> 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
*
Expand Down
4 changes: 4 additions & 0 deletions src/shogun/machine/LinearStructuredOutputMachine.cpp
Expand Up @@ -84,3 +84,7 @@ void CLinearStructuredOutputMachine::register_parameters()
{
SG_ADD(&m_w, "m_w", "Weight vector", MS_NOT_AVAILABLE);
}

void CLinearStructuredOutputMachine::store_model_features()
{
}
6 changes: 6 additions & 0 deletions src/shogun/machine/LinearStructuredOutputMachine.h
Expand Up @@ -69,6 +69,12 @@ class CLinearStructuredOutputMachine : public CStructuredOutputMachine
*/
virtual CStructuredLabels* apply_structured(CFeatures* data = NULL);

/** Stores feature data of underlying model. Does nothing because
* Linear machines store the normal vector of the separating hyperplane
* and therefore the model anyway
*/
virtual void store_model_features();

/** @return object name */
virtual const char* get_name() const
{
Expand Down
6 changes: 6 additions & 0 deletions src/shogun/machine/StructuredOutputMachine.cpp
Expand Up @@ -67,3 +67,9 @@ void CStructuredOutputMachine::register_parameters()
SG_ADD((CSGObject**)&m_model, "m_model", "Structured model", MS_NOT_AVAILABLE);
SG_ADD((CSGObject**)&m_loss, "m_loss", "Structured loss", MS_NOT_AVAILABLE);
}

void CStructuredOutputMachine::set_labels(CLabels* lab)
{
CMachine::set_labels(lab);
m_model->set_labels(CLabelsFactory::to_structured(lab));
}
6 changes: 6 additions & 0 deletions src/shogun/machine/StructuredOutputMachine.h
Expand Up @@ -73,6 +73,12 @@ class CStructuredOutputMachine : public CMachine
return "StructuredOutputMachine";
}

/** set labels
*
* @param lab labels
*/
virtual void set_labels(CLabels* lab);

private:
/** register class members */
void register_parameters();
Expand Down
13 changes: 13 additions & 0 deletions src/shogun/mathematics/Math.cpp
Expand Up @@ -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;
}
9 changes: 9 additions & 0 deletions src/shogun/mathematics/Math.h
Expand Up @@ -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 */
Expand Down
17 changes: 15 additions & 2 deletions src/shogun/structure/DirectorStructuredModel.cpp
Expand Up @@ -53,9 +53,22 @@ bool CDirectorStructuredModel::check_training_setup() const
return false;
}

void CDirectorStructuredModel::init_opt(SGMatrix< float64_t > & A, SGVector< float64_t > a, SGMatrix< float64_t > B, SGVector< float64_t > & b, SGVector< float64_t > lb, SGVector< float64_t > ub, SGMatrix < float64_t > & C)
void CDirectorStructuredModel::init_opt(
float64_t regularization,
SGMatrix< float64_t > & A,
SGVector< float64_t > a,
SGMatrix< float64_t > B,
SGVector< float64_t > & b,
SGVector< float64_t > lb,
SGVector< float64_t > ub,
SGMatrix< float64_t > & C)
{
SG_ERROR("Please implemement init_opt(A,a,B,b,lb,ub,C) in your target language before use\n")
SG_ERROR("Please implemement init_opt(regularization,A,a,B,b,lb,ub,C) in your target language before use\n")
}

void CDirectorStructuredModel::init_training()
{
SG_ERROR("Please implemement init_training() in your target language before use\n")
}

#endif /* USE_SWIG_DIRECTORS */
10 changes: 9 additions & 1 deletion src/shogun/structure/DirectorStructuredModel.h
Expand Up @@ -98,7 +98,12 @@ IGNORE_IN_CLASSLIST class CDirectorStructuredModel : public CStructuredModel
* @param ub
* @param C
*/
virtual void init_opt(SGMatrix< float64_t > & A, SGVector< float64_t > a, SGMatrix< float64_t > B, SGVector< float64_t > & b, SGVector< float64_t > lb, SGVector< float64_t > ub, SGMatrix < float64_t > & C);
virtual void init_opt(
float64_t regularization,
SGMatrix< float64_t > & A, SGVector< float64_t > a,
SGMatrix< float64_t > B, SGVector< float64_t > & b,
SGVector< float64_t > lb, SGVector< float64_t > ub,
SGMatrix < float64_t > & C);

using CStructuredModel::director_risk;

Expand All @@ -107,6 +112,9 @@ IGNORE_IN_CLASSLIST class CDirectorStructuredModel : public CStructuredModel
/** @return name of SGSerializable */
virtual const char* get_name() const { return "DirectorStructuredModel"; }

/** initializes the part of the model that needs to be used during training. */
virtual void init_training();

}; /* class CDirectorStructuredModel */
} /* namespace shogun */
#endif /* USE_SWIG_DIRECTORS */
Expand Down
2 changes: 2 additions & 0 deletions src/shogun/structure/DualLibQPBMSOSVM.cpp
Expand Up @@ -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)
{
Expand Down

0 comments on commit 923f9b3

Please sign in to comment.