SHOGUN
v2.0.0
|
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 }