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) 2007-2010 Soeren Sonnenburg 00008 * Written (W) 2011 Shashwat Lal Das 00009 * Copyright (c) 2007-2009 The LIBLINEAR Project. 00010 * Copyright (C) 2007-2010 Fraunhofer Institute FIRST and Max-Planck-Society 00011 */ 00012 00013 #include <shogun/classifier/svm/OnlineLibLinear.h> 00014 #include <shogun/features/streaming/StreamingDenseFeatures.h> 00015 #include <shogun/lib/Time.h> 00016 00017 using namespace shogun; 00018 00019 COnlineLibLinear::COnlineLibLinear() 00020 : COnlineLinearMachine() 00021 { 00022 init(); 00023 } 00024 00025 COnlineLibLinear::COnlineLibLinear(float64_t C_reg) 00026 { 00027 init(); 00028 C1=C_reg; 00029 C2=C_reg; 00030 use_bias=true; 00031 } 00032 00033 COnlineLibLinear::COnlineLibLinear( 00034 float64_t C_reg, CStreamingDotFeatures* traindat) 00035 { 00036 init(); 00037 C1=C_reg; 00038 C2=C_reg; 00039 use_bias=true; 00040 00041 set_features(traindat); 00042 } 00043 00044 COnlineLibLinear::COnlineLibLinear(COnlineLibLinear *mch) 00045 { 00046 init(); 00047 C1 = mch->C1; 00048 C2 = mch->C2; 00049 use_bias = mch->use_bias; 00050 00051 set_features(mch->features); 00052 00053 w_dim = mch->w_dim; 00054 if (w_dim > 0) 00055 { 00056 w = SG_MALLOC(float32_t, w_dim); 00057 memcpy(w, mch->w, w_dim*sizeof(float32_t)); 00058 } 00059 else 00060 { 00061 w = NULL; 00062 } 00063 bias = mch->bias; 00064 } 00065 00066 00067 void COnlineLibLinear::init() 00068 { 00069 C1=1; 00070 C2=1; 00071 use_bias=false; 00072 00073 m_parameters->add(&C1, "C1", "C Cost constant 1."); 00074 m_parameters->add(&C2, "C2", "C Cost constant 2."); 00075 m_parameters->add(&use_bias, "use_bias", "Indicates if bias is used."); 00076 } 00077 00078 COnlineLibLinear::~COnlineLibLinear() 00079 { 00080 } 00081 00082 void COnlineLibLinear::start_train() 00083 { 00084 Cp = C1; 00085 Cn = C2; 00086 PGmax_old = CMath::INFTY; 00087 PGmin_old = -CMath::INFTY; 00088 PGmax_new = -CMath::INFTY; 00089 PGmin_new = CMath::INFTY; 00090 00091 diag[0]=0;diag[1]=0;diag[2]=0; 00092 upper_bound[0]=Cn;upper_bound[1]=0;upper_bound[2]=Cp; 00093 00094 bias = 0; 00095 00096 PGmax_new = -CMath::INFTY; 00097 PGmin_new = CMath::INFTY; 00098 00099 v = 0; 00100 nSV = 0; 00101 } 00102 00103 void COnlineLibLinear::stop_train() 00104 { 00105 float64_t gap = PGmax_new - PGmin_new; 00106 00107 SG_DONE(); 00108 SG_INFO("Optimization finished.\n"); 00109 00110 // calculate objective value 00111 for (int32_t i=0; i<w_dim; i++) 00112 v += w[i]*w[i]; 00113 v += bias*bias; 00114 00115 SG_INFO("Objective value = %lf\n", v/2); 00116 SG_INFO("nSV = %d\n", nSV); 00117 SG_INFO("gap = %g\n", gap); 00118 } 00119 00120 void COnlineLibLinear::train_one(SGVector<float32_t> ex, float64_t label) 00121 { 00122 alpha_current = 0; 00123 if (label > 0) 00124 y_current = +1; 00125 else 00126 y_current = -1; 00127 00128 QD = diag[y_current + 1]; 00129 // Dot product of vector with itself 00130 QD += SGVector<float32_t>::dot(ex.vector, ex.vector, ex.vlen); 00131 00132 if (ex.vlen > w_dim) 00133 { 00134 w = SG_REALLOC(float32_t, w, ex.vlen); 00135 memset(&w[w_dim], 0, (ex.vlen - w_dim)*sizeof(float32_t)); 00136 w_dim = ex.vlen; 00137 } 00138 00139 G = SGVector<float32_t>::dot(ex.vector, w, w_dim); 00140 if (use_bias) 00141 G += bias; 00142 G = G*y_current - 1; 00143 // LINEAR TERM PART? 00144 00145 C = upper_bound[y_current + 1]; 00146 G += alpha_current*diag[y_current + 1]; // Can be eliminated, since diag = 0 vector 00147 00148 PG = 0; 00149 if (alpha_current == 0) // This condition will always be true in the online version 00150 { 00151 if (G > PGmax_old) 00152 { 00153 return; 00154 } 00155 else if (G < 0) 00156 PG = G; 00157 } 00158 else if (alpha_current == C) 00159 { 00160 if (G < PGmin_old) 00161 { 00162 return; 00163 } 00164 else if (G > 0) 00165 PG = G; 00166 } 00167 else 00168 PG = G; 00169 00170 PGmax_new = CMath::max(PGmax_new, PG); 00171 PGmin_new = CMath::min(PGmin_new, PG); 00172 00173 if (fabs(PG) > 1.0e-12) 00174 { 00175 float64_t alpha_old = alpha_current; 00176 alpha_current = CMath::min(CMath::max(alpha_current - G/QD, 0.0), C); 00177 d = (alpha_current - alpha_old) * y_current; 00178 00179 for (int32_t i=0; i < w_dim; ++i) 00180 w[i] += d*ex[i]; 00181 00182 00183 if (use_bias) 00184 bias += d; 00185 } 00186 00187 v += alpha_current*(alpha_current*diag[y_current + 1] - 2); 00188 if (alpha_current > 0) 00189 nSV++; 00190 } 00191 00192 void COnlineLibLinear::train_example(CStreamingDotFeatures *feature, float64_t label) 00193 { 00194 CStreamingDenseFeatures<float32_t> *feat = 00195 dynamic_cast<CStreamingDenseFeatures<float32_t> *>(feature); 00196 if (feat == NULL) 00197 SG_ERROR("Expected streaming dense feature <float32_t>\n"); 00198 00199 train_one(feat->get_vector(), label); 00200 } 00201