Skip to content

Commit

Permalink
Redesign LatentLabels This way LatentLabels not only store actually t…
Browse files Browse the repository at this point in the history
…he h_i (latent labels) but as well as in a general way store the actual y_i (labels).
  • Loading branch information
vigsterkr committed Aug 15, 2012
1 parent f7116ba commit 5689042
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 38 deletions.
6 changes: 5 additions & 1 deletion examples/undocumented/libshogun/classifier_latent_svm.cpp
Expand Up @@ -102,6 +102,8 @@ static void read_dataset(char* fname, CLatentFeatures*& feats, CLatentLabels*& l
labels = new CLatentLabels(num_examples);
SG_REF(labels);

CBinaryLabels* ys = new CBinaryLabels(num_examples);

feats = new CLatentFeatures(num_examples);
SG_REF(feats);

Expand All @@ -122,7 +124,7 @@ static void read_dataset(char* fname, CLatentFeatures*& feats, CLatentLabels*& l
label = (atoi(last_pchar) % 2 == 0) ? 1 : -1;
pchar++;

if (labels->set_label(i, label) == false)
if (ys->set_label(i, label) == false)
SG_SERROR("Couldn't set label for element %d\n", i);

last_pchar = pchar;
Expand Down Expand Up @@ -166,6 +168,8 @@ static void read_dataset(char* fname, CLatentFeatures*& feats, CLatentLabels*& l
}
fclose(fd);

labels->set_labels(ys);

SG_SDONE();
}

Expand Down
2 changes: 1 addition & 1 deletion src/shogun/classifier/svm/SVMOcas.cpp
Expand Up @@ -58,7 +58,7 @@ bool CSVMOcas::train_machine(CFeatures* data)
SG_DEBUG("use_bias = %i\n", get_bias_enabled()) ;

ASSERT(m_labels);
ASSERT(m_labels->get_label_type() == LT_BINARY || m_labels->get_label_type() == LT_LATENT);
ASSERT(m_labels->get_label_type() == LT_BINARY);
if (data)
{
if (!data->has_property(FP_DOT))
Expand Down
47 changes: 42 additions & 5 deletions src/shogun/labels/LatentLabels.cpp
Expand Up @@ -13,28 +13,41 @@
using namespace shogun;

CLatentLabels::CLatentLabels()
: CBinaryLabels()
: CLabels()
{
init();
}

CLatentLabels::CLatentLabels(int32_t num_labels)
: CBinaryLabels(num_labels)
CLatentLabels::CLatentLabels(int32_t num_samples)
: CLabels()
{
init();
m_latent_labels = new CDynamicObjectArray(num_labels);
m_latent_labels = new CDynamicObjectArray(num_samples);
SG_REF(m_latent_labels);
}

CLatentLabels::CLatentLabels(CLabels* labels)
: CLabels()
{
init();
m_labels = labels;
SG_REF(m_labels);
m_latent_labels = new CDynamicObjectArray(m_labels->get_num_labels());
SG_REF(m_latent_labels);
}

CLatentLabels::~CLatentLabels()
{
SG_UNREF(m_latent_labels);
SG_UNREF(m_labels);
}

void CLatentLabels::init()
{
SG_ADD((CSGObject**) &m_latent_labels, "m_labels", "The labels", MS_NOT_AVAILABLE);
SG_ADD((CSGObject**) &m_latent_labels, "m_latent_labels", "The latent labels", MS_NOT_AVAILABLE);
SG_ADD((CSGObject**) &m_labels, "m_labels", "The labels", MS_NOT_AVAILABLE);
m_latent_labels = NULL;
m_labels = NULL;
}

CDynamicObjectArray* CLatentLabels::get_latent_labels() const
Expand Down Expand Up @@ -87,3 +100,27 @@ CLatentLabels* CLatentLabels::obtain_from_generic(CLabels* base_labels)
return NULL;
}

int32_t CLatentLabels::get_num_labels()
{
if (!m_latent_labels || !m_labels)
return 0;
int32_t num_labels = m_latent_labels->get_num_elements();

ASSERT(num_labels == m_labels->get_num_labels());

return num_labels;
}

void CLatentLabels::set_labels(CLabels* labels)
{
SG_UNREF(m_labels);
SG_REF(labels);
m_labels = labels;
}

CLabels* CLatentLabels::get_labels() const
{
SG_REF(m_labels);
return m_labels;
}

34 changes: 30 additions & 4 deletions src/shogun/labels/LatentLabels.h
Expand Up @@ -11,7 +11,7 @@
#ifndef __LATENTLABELS_H__
#define __LATENTLABELS_H__

#include <shogun/labels/BinaryLabels.h>
#include <shogun/labels/Labels.h>
#include <shogun/lib/Data.h>
#include <shogun/lib/DynamicObjectArray.h>

Expand All @@ -21,7 +21,7 @@ namespace shogun
* As latent labels always depends on the given application, this class
* only defines the API that the user has to implement for latent labels.
*/
class CLatentLabels : public CBinaryLabels
class CLatentLabels : public CLabels
{
public:
/** default ctor */
Expand All @@ -31,7 +31,13 @@ namespace shogun
*
* @param num_samples the number of labels
*/
CLatentLabels(int32_t num_labels);
CLatentLabels(int32_t num_samples);

/** constructor
*
* @param labels the (y_i) labels
*/
CLatentLabels(CLabels* labels);

/** destructor */
virtual ~CLatentLabels();
Expand Down Expand Up @@ -89,9 +95,29 @@ namespace shogun
*/
virtual const char* get_name() const { return "LatentLabels"; }

/** get the number of stored labels
*
* @return the number of labels
*/
virtual int32_t get_num_labels();

/** set labels
*
* @param labels the labels (y_i)
*/
void set_labels(CLabels* labels);

/** get the labels (y_i)
*
* @return the labels (y_i)
*/
CLabels* get_labels() const;

protected:
/** the vector of labels */
/** the of CData, the latent labels (h_i) */
CDynamicObjectArray* m_latent_labels;
/** the labels (y_i) */
CLabels* m_labels;

private:
/** initalize the values to default values */
Expand Down
5 changes: 4 additions & 1 deletion src/shogun/latent/LatentModel.cpp
Expand Up @@ -9,6 +9,7 @@
*/

#include <shogun/latent/LatentModel.h>
#include <shogun/labels/BinaryLabels.h>

using namespace shogun;

Expand Down Expand Up @@ -60,13 +61,15 @@ void CLatentModel::set_features(CLatentFeatures* feats)
void CLatentModel::argmax_h(const SGVector<float64_t>& w)
{
int32_t num = get_num_vectors();
CBinaryLabels* y = CBinaryLabels::obtain_from_generic(m_labels->get_labels());
ASSERT(num > 0);
ASSERT(num == m_labels->get_num_labels());


// argmax_h only for positive examples
for (int32_t i = 0; i < num; ++i)
{
if (m_labels->get_label(i) == 1)
if (y->get_label(i) == 1)
{
// infer h and set it for the argmax_h <w,psi(x,h)>
CData* latent_data = infer_latent_variable(w, i);
Expand Down
3 changes: 1 addition & 2 deletions src/shogun/latent/LatentSOSVM.cpp
Expand Up @@ -32,10 +32,9 @@ CLatentSOSVM::~CLatentSOSVM()
SG_UNREF(m_so_solver);
}

CLatentLabels* CLatentSOSVM::apply(CFeatures* data)
CLatentLabels* CLatentSOSVM::apply()
{


return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion src/shogun/latent/LatentSOSVM.h
Expand Up @@ -41,7 +41,7 @@ namespace shogun
* @param data (test)data to be classified
* @return classified labels
*/
virtual CLatentLabels* apply(CFeatures* data);
virtual CLatentLabels* apply();

void set_so_solver(CLinearStructuredOutputMachine* so);

Expand Down
35 changes: 32 additions & 3 deletions src/shogun/latent/LatentSVM.cpp
Expand Up @@ -29,13 +29,42 @@ CLatentSVM::~CLatentSVM()
{
}

CLatentLabels* CLatentSVM::apply()
{
if (!m_model)
SG_ERROR("LatentModel is not set!\n");

if (!features)
return NULL;

index_t num_examples = m_model->get_num_vectors();
CLatentLabels* hs = new CLatentLabels(num_examples);
CBinaryLabels* ys = new CBinaryLabels(num_examples);

for (index_t i = 0; i < num_examples; ++i)
{
/* find h for the example */
CData* h = m_model->infer_latent_variable(w, i);
hs->set_latent_label(i, h);
SGVector<float64_t> psi_feat = m_model->get_psi_feature_vector(i);

/* calculate and set y for the example */
float64_t y = w.dot(w.vector, psi_feat.vector, w.vlen);
ys->set_label(i, y);
}

hs->set_labels(ys);

return hs;
}

float64_t CLatentSVM::do_inner_loop(float64_t cooling_eps)
{
CLatentLabels* labels = m_model->get_labels();
CSVMOcas svm(m_C, features, labels);
CLabels* ys = m_model->get_labels()->get_labels();
CSVMOcas svm(m_C, features, ys);
svm.set_epsilon(cooling_eps);
svm.train();
SG_UNREF(labels);
SG_UNREF(ys);

/* copy the resulting w */
SGVector<float64_t> cur_w = svm.get_w();
Expand Down
8 changes: 8 additions & 0 deletions src/shogun/latent/LatentSVM.h
Expand Up @@ -44,6 +44,14 @@ namespace shogun

virtual ~CLatentSVM();

/** apply linear machine to all examples
*
* @return resulting labels
*/
virtual CLatentLabels* apply();

using CLinearLatentMachine::apply;

/** Returns the name of the SGSerializable instance.
*
* @return name of the SGSerializable
Expand Down
20 changes: 1 addition & 19 deletions src/shogun/machine/LinearLatentMachine.cpp
Expand Up @@ -44,10 +44,6 @@ CLinearLatentMachine::~CLinearLatentMachine()

CLatentLabels* CLinearLatentMachine::apply()
{
if (!features)
return NULL;

return NULL;
}

CLatentLabels* CLinearLatentMachine::apply(CFeatures* data)
Expand All @@ -57,22 +53,8 @@ CLatentLabels* CLinearLatentMachine::apply(CFeatures* data)

CLatentFeatures* lf = CLatentFeatures::obtain_from_generic(data);
m_model->set_features(lf);
index_t num_examples = m_model->get_num_vectors();
CLatentLabels* labels = new CLatentLabels(num_examples);

for (index_t i = 0; i < num_examples; ++i)
{
/* find h for the example */
CData* h = m_model->infer_latent_variable(w, i);
labels->set_latent_label(i, h);
SGVector<float64_t> psi_feat = m_model->get_psi_feature_vector(i);

/* calculate and set y for the example */
float64_t y = w.dot(w.vector, psi_feat.vector, w.vlen);
labels->set_label(i, y);
}

return labels;
return apply();
}

void CLinearLatentMachine::set_model(CLatentModel* latent_model)
Expand Down
2 changes: 1 addition & 1 deletion src/shogun/machine/LinearLatentMachine.h
Expand Up @@ -44,7 +44,7 @@ namespace shogun
*
* @return resulting labels
*/
virtual CLatentLabels* apply();
virtual CLatentLabels* apply() = 0;

/** apply linear machine to data
*
Expand Down

0 comments on commit 5689042

Please sign in to comment.