Skip to content

Commit

Permalink
Added subset support for multitask algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
lisitsyn committed Jul 27, 2012
1 parent 57d6371 commit bea8e08
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 28 deletions.
5 changes: 5 additions & 0 deletions src/shogun/features/Features.cpp
Expand Up @@ -366,6 +366,11 @@ void CFeatures::remove_all_subsets()
subset_changed_post();
}

CSubsetStack* CFeatures::get_subset_stack()
{
return m_subset_stack;
}

CFeatures* CFeatures::copy_subset(SGVector<index_t> indices)
{
SG_ERROR("%s::copy_subset(): copy_subset and therefore model storage of "
Expand Down
2 changes: 2 additions & 0 deletions src/shogun/features/Features.h
Expand Up @@ -252,6 +252,8 @@ class CFeatures : public CSGObject
* Calls subset_changed_post() afterwards */
virtual void remove_all_subsets();

virtual CSubsetStack* get_subset_stack();

/** method may be overwritten to update things that depend on subset */
virtual void subset_changed_post() {}

Expand Down
3 changes: 3 additions & 0 deletions src/shogun/features/Subset.h
Expand Up @@ -43,6 +43,9 @@ class CSubset: public CSGObject
/** @return name of the SGSerializable */
inline const char* get_name() const { return "Subset"; }

/** get subset indices */
SGVector<index_t> get_subset_idx() const { return m_subset_idx; }

private:
void init();

Expand Down
2 changes: 2 additions & 0 deletions src/shogun/features/SubsetStack.h
Expand Up @@ -70,6 +70,8 @@ class CSubsetStack: public CSGObject
return m_active_subsets_stack->get_num_elements();
}

CSubset* get_last_subset() const { return m_active_subset; }

/** returns the corresponding real index of a subset index
* Maps through all added subsets in stack.
*
Expand Down
19 changes: 2 additions & 17 deletions src/shogun/lib/malsar/malsar_low_rank.cpp
Expand Up @@ -38,22 +38,6 @@ malsar_result_t malsar_low_rank(
// initialize weight vector and bias for each task
MatrixXd Ws = MatrixXd::Zero(n_feats, n_tasks);
VectorXd Cs = VectorXd::Zero(n_tasks);
for (task=0; task<n_tasks; task++)
{
int n_pos = 0;
int n_neg = 0;
SGVector<index_t> task_idx = options.tasks_indices[task];
for (int i=0; i<task_idx.vlen; i++)
{
if (y[task_idx[i]] > 0)
n_pos++;
else
n_neg++;
}
SG_SDEBUG("There are %d positive and %d negative examples in task %d\n",n_pos,n_neg,task);
Cs[task] = CMath::log(double(n_pos)/n_neg);
}

MatrixXd Wz=Ws, Wzp=Ws, Wz_old=Ws, delta_Wzp=Ws, gWs=Ws;
VectorXd Cz=Cs, Czp=Cs, Cz_old=Cs, delta_Czp=Cs, gCs=Cs;

Expand Down Expand Up @@ -131,7 +115,7 @@ malsar_result_t malsar_low_rank(
int n_task_vecs = task_idx.vlen;
for (int i=0; i<n_task_vecs; i++)
{
double aa = -y[task_idx[i]]*(features->dense_dot(task_idx[i], Wzp.col(task).data(), n_feats)+Cs[task]);
double aa = -y[task_idx[i]]*(features->dense_dot(task_idx[i], Wzp.col(task).data(), n_feats)+Czp[task]);
double bb = CMath::max(aa,0.0);

Fzp += (CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb)/n_task_vecs;
Expand Down Expand Up @@ -181,6 +165,7 @@ malsar_result_t malsar_low_rank(
obj += rho*svd.singularValues().sum();
internal::set_is_malloc_allowed(false);


// check if process should be terminated
switch (options.termination)
{
Expand Down
Expand Up @@ -71,6 +71,7 @@ bool CMultitaskClusteredLogisticRegression::train_machine(CFeatures* data)

ASSERT(features);
ASSERT(m_labels);
ASSERT(m_task_relation);

SGVector<float64_t> y(m_labels->get_num_labels());
for (int32_t i=0; i<y.vlen; i++)
Expand All @@ -83,6 +84,8 @@ bool CMultitaskClusteredLogisticRegression::train_machine(CFeatures* data)
options.n_tasks = ((CTaskGroup*)m_task_relation)->get_num_tasks();
options.tasks_indices = ((CTaskGroup*)m_task_relation)->get_tasks_indices();
options.n_clusters = m_num_clusters;
SGVector<index_t>* subset_tasks_indices = get_subset_tasks_indices();
options.tasks_indices = subset_tasks_indices;

#ifdef HAVE_EIGEN3
malsar_result_t model = malsar_clustered(
Expand All @@ -95,8 +98,10 @@ bool CMultitaskClusteredLogisticRegression::train_machine(CFeatures* data)
m_tasks_w = SGMatrix<float64_t>(((CDotFeatures*)features)->get_dim_feature_space(), options.n_tasks);
m_tasks_c = SGVector<float64_t>(options.n_tasks);
#endif

ASSERT(m_task_relation);

for (int32_t i=0; i<options.n_tasks; i++)
subset_tasks_indices[i].~SGVector<index_t>();
SG_FREE(subset_tasks_indices);

return true;
}
Expand Down
Expand Up @@ -50,6 +50,7 @@ bool CMultitaskL1L2LogisticRegression::train_machine(CFeatures* data)

ASSERT(features);
ASSERT(m_labels);
ASSERT(m_task_relation);

SGVector<float64_t> y(m_labels->get_num_labels());
for (int32_t i=0; i<y.vlen; i++)
Expand All @@ -60,7 +61,8 @@ bool CMultitaskL1L2LogisticRegression::train_machine(CFeatures* data)
options.tolerance = m_tolerance;
options.max_iter = m_max_iter;
options.n_tasks = ((CTaskGroup*)m_task_relation)->get_num_tasks();
options.tasks_indices = ((CTaskGroup*)m_task_relation)->get_tasks_indices();
SGVector<index_t>* subset_tasks_indices = get_subset_tasks_indices();
options.tasks_indices = subset_tasks_indices;

#ifdef HAVE_EIGEN3
malsar_result_t model = malsar_joint_feature_learning(
Expand All @@ -73,9 +75,11 @@ bool CMultitaskL1L2LogisticRegression::train_machine(CFeatures* data)
m_tasks_w = SGMatrix<float64_t>(((CDotFeatures*)features)->get_dim_feature_space(), options.n_tasks);
m_tasks_c = SGVector<float64_t>(options.n_tasks);
#endif

ASSERT(m_task_relation);

for (int32_t i=0; i<options.n_tasks; i++)
subset_tasks_indices[i].~SGVector<index_t>();
SG_FREE(subset_tasks_indices);

return true;
}

Expand Down
41 changes: 41 additions & 0 deletions src/shogun/transfer/multitask/MultitaskLogisticRegression.cpp
Expand Up @@ -11,6 +11,11 @@
#include <shogun/lib/slep/slep_solver.h>
#include <shogun/lib/slep/slep_options.h>

#include <map>
#include <vector>

using namespace std;

namespace shogun
{

Expand Down Expand Up @@ -137,4 +142,40 @@ bool CMultitaskLogisticRegression::train_machine(CFeatures* data)
return true;
}

SGVector<index_t>* CMultitaskLogisticRegression::get_subset_tasks_indices()
{
int n_tasks = ((CTaskGroup*)m_task_relation)->get_num_tasks();
SGVector<index_t>* tasks_indices = ((CTaskGroup*)m_task_relation)->get_tasks_indices();

CSubsetStack* sstack = features->get_subset_stack();
map<index_t,index_t> subset_inv_map = map<index_t,index_t>();
for (int32_t i=0; i<sstack->get_size(); i++)
subset_inv_map[sstack->subset_idx_conversion(i)] = i;

SGVector<index_t>* subset_tasks_indices = SG_MALLOC(SGVector<index_t>, n_tasks);
for (int32_t i=0; i<n_tasks; i++)
{
new (&subset_tasks_indices[i]) SGVector<index_t>();
SGVector<index_t> task = tasks_indices[i];
//task.display_vector("task");
vector<index_t> cutted = vector<index_t>();
for (int32_t j=0; j<task.vlen; j++)
{
if (subset_inv_map.count(task[j]))
cutted.push_back(subset_inv_map[task[j]]);
}
SGVector<index_t> cutted_task(cutted.size());
for (int32_t j=0; j<cutted_task.vlen; j++)
cutted_task[j] = cutted[j];
//cutted_task.display_vector("cutted");
subset_tasks_indices[i] = cutted_task;
}
for (int32_t i=0; i<n_tasks; i++)
tasks_indices[i].~SGVector<index_t>();
SG_FREE(tasks_indices);

return subset_tasks_indices;
}


}
3 changes: 3 additions & 0 deletions src/shogun/transfer/multitask/MultitaskLogisticRegression.h
Expand Up @@ -74,6 +74,9 @@ class CMultitaskLogisticRegression : public CSLEPMachine
/** train machine */
virtual bool train_machine(CFeatures* data=NULL);

/** subset mapped task indices */
SGVector<index_t>* get_subset_tasks_indices();

private:

/** register parameters */
Expand Down
Expand Up @@ -45,6 +45,7 @@ bool CMultitaskTraceLogisticRegression::train_machine(CFeatures* data)

ASSERT(features);
ASSERT(m_labels);
ASSERT(m_task_relation);

SGVector<float64_t> y(m_labels->get_num_labels());
for (int32_t i=0; i<y.vlen; i++)
Expand All @@ -56,11 +57,8 @@ bool CMultitaskTraceLogisticRegression::train_machine(CFeatures* data)
options.max_iter = m_max_iter;
options.n_tasks = ((CTaskGroup*)m_task_relation)->get_num_tasks();
options.tasks_indices = ((CTaskGroup*)m_task_relation)->get_tasks_indices();

SG_DEBUG("Starting malsar solver\n");
SG_DEBUG("N tasks = %d \n", options.n_tasks);
for (int32_t i=0; i<options.n_tasks; i++)
options.tasks_indices[i].display_vector();
SGVector<index_t>* subset_tasks_indices = get_subset_tasks_indices();
options.tasks_indices = subset_tasks_indices;

#ifdef HAVE_EIGEN3
malsar_result_t model = malsar_low_rank(
Expand All @@ -74,7 +72,9 @@ bool CMultitaskTraceLogisticRegression::train_machine(CFeatures* data)
m_tasks_c = SGVector<float64_t>(options.n_tasks);
#endif

ASSERT(m_task_relation);
for (int32_t i=0; i<options.n_tasks; i++)
subset_tasks_indices[i].~SGVector<index_t>();
SG_FREE(subset_tasks_indices);

return true;
}
Expand Down

0 comments on commit bea8e08

Please sign in to comment.