SHOGUN
v3.2.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/mathematics/Math.h> 00014 #include <shogun/optimization/lbfgs/lbfgs.h> 00015 #include <shogun/multiclass/ShareBoostOptimizer.h> 00016 00017 using namespace shogun; 00018 00019 void ShareBoostOptimizer::optimize() 00020 { 00021 int32_t N = m_sb->m_multiclass_strategy->get_num_classes() * m_sb->m_activeset.vlen; 00022 float64_t *W = SG_CALLOC(float64_t, N); // should use this function, if sse is enabled for liblbfgs 00023 float64_t objval; 00024 lbfgs_parameter_t param; 00025 lbfgs_parameter_init(¶m); 00026 00027 std::fill(W, W+N, 0); 00028 00029 lbfgs_progress_t progress = m_verbose ? &ShareBoostOptimizer::lbfgs_progress : NULL; 00030 00031 lbfgs(N, W, &objval, &ShareBoostOptimizer::lbfgs_evaluate, progress, this, ¶m); 00032 00033 int32_t w_len = m_sb->m_activeset.vlen; 00034 for (int32_t i=0; i < m_sb->m_multiclass_strategy->get_num_classes(); ++i) 00035 { 00036 CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_sb->m_machines->get_element(i)); 00037 SGVector<float64_t> w(w_len); 00038 std::copy(W + i*w_len, W + (i+1)*w_len, w.vector); 00039 machine->set_w(w); 00040 SG_UNREF(machine); 00041 } 00042 00043 SG_FREE(W); 00044 } 00045 00046 float64_t ShareBoostOptimizer::lbfgs_evaluate(void *userdata, const float64_t *W, 00047 float64_t *grad, const int32_t n, const float64_t step) 00048 { 00049 ShareBoostOptimizer *optimizer = static_cast<ShareBoostOptimizer *>(userdata); 00050 00051 optimizer->m_sb->compute_pred(W); 00052 optimizer->m_sb->compute_rho(); 00053 00054 int32_t m = optimizer->m_sb->m_activeset.vlen; 00055 int32_t k = optimizer->m_sb->m_multiclass_strategy->get_num_classes(); 00056 00057 SGMatrix<float64_t> fea = optimizer->m_sb->m_fea; 00058 CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(optimizer->m_sb->m_labels); 00059 00060 // compute gradient 00061 for (int32_t i=0; i < m; ++i) 00062 { 00063 for (int32_t j=0; j < k; ++j) 00064 { 00065 int32_t idx = j*m + i; 00066 float64_t g=0; 00067 for (int32_t ii=0; ii < fea.num_cols; ++ii) 00068 g += fea(optimizer->m_sb->m_activeset[i], ii) * 00069 (optimizer->m_sb->m_rho(j,ii)/optimizer->m_sb->m_rho_norm[ii] - 00070 (j == lab->get_int_label(ii))); 00071 g /= fea.num_cols; 00072 grad[idx] = g; 00073 } 00074 } 00075 00076 // compute objective function 00077 float64_t objval = 0; 00078 for (int32_t ii=0; ii < fea.num_cols; ++ii) 00079 { 00080 objval += CMath::log(optimizer->m_sb->m_rho_norm[ii]); 00081 } 00082 objval /= fea.num_cols; 00083 00084 return objval; 00085 } 00086 00087 int ShareBoostOptimizer::lbfgs_progress( 00088 void *instance, 00089 const float64_t *x, 00090 const float64_t *g, 00091 const float64_t fx, 00092 const float64_t xnorm, 00093 const float64_t gnorm, 00094 const float64_t step, 00095 int n, 00096 int k, 00097 int ls 00098 ) 00099 { 00100 if (k != 1 && k % 100 != 0) 00101 return 0; 00102 00103 SG_SPRINT("Iteration %d:\n", k) 00104 SG_SPRINT(" fx = %f, x[0] = %f, x[1] = %f\n", fx, x[0], x[1]) 00105 SG_SPRINT(" xnorm = %f, gnorm = %f, step = %f\n", xnorm, gnorm, step) 00106 SG_SPRINT("\n") 00107 return 0; 00108 }