SHOGUN
v1.1.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/lib/Time.h> 00015 00016 using namespace shogun; 00017 00018 COnlineLibLinear::COnlineLibLinear() 00019 : COnlineLinearMachine() 00020 { 00021 init(); 00022 } 00023 00024 COnlineLibLinear::COnlineLibLinear(float64_t C) 00025 { 00026 init(); 00027 C1=C; 00028 C2=C; 00029 use_bias=true; 00030 } 00031 00032 COnlineLibLinear::COnlineLibLinear( 00033 float64_t C, CStreamingDotFeatures* traindat) 00034 { 00035 init(); 00036 C1=C; 00037 C2=C; 00038 use_bias=true; 00039 00040 set_features(traindat); 00041 } 00042 00043 00044 void COnlineLibLinear::init() 00045 { 00046 C1=1; 00047 C2=1; 00048 use_bias=false; 00049 00050 m_parameters->add(&C1, "C1", "C Cost constant 1."); 00051 m_parameters->add(&C2, "C2", "C Cost constant 2."); 00052 m_parameters->add(&use_bias, "use_bias", "Indicates if bias is used."); 00053 } 00054 00055 COnlineLibLinear::~COnlineLibLinear() 00056 { 00057 } 00058 00059 bool COnlineLibLinear::train(CFeatures* data) 00060 { 00061 if (data) 00062 { 00063 if (!data->has_property(FP_STREAMING_DOT)) 00064 SG_ERROR("Specified features are not of type CStreamingDotFeatures\n"); 00065 set_features((CStreamingDotFeatures*) data); 00066 } 00067 00068 float64_t C, d, G; 00069 float64_t QD; 00070 00071 // y and alpha for example being processed 00072 int32_t y_current; 00073 float64_t alpha_current; 00074 00075 // Cost constants 00076 float64_t Cp=C1; 00077 float64_t Cn=C2; 00078 00079 // PG: projected gradient, for shrinking and stopping 00080 float64_t PG; 00081 float64_t PGmax_old = CMath::INFTY; 00082 float64_t PGmin_old = -CMath::INFTY; 00083 float64_t PGmax_new = -CMath::INFTY; 00084 float64_t PGmin_new = CMath::INFTY; 00085 00086 // Diag is probably unnecessary 00087 float64_t diag[3] = {0, 0, 0}; 00088 float64_t upper_bound[3] = {Cn, 0, Cp}; 00089 00090 // Bias 00091 bias = 0; 00092 00093 PGmax_new = -CMath::INFTY; 00094 PGmin_new = CMath::INFTY; 00095 00096 // Objective value = v/2 00097 float64_t v = 0; 00098 // Number of support vectors 00099 int32_t nSV = 0; 00100 00101 // Start reading the examples 00102 features->start_parser(); 00103 00104 CTime start_time; 00105 while (features->get_next_example()) 00106 { 00107 alpha_current = 0; 00108 if (features->get_label() > 0) 00109 y_current = +1; 00110 else 00111 y_current = -1; 00112 00113 QD = diag[y_current + 1]; 00114 // Dot product of vector with itself 00115 QD += features->dot(features); 00116 00117 features->expand_if_required(w, w_dim); 00118 00119 G = features->dense_dot(w, w_dim); 00120 if (use_bias) 00121 G += bias; 00122 G = G*y_current - 1; 00123 // LINEAR TERM PART? 00124 00125 C = upper_bound[y_current + 1]; 00126 G += alpha_current*diag[y_current + 1]; // Can be eliminated, since diag = 0 vector 00127 00128 PG = 0; 00129 if (alpha_current == 0) // This condition will always be true in the online version 00130 { 00131 if (G > PGmax_old) 00132 { 00133 features->release_example(); 00134 continue; 00135 } 00136 else if (G < 0) 00137 PG = G; 00138 } 00139 else if (alpha_current == C) 00140 { 00141 if (G < PGmin_old) 00142 { 00143 features->release_example(); 00144 continue; 00145 } 00146 else if (G > 0) 00147 PG = G; 00148 } 00149 else 00150 PG = G; 00151 00152 PGmax_new = CMath::max(PGmax_new, PG); 00153 PGmin_new = CMath::min(PGmin_new, PG); 00154 00155 if (fabs(PG) > 1.0e-12) 00156 { 00157 float64_t alpha_old = alpha_current; 00158 alpha_current = CMath::min(CMath::max(alpha_current - G/QD, 0.0), C); 00159 d = (alpha_current - alpha_old) * y_current; 00160 00161 features->add_to_dense_vec(d, w, w_dim); 00162 00163 if (use_bias) 00164 bias += d; 00165 } 00166 00167 v += alpha_current*(alpha_current*diag[y_current + 1] - 2); 00168 if (alpha_current > 0) 00169 nSV++; 00170 00171 features->release_example(); 00172 } 00173 00174 features->end_parser(); 00175 00176 float64_t gap = PGmax_new - PGmin_new; 00177 00178 SG_DONE(); 00179 SG_INFO("Optimization finished.\n"); 00180 00181 // calculate objective value 00182 for (int32_t i=0; i<w_dim; i++) 00183 v += w[i]*w[i]; 00184 v += bias*bias; 00185 00186 SG_INFO("Objective value = %lf\n", v/2); 00187 SG_INFO("nSV = %d\n", nSV); 00188 SG_INFO("gap = %g\n", gap); 00189 00190 return true; 00191 }