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 Viktor Gal 00008 * Copyright (C) 2012 Viktor Gal 00009 */ 00010 00011 #include <typeinfo> 00012 00013 #include <shogun/machine/LinearLatentMachine.h> 00014 #include <shogun/features/LatentFeatures.h> 00015 #include <shogun/features/DenseFeatures.h> 00016 00017 using namespace shogun; 00018 00019 CLinearLatentMachine::CLinearLatentMachine() 00020 : CLinearMachine() 00021 { 00022 init(); 00023 } 00024 00025 CLinearLatentMachine::CLinearLatentMachine(CLatentModel* model, float64_t C) 00026 : CLinearMachine() 00027 { 00028 init(); 00029 m_C= C; 00030 set_model(model); 00031 00032 index_t feat_dim = m_model->get_dim(); 00033 set_w(SGVector<float64_t> (feat_dim)); 00034 } 00035 00036 CLinearLatentMachine::~CLinearLatentMachine() 00037 { 00038 SG_UNREF(m_model); 00039 } 00040 00041 CLatentLabels* CLinearLatentMachine::apply_latent(CFeatures* data) 00042 { 00043 if (m_model == NULL) 00044 SG_ERROR("LatentModel is not set!\n"); 00045 00046 CLatentFeatures* lf = CLatentFeatures::obtain_from_generic(data); 00047 m_model->set_features(lf); 00048 00049 return apply_latent(); 00050 } 00051 00052 void CLinearLatentMachine::set_model(CLatentModel* latent_model) 00053 { 00054 ASSERT(latent_model != NULL); 00055 SG_UNREF(m_model); 00056 SG_REF(latent_model); 00057 m_model = latent_model; 00058 } 00059 00060 void CLinearLatentMachine::cache_psi_vectors() 00061 { 00062 set_features(m_model->get_psi_feature_vectors()); 00063 } 00064 00065 bool CLinearLatentMachine::train_machine(CFeatures* data) 00066 { 00067 if (m_model == NULL) 00068 SG_ERROR("LatentModel is not set!\n"); 00069 00070 SG_DEBUG("Initialise PSI (x,h)\n"); 00071 cache_psi_vectors(); 00072 00073 /* 00074 * define variables for calculating the stopping 00075 * criterion for the outer loop 00076 */ 00077 float64_t decrement = 0.0, primal_obj = 0.0, prev_po = 0.0; 00078 float64_t inner_eps = 0.5*m_C*m_epsilon; 00079 bool stop = false; 00080 int32_t iter = 0; 00081 00082 /* do CCCP */ 00083 SG_DEBUG("Starting CCCP\n"); 00084 while ((iter < 2)||(!stop&&(iter < m_max_iter))) 00085 { 00086 SG_DEBUG("iteration: %d\n", iter); 00087 /* do the SVM optimisation with fixed h* */ 00088 SG_DEBUG("Do the inner loop of CCCP: optimize for w for fixed h*\n"); 00089 primal_obj = do_inner_loop(inner_eps); 00090 00091 /* calculate the decrement */ 00092 decrement = prev_po - primal_obj; 00093 prev_po = primal_obj; 00094 SG_DEBUG("decrement: %f\n", decrement); 00095 SG_DEBUG("primal objective: %f\n", primal_obj); 00096 00097 /* check the stopping criterion */ 00098 stop = (inner_eps < (0.5*m_C*m_epsilon+1E-8)) && (decrement < m_C*m_epsilon); 00099 00100 inner_eps = -decrement*0.01; 00101 inner_eps = CMath::max(inner_eps, 0.5*m_C*m_epsilon); 00102 SG_DEBUG("inner epsilon: %f\n", inner_eps); 00103 00104 /* find argmaxH */ 00105 SG_DEBUG("Find and set h_i = argmax_h (w, psi(x_i,h))\n"); 00106 m_model->argmax_h(w); 00107 00108 SG_DEBUG("Recalculating PSI (x,h) with the new h variables\n"); 00109 cache_psi_vectors(); 00110 00111 /* increment iteration counter */ 00112 iter++; 00113 } 00114 00115 return true; 00116 } 00117 00118 void CLinearLatentMachine::init() 00119 { 00120 m_C = 10.0; 00121 m_epsilon = 1E-3; 00122 m_max_iter = 400; 00123 features = new CDenseFeatures<float64_t> (); 00124 SG_REF(features); 00125 m_model = NULL; 00126 00127 m_parameters->add(&m_C, "C", "Cost constant."); 00128 m_parameters->add(&m_epsilon, "epsilon", "Convergence precision."); 00129 m_parameters->add(&m_max_iter, "max_iter", "Maximum iterations."); 00130 m_parameters->add((CSGObject**) &m_model, "latent_model", "Latent Model."); 00131 } 00132