SVM_linear.cpp
Go to the documentation of this file.00001 #include "lib/config.h"
00002
00003 #ifdef HAVE_LAPACK
00004 #include <math.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <stdarg.h>
00009
00010 #include "classifier/svm/SVM_linear.h"
00011 #include "classifier/svm/Tron.h"
00012
00013 l2_lr_fun::l2_lr_fun(const problem *p, double Cp, double Cn)
00014 : function()
00015 {
00016 int i;
00017 int l=p->l;
00018 int *y=p->y;
00019
00020 this->prob = p;
00021
00022 z = new double[l];
00023 D = new double[l];
00024 C = new double[l];
00025
00026 for (i=0; i<l; i++)
00027 {
00028 if (y[i] == 1)
00029 C[i] = Cp;
00030 else
00031 C[i] = Cn;
00032 }
00033 }
00034
00035 l2_lr_fun::~l2_lr_fun()
00036 {
00037 delete[] z;
00038 delete[] D;
00039 delete[] C;
00040 }
00041
00042
00043 double l2_lr_fun::fun(double *w)
00044 {
00045 int i;
00046 double f=0;
00047 int *y=prob->y;
00048 int l=prob->l;
00049 int n=prob->n;
00050
00051 Xv(w, z);
00052 for(i=0;i<l;i++)
00053 {
00054 double yz = y[i]*z[i];
00055 if (yz >= 0)
00056 f += C[i]*log(1 + exp(-yz));
00057 else
00058 f += C[i]*(-yz+log(1 + exp(yz)));
00059 }
00060 f = 2*f;
00061 for(i=0;i<n;i++)
00062 f += w[i]*w[i];
00063 f /= 2.0;
00064
00065 return(f);
00066 }
00067
00068 void l2_lr_fun::grad(double *w, double *g)
00069 {
00070 int i;
00071 int *y=prob->y;
00072 int l=prob->l;
00073 int n=prob->n;
00074
00075 for(i=0;i<l;i++)
00076 {
00077 z[i] = 1/(1 + exp(-y[i]*z[i]));
00078 D[i] = z[i]*(1-z[i]);
00079 z[i] = C[i]*(z[i]-1)*y[i];
00080 }
00081 XTv(z, g);
00082
00083 for(i=0;i<n;i++)
00084 g[i] = w[i] + g[i];
00085 }
00086
00087 int l2_lr_fun::get_nr_variable(void)
00088 {
00089 return prob->n;
00090 }
00091
00092 void l2_lr_fun::Hv(double *s, double *Hs)
00093 {
00094 int i;
00095 int l=prob->l;
00096 int n=prob->n;
00097 double *wa = new double[l];
00098
00099 Xv(s, wa);
00100 for(i=0;i<l;i++)
00101 wa[i] = C[i]*D[i]*wa[i];
00102
00103 XTv(wa, Hs);
00104 for(i=0;i<n;i++)
00105 Hs[i] = s[i] + Hs[i];
00106 delete[] wa;
00107 }
00108
00109 void l2_lr_fun::Xv(double *v, double *res_Xv)
00110 {
00111 int l=prob->l;
00112 int n=prob->n;
00113
00114 if (prob->use_bias)
00115 n--;
00116
00117 for (int i=0;i<l;i++)
00118 {
00119 res_Xv[i]=prob->x->dense_dot(1.0, i, v, n, 0);
00120
00121 if (prob->use_bias)
00122 res_Xv[i]+=v[n];
00123 }
00124 }
00125
00126 void l2_lr_fun::XTv(double *v, double *res_XTv)
00127 {
00128 int l=prob->l;
00129 int n=prob->n;
00130
00131 if (prob->use_bias)
00132 n--;
00133
00134 memset(res_XTv, 0, sizeof(double)*prob->n);
00135
00136 for (int i=0;i<l;i++)
00137 {
00138 prob->x->add_to_dense_vec(v[i], i, res_XTv, n);
00139
00140 if (prob->use_bias)
00141 res_XTv[n]+=v[i];
00142 }
00143 }
00144
00145 l2loss_svm_fun::l2loss_svm_fun(const problem *p, double Cp, double Cn)
00146 : function()
00147 {
00148 int i;
00149 int l=p->l;
00150 int *y=p->y;
00151
00152 this->prob = p;
00153
00154 z = new double[l];
00155 D = new double[l];
00156 C = new double[l];
00157 I = new int[l];
00158
00159 for (i=0; i<l; i++)
00160 {
00161 if (y[i] == 1)
00162 C[i] = Cp;
00163 else
00164 C[i] = Cn;
00165 }
00166 }
00167
00168 l2loss_svm_fun::~l2loss_svm_fun()
00169 {
00170 delete[] z;
00171 delete[] D;
00172 delete[] C;
00173 delete[] I;
00174 }
00175
00176 double l2loss_svm_fun::fun(double *w)
00177 {
00178 int i;
00179 double f=0;
00180 int *y=prob->y;
00181 int l=prob->l;
00182 int n=prob->n;
00183
00184 Xv(w, z);
00185 for(i=0;i<l;i++)
00186 {
00187 z[i] = y[i]*z[i];
00188 double d = z[i]-1;
00189 if (d < 0)
00190 f += C[i]*d*d;
00191 }
00192 f = 2*f;
00193 for(i=0;i<n;i++)
00194 f += w[i]*w[i];
00195 f /= 2.0;
00196
00197 return(f);
00198 }
00199
00200 void l2loss_svm_fun::grad(double *w, double *g)
00201 {
00202 int i;
00203 int *y=prob->y;
00204 int l=prob->l;
00205 int n=prob->n;
00206
00207 sizeI = 0;
00208 for (i=0;i<l;i++)
00209 if (z[i] < 1)
00210 {
00211 z[sizeI] = C[i]*y[i]*(z[i]-1);
00212 I[sizeI] = i;
00213 sizeI++;
00214 }
00215 subXTv(z, g);
00216
00217 for(i=0;i<n;i++)
00218 g[i] = w[i] + 2*g[i];
00219 }
00220
00221 int l2loss_svm_fun::get_nr_variable(void)
00222 {
00223 return prob->n;
00224 }
00225
00226 void l2loss_svm_fun::Hv(double *s, double *Hs)
00227 {
00228 int i;
00229 int l=prob->l;
00230 int n=prob->n;
00231 double *wa = new double[l];
00232
00233 subXv(s, wa);
00234 for(i=0;i<sizeI;i++)
00235 wa[i] = C[I[i]]*wa[i];
00236
00237 subXTv(wa, Hs);
00238 for(i=0;i<n;i++)
00239 Hs[i] = s[i] + 2*Hs[i];
00240 delete[] wa;
00241 }
00242
00243 void l2loss_svm_fun::Xv(double *v, double *res_Xv)
00244 {
00245 int l=prob->l;
00246 int n=prob->n;
00247
00248 if (prob->use_bias)
00249 n--;
00250
00251 for(int i=0;i<l;i++)
00252 {
00253 res_Xv[i]=prob->x->dense_dot(1.0, i, v, n, 0);
00254
00255 if (prob->use_bias)
00256 res_Xv[i]+=v[n];
00257 }
00258 }
00259
00260 void l2loss_svm_fun::subXv(double *v, double *res_Xv)
00261 {
00262 int n=prob->n;
00263
00264 if (prob->use_bias)
00265 n--;
00266
00267 for(int i=0;i<sizeI;i++)
00268 {
00269 res_Xv[i]=prob->x->dense_dot(1.0, I[i], v, n, 0);
00270
00271 if (prob->use_bias)
00272 res_Xv[i]+=v[n];
00273 }
00274 }
00275
00276 void l2loss_svm_fun::subXTv(double *v, double *XTv)
00277 {
00278 int n=prob->n;
00279
00280 if (prob->use_bias)
00281 n--;
00282
00283 memset(XTv, 0, sizeof(double)*prob->n);
00284 for(int i=0;i<sizeI;i++)
00285 {
00286 prob->x->add_to_dense_vec(v[i], I[i], XTv, n);
00287
00288 if (prob->use_bias)
00289 XTv[n]+=v[i];
00290 }
00291 }
00292
00293 #endif //HAVE_LAPACK