Skip to content

Commit

Permalink
Merge pull request #752 from iglesias/master
Browse files Browse the repository at this point in the history
Loss included in multiclass argmax
  • Loading branch information
lisitsyn committed Aug 22, 2012
2 parents 50ba31c + bbb3457 commit 8cec5d0
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 9 deletions.
1 change: 1 addition & 0 deletions examples/undocumented/libshogun/Makefile
Expand Up @@ -96,6 +96,7 @@ TARGETS = basic_minimal \
statistics_linear_time_mmd_kernel_choice \
statistics_hsic \
classifier_featureblocklogisticregression \
so_multiclass_BMRM \

all: $(TARGETS)

Expand Down
42 changes: 39 additions & 3 deletions examples/undocumented/libshogun/so_multiclass.cpp
Expand Up @@ -13,6 +13,8 @@
#include <shogun/structure/MulticlassSOLabels.h>
#include <shogun/structure/MulticlassModel.h>
#include <shogun/structure/PrimalMosekSOSVM.h>
#include <shogun/structure/DualLibQPBMSOSVM.h>
#include <shogun/lib/Time.h>

using namespace shogun;

Expand Down Expand Up @@ -59,14 +61,37 @@ void gen_rand_data(SGVector< float64_t > labs, SGMatrix< float64_t > feats)
fclose(pfile);
}

void read_data(SGVector< float64_t > labs, SGMatrix< float64_t > feats)
{
FILE* pfile = fopen(FNAME, "r");
int32_t label, idx;
float32_t value;

for ( int32_t i = 0 ; i < NUM_SAMPLES*NUM_CLASSES ; ++i )
{
fscanf(pfile, "%d", &label);

labs[i] = label;

for ( int32_t j = 0 ; j < DIMS ; ++j )
{
fscanf(pfile, "%d:%f", &idx, &value);
feats[i*DIMS + j] = value;
}
}

fclose(pfile);
}

int main(int argc, char ** argv)
{
init_shogun_with_defaults();

SGVector< float64_t > labs(NUM_CLASSES*NUM_SAMPLES);
SGMatrix< float64_t > feats(DIMS, NUM_CLASSES*NUM_SAMPLES);

gen_rand_data(labs, feats);
//gen_rand_data(labs, feats);
read_data(labs, feats);

// Create train labels
CMulticlassSOLabels* labels = new CMulticlassSOLabels(labs);
Expand All @@ -82,11 +107,20 @@ int main(int argc, char ** argv)
CHingeLoss* loss = new CHingeLoss();

// Create SO-SVM
CPrimalMosekSOSVM* sosvm = new CPrimalMosekSOSVM(model, loss, labels, features);
CPrimalMosekSOSVM* sosvm = new CPrimalMosekSOSVM(model, loss, labels);
CDualLibQPBMSOSVM* bundle = new CDualLibQPBMSOSVM(model, loss, labels, 1000);
bundle->set_verbose(false);
SG_REF(sosvm);
SG_REF(bundle);

CTime start;
float64_t t1;
sosvm->train();
SG_SPRINT(">>>> PrimalMosekSOSVM trained in %9.4f\n", (t1 = start.cur_time_diff(false)));
bundle->train();
SG_SPRINT(">>>> BMRM trained in %9.4f\n", start.cur_time_diff(false)-t1);
CStructuredLabels* out = CStructuredLabels::obtain_from_generic(sosvm->apply());
CStructuredLabels* bout = CStructuredLabels::obtain_from_generic(bundle->apply());

// Create liblinear svm classifier with L2-regularized L2-loss
CLibLinear* svm = new CLibLinear(L2R_L2LOSS_SVC);
Expand Down Expand Up @@ -127,16 +161,18 @@ int main(int argc, char ** argv)
SG_REF(multiclass_evaluator);

SG_SPRINT("SO-SVM: %5.2f%\n", 100.0*structured_evaluator->evaluate(out, labels));
SG_SPRINT("BMRM: %5.2f%\n", 100.0*structured_evaluator->evaluate(bout, labels));
SG_SPRINT("MC: %5.2f%\n", 100.0*multiclass_evaluator->evaluate(mout, mlabels));

// Free memory
SG_UNREF(multiclass_evaluator);
SG_UNREF(structured_evaluator);
SG_UNREF(mout);
SG_UNREF(mc_svm);
SG_UNREF(bundle);
SG_UNREF(sosvm);
SG_UNREF(bout);
SG_UNREF(out);

exit_shogun();

return 0;
Expand Down
1 change: 0 additions & 1 deletion examples/undocumented/libshogun/so_multiclass_BMRM.cpp
Expand Up @@ -139,7 +139,6 @@ int main(int argc, char * argv[])
model,
loss,
labels,
features,
lambda);
SG_REF(sosvm);

Expand Down
25 changes: 22 additions & 3 deletions src/shogun/structure/MulticlassModel.cpp
Expand Up @@ -81,11 +81,13 @@ CResultSet* CMulticlassModel::argmax(
// Find the class that gives the maximum score

float64_t score = 0, ypred = 0;
float64_t max_score = df->dense_dot(feat_idx, w.vector, feats_dim);
float64_t max_score = -CMath::INFTY;

for ( int32_t c = 1 ; c < m_num_classes ; ++c )
for ( int32_t c = 0 ; c < m_num_classes ; ++c )
{
score = df->dense_dot(feat_idx, w.vector+c*feats_dim, feats_dim);
if ( training )
score += delta_loss(feat_idx, c);

if ( score > max_score )
{
Expand Down Expand Up @@ -119,7 +121,24 @@ float64_t CMulticlassModel::delta_loss(CStructuredData* y1, CStructuredData* y2)
ASSERT(rn1 != NULL);
ASSERT(rn2 != NULL);

return ( rn1->value == rn2->value ) ? 0 : 1;
return delta_loss(rn1->value, rn2->value);
}

float64_t CMulticlassModel::delta_loss(int32_t y1_idx, float64_t y2)
{
REQUIRE(y1_idx >= 0 || y1_idx < m_labels->get_num_labels(),
"The label index must be inside [0, num_labels-1]\n");

CRealNumber* rn1 = CRealNumber::obtain_from_generic(m_labels->get_label(y1_idx));
float64_t ret = delta_loss(rn1->value, y2);
SG_UNREF(rn1);

return ret;
}

float64_t CMulticlassModel::delta_loss(float64_t y1, float64_t y2)
{
return (y1 == y2) ? 0 : 1;
}

void CMulticlassModel::init_opt(
Expand Down
4 changes: 4 additions & 0 deletions src/shogun/structure/MulticlassModel.h
Expand Up @@ -133,6 +133,10 @@ class CMulticlassModel : public CStructuredModel
private:
void init();

/** Different flavours of the delta_loss that become handy */
float64_t delta_loss(float64_t y1, float64_t y2);
float64_t delta_loss(int32_t y1_idx, float64_t y2);

private:
/** number of classes */
int32_t m_num_classes;
Expand Down
4 changes: 2 additions & 2 deletions src/shogun/structure/StructuredModel.cpp
Expand Up @@ -98,8 +98,8 @@ SGVector< float64_t > CStructuredModel::get_joint_feature_vector(

float64_t CStructuredModel::delta_loss(int32_t ytrue_idx, CStructuredData* ypred)
{
if ( ytrue_idx < 0 || ytrue_idx >= m_labels->get_num_labels() )
SG_ERROR("The label index must be inside [0, num_labels-1]\n");
REQUIRE(ytrue_idx >= 0 || ytrue_idx < m_labels->get_num_labels(),
"The label index must be inside [0, num_labels-1]\n");

CStructuredData* ytrue = m_labels->get_label(ytrue_idx);
float64_t ret = delta_loss(ytrue, ypred);
Expand Down

0 comments on commit 8cec5d0

Please sign in to comment.