Skip to content

Commit

Permalink
Some improvement for multiclass confidences
Browse files Browse the repository at this point in the history
- Changed the way confidences are stored (array of sgvectors -> sgmatrix)

- Added a unit test for confidences
  • Loading branch information
lisitsyn authored and karlnapf committed Mar 14, 2013
1 parent 934d00f commit 5fc7151
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 21 deletions.
39 changes: 23 additions & 16 deletions src/shogun/labels/MulticlassLabels.cpp
Expand Up @@ -6,42 +6,50 @@ using namespace shogun;

CMulticlassLabels::CMulticlassLabels() : CDenseLabels()
{
m_multiclass_confidences = NULL;
m_num_multiclass_confidences = 0;
}

CMulticlassLabels::CMulticlassLabels(int32_t num_labels) : CDenseLabels(num_labels)
{
m_multiclass_confidences = SG_MALLOC(SGVector<float64_t>, num_labels);
m_num_multiclass_confidences = num_labels;
}

CMulticlassLabels::CMulticlassLabels(const SGVector<float64_t> src) : CDenseLabels()
{
set_labels(src);
m_multiclass_confidences = NULL;
m_num_multiclass_confidences = 0;
}

CMulticlassLabels::CMulticlassLabels(CFile* loader) : CDenseLabels(loader)
{
m_multiclass_confidences = NULL;
m_num_multiclass_confidences = 0;
}

CMulticlassLabels::~CMulticlassLabels()
{
SG_FREE(m_multiclass_confidences);
}

void CMulticlassLabels::set_multiclass_confidences(int32_t i, SGVector<float64_t> confidences)
{
m_multiclass_confidences[i] = confidences;
REQUIRE(confidences.size()==m_multiclass_confidences.num_rows,"Length of confidences should match size of the matrix");
for (index_t j=0; j<confidences.size(); j++)
{
m_multiclass_confidences(j,i) = confidences[j];
}
}

SGVector<float64_t> CMulticlassLabels::get_multiclass_confidences(int32_t i)
{
return m_multiclass_confidences[i];
SGVector<float64_t> confs(m_multiclass_confidences.num_rows);
for (index_t j=0; j<confs.size(); j++)
{
confs[j] = m_multiclass_confidences(j,i);
}
return confs;
}

void CMulticlassLabels::allocate_confidences_for(int32_t n_classes)
{
int32_t n_labels = m_labels.size();
REQUIRE(n_labels!=0,"There should be labels to store confidences");

m_multiclass_confidences = SGMatrix<float64_t>(n_classes,n_labels);
}

CMulticlassLabels* CMulticlassLabels::obtain_from_generic(CLabels* base_labels)
Expand Down Expand Up @@ -82,18 +90,17 @@ CBinaryLabels* CMulticlassLabels::get_binary_for_class(int32_t i)
SGVector<float64_t> binary_labels(get_num_labels());

bool use_confidences = false;
if (m_num_multiclass_confidences != 0)
if ((m_multiclass_confidences.num_rows != 0) && (m_multiclass_confidences.num_cols != 0))
{
if (m_multiclass_confidences[i].size())
use_confidences = true;
use_confidences = true;
}
if (use_confidences)
{
for (int32_t k=0; k<binary_labels.vlen; k++)
{
SGVector<float64_t> confs = m_multiclass_confidences[k];
int32_t label = get_int_label(k);
binary_labels[k] = label == i ? confs[label] : -confs[label];
float64_t confidence = m_multiclass_confidences(label,k);
binary_labels[k] = label == i ? confidence : -confidence;
}
}
else
Expand Down
17 changes: 12 additions & 5 deletions src/shogun/labels/MulticlassLabels.h
Expand Up @@ -107,23 +107,30 @@ class CMulticlassLabels : public CDenseLabels
*/
SGVector<float64_t> get_multiclass_confidences(int32_t i);

/** sets multiclass confidences
/** sets multiclass confidences. to prepare labels
* for storing multiclass confidences call
* @ref allocate_confidences_for
*
* @param i index
* @param confidences confidences to be set for ith result
*/
void set_multiclass_confidences(int32_t i, SGVector<float64_t> confidences);

/** allocates matrix to store confidences. should always
* be called before setting confidences with
* @ref set_multiclass_confidences
*
* @param n_classes number of classes
*/
void allocate_confidences_for(int32_t n_classes);

/** @return object name */
virtual const char* get_name() const { return "MulticlassLabels"; }

protected:

/** multiclass confidences */
SGVector<float64_t>* m_multiclass_confidences;

/** number of multiclass confidences */
int32_t m_num_multiclass_confidences;
SGMatrix<float64_t> m_multiclass_confidences;
};
}
#endif
2 changes: 2 additions & 0 deletions src/shogun/machine/MulticlassMachine.cpp
Expand Up @@ -112,6 +112,8 @@ CMulticlassLabels* CMulticlassMachine::apply_multiclass(CFeatures* data)
SG_ERROR("num_machines = %d, did you train your machine?", num_machines)

CMulticlassLabels* result=new CMulticlassLabels(num_vectors);
result->allocate_confidences_for(m_multiclass_strategy->get_num_classes());

CBinaryLabels** outputs=SG_MALLOC(CBinaryLabels*, num_machines);

for (int32_t i=0; i < num_machines; ++i)
Expand Down
46 changes: 46 additions & 0 deletions tests/unit/labels/MulticlassLabels_unittest.cc
@@ -0,0 +1,46 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Written (W) 2013 Sergey Lisitsyn
*/

#include <shogun/base/init.h>
#include <shogun/labels/MulticlassLabels.h>
#include <gtest/gtest.h>

using namespace shogun;

TEST(MulticlassLabelsTest,confidences)
{
const int n_labels = 3;
const int n_classes = 4;

CMulticlassLabels* labels = new CMulticlassLabels(n_labels);

ASSERT_NO_THROW(labels->allocate_confidences_for(n_classes));

for (int i=0; i<n_labels; i++)
ASSERT_EQ(labels->get_multiclass_confidences(i).size(),n_classes);

for (int i=0; i<n_labels; i++)
{
SGVector<float64_t> confs(n_classes);
confs.zero();
confs[i%n_classes] = 1.0;

labels->set_multiclass_confidences(i,confs);

SGVector<float64_t> obtained_confs = labels->get_multiclass_confidences(i);
for (int j=0; j<n_classes; j++)
{
if (j==i%n_classes)
ASSERT_NEAR(obtained_confs[j],1.0,1e-9);
else
ASSERT_NEAR(obtained_confs[j],0.0,1e-9);
}
}
SG_UNREF(labels);
}

0 comments on commit 5fc7151

Please sign in to comment.