ShareBoost.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2012 Chiyuan Zhang
00008  * Copyright (C) 2012 Chiyuan Zhang
00009  */
00010 
00011 #include <algorithm>
00012 
00013 #include <shogun/lib/Time.h>
00014 #include <shogun/mathematics/Math.h>
00015 #include <shogun/multiclass/ShareBoost.h>
00016 #include <shogun/multiclass/ShareBoostOptimizer.h>
00017 #include <shogun/features/DenseSubsetFeatures.h>
00018 #include <shogun/labels/RegressionLabels.h>
00019 
00020 using namespace shogun;
00021 
00022 CShareBoost::CShareBoost()
00023     :CLinearMulticlassMachine(), m_nonzero_feas(0)
00024 {
00025     init_sb_params();
00026 }
00027 
00028 CShareBoost::CShareBoost(CDenseFeatures<float64_t> *features, CMulticlassLabels *labs, int32_t num_nonzero_feas)
00029     :CLinearMulticlassMachine(new CMulticlassOneVsRestStrategy(), features, NULL, labs), m_nonzero_feas(num_nonzero_feas)
00030 {
00031     init_sb_params();
00032 }
00033 
00034 void CShareBoost::init_sb_params()
00035 {
00036     SG_ADD(&m_nonzero_feas, "m_nonzero_feas", "Number of non-zero features", MS_NOT_AVAILABLE);
00037 }
00038 
00039 SGVector<int32_t> CShareBoost::get_activeset()
00040 {
00041     return m_activeset.clone();
00042 }
00043 
00044 bool CShareBoost::train_machine(CFeatures* data)
00045 {
00046     if (data)
00047         set_features(data);
00048 
00049     if (m_features == NULL)
00050         SG_ERROR("No features given for training\n");
00051     if (m_labels == NULL)
00052         SG_ERROR("No labels given for training\n");
00053 
00054     if (m_nonzero_feas <= 0)
00055         SG_ERROR("Set a valid (> 0) number of non-zero features to seek before training\n");
00056     if (m_nonzero_feas >= dynamic_cast<CDenseFeatures<float64_t>*>(m_features)->get_num_features())
00057         SG_ERROR("It doesn't make sense to use ShareBoost with num non-zero features >= num features in the data\n");
00058 
00059     m_fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features)->get_feature_matrix();
00060     m_rho = SGMatrix<float64_t>(m_multiclass_strategy->get_num_classes(), m_fea.num_cols);
00061     m_rho_norm = SGVector<float64_t>(m_fea.num_cols);
00062     m_pred = SGMatrix<float64_t>(m_fea.num_cols, m_multiclass_strategy->get_num_classes());
00063     m_pred.zero();
00064 
00065     m_activeset = SGVector<int32_t>(m_fea.num_rows);
00066     m_activeset.vlen = 0;
00067 
00068     m_machines->reset_array();
00069     for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
00070         m_machines->push_back(new CLinearMachine());
00071 
00072     CTime *timer = new CTime();
00073 
00074     float64_t t_compute_pred = 0; // t of 1st round is 0, since no pred to compute
00075     for (int32_t t=0; t < m_nonzero_feas; ++t)
00076     {
00077         timer->start();
00078         compute_rho();
00079         int32_t i_fea = choose_feature();
00080         m_activeset.vector[m_activeset.vlen] = i_fea;
00081         m_activeset.vlen += 1;
00082         float64_t t_choose_feature = timer->cur_time_diff();
00083         timer->start();
00084         optimize_coefficients();
00085         float64_t t_optimize = timer->cur_time_diff();
00086 
00087         SG_SPRINT(" SB[round %03d]: (%8.4f + %8.4f) sec.\n", t,
00088                 t_compute_pred + t_choose_feature, t_optimize);
00089 
00090         timer->start();
00091         compute_pred();
00092         t_compute_pred = timer->cur_time_diff();
00093     }
00094 
00095     SG_UNREF(timer);
00096 
00097     // release memory
00098     m_fea = SGMatrix<float64_t>();
00099     m_rho = SGMatrix<float64_t>();
00100     m_rho_norm = SGVector<float64_t>();
00101     m_pred = SGMatrix<float64_t>();
00102 
00103     return true;
00104 }
00105 
00106 void CShareBoost::compute_pred()
00107 {
00108     CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features);
00109     CDenseSubsetFeatures<float64_t> *subset_fea = new CDenseSubsetFeatures<float64_t>(fea, m_activeset);
00110     SG_REF(subset_fea);
00111     for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
00112     {
00113         CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
00114         CRegressionLabels *lab = machine->apply_regression(subset_fea);
00115         SGVector<float64_t> lab_raw = lab->get_labels();
00116         std::copy(lab_raw.vector, lab_raw.vector + lab_raw.vlen, m_pred.get_column_vector(i));
00117         SG_UNREF(machine);
00118         SG_UNREF(lab);
00119     }
00120     SG_UNREF(subset_fea);
00121 }
00122 
00123 void CShareBoost::compute_pred(const float64_t *W)
00124 {
00125     int32_t w_len = m_activeset.vlen;
00126 
00127     for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
00128     {
00129         CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
00130         SGVector<float64_t> w(w_len);
00131         std::copy(W + i*w_len, W + (i+1)*w_len, w.vector);
00132         machine->set_w(w);
00133         SG_UNREF(machine);
00134     }
00135     compute_pred();
00136 }
00137 
00138 void CShareBoost::compute_rho()
00139 {
00140     CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
00141     for (int32_t i=0; i < m_rho.num_rows; ++i)
00142     { // i loop classes
00143         for (int32_t j=0; j < m_rho.num_cols; ++j)
00144         { // j loop samples
00145             int32_t label = lab->get_int_label(j);
00146 
00147             m_rho(i,j) = CMath::exp((label == i) - m_pred(j, label) + m_pred(j, i));
00148         }
00149     }
00150 
00151     // normalize
00152     for (int32_t j=0; j < m_rho.num_cols; ++j)
00153     {
00154         m_rho_norm[j] = 0;
00155         for (int32_t i=0; i < m_rho.num_rows; ++i)
00156             m_rho_norm[j] += m_rho(i,j);
00157     }
00158 }
00159 
00160 int32_t CShareBoost::choose_feature()
00161 {
00162     SGVector<float64_t> l1norm(m_fea.num_rows);
00163     for (int32_t j=0; j < m_fea.num_rows; ++j)
00164     {
00165         if (std::find(&m_activeset[0], &m_activeset[m_activeset.vlen], j) !=
00166                 &m_activeset[m_activeset.vlen])
00167         {
00168             l1norm[j] = 0;
00169         }
00170         else
00171         {
00172             l1norm[j] = 0;
00173             CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
00174             for (int32_t k=0; k < m_multiclass_strategy->get_num_classes(); ++k)
00175             {
00176                 float64_t abssum = 0;
00177                 for (int32_t ii=0; ii < m_fea.num_cols; ++ii)
00178                 {
00179                     abssum += m_fea(j, ii)*(m_rho(k, ii)/m_rho_norm[ii] - 
00180                             (j == lab->get_int_label(ii)));
00181                 }
00182                 l1norm[j] += CMath::abs(abssum);
00183             }
00184             l1norm[j] /= m_fea.num_cols;
00185         }
00186     }
00187 
00188     return SGVector<float64_t>::arg_max(l1norm.vector, 1, l1norm.vlen);
00189 }
00190 
00191 void CShareBoost::optimize_coefficients()
00192 {
00193     ShareBoostOptimizer optimizer(this, false);
00194     optimizer.optimize();
00195 }
00196 
00197 void CShareBoost::set_features(CFeatures *f)
00198 {
00199     CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(f);
00200     if (fea == NULL)
00201         SG_ERROR("Require DenseFeatures<float64_t>\n");
00202     CLinearMulticlassMachine::set_features(fea);
00203 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation