svmsgd_alg.cpp
Go to the documentation of this file.
00001 #include "svmsgd_alg.h"
00002 
00003 SvmsgdAlgorithm::SvmsgdAlgorithm(void) // loss, d, C1, num_iters, use_bias, use_reg_bias, wscale
00004 {
00005   this->loss_type=LOGLOSS; //default values for now
00006   this->bias=0;
00007   this->wscale=1.0;
00008   this->num_iters=100;
00009   double C1=1.0;
00010 
00011   this->lambda=1.0/(C1*this->num_iters);
00012   this->use_bias=1;
00013   this->use_reg_bias=0;
00014   
00015   double maxw=1.0/sqrt(lambda);
00016   double typw=sqrt(maxw);
00017   double l=this->dloss(-typw);
00018   l=1.0>l?1.0:l;
00019   double eta0=typw / l;
00020   this->t=1.0/(eta0*this->lambda);
00021   this->calibrated=false;
00022 }
00023 
00024 SvmsgdAlgorithm::~SvmsgdAlgorithm(void)
00025 {
00026   delete [] this->w;
00027 }
00028 
00029 void SvmsgdAlgorithm::config_update(Config& new_cfg, uint32_t level)
00030 {
00031   this->lock();
00032 
00033   // save the current configuration
00034   this->config_=new_cfg;
00035   
00036   this->unlock();
00037 }
00038 
00039 double SvmsgdAlgorithm::dloss(double z)
00040 {
00041   double ez;
00042   switch(this->loss_type)
00043   {
00044   case LOGLOSS:
00045     if (z < 0) return 1 / (exp(z) + 1);
00046     ez = exp(-z);
00047     return ez / (ez + 1);
00048   case LOGLOSSMARGIN:
00049     if (z < 1) return 1 / (exp(z-1) + 1);
00050     ez = exp(1-z);
00051     return ez / (ez + 1);
00052   case SMOOTHHINGELOSS:
00053     if (z < 0) return 1;
00054     if (z < 1) return 1-z;
00055     return 0;
00056   case SQUAREDHINGELOSS:
00057     if (z < 1) return (1 - z);
00058     return 0;
00059   default:
00060     if (z < 1) return 1;
00061     return 0;
00062   }
00063   return 0;
00064 }
00065 
00066 double SvmsgdAlgorithm::loss(double z)
00067 {
00068   switch(this->loss_type)
00069   {
00070   case LOGLOSS:
00071     if (z >= 0) return log(1+exp(-z));
00072     else return -z + log(1+exp(z));
00073   case LOGLOSSMARGIN:
00074     if (z >= 1) return log(1+exp(1-z));
00075     else return 1-z + log(1+exp(z-1));
00076   case SMOOTHHINGELOSS:
00077     if (z < 0) return 0.5 - z;
00078     if (z < 1) return 0.5 * (1-z) * (1-z);
00079     return 0;
00080   case SQUAREDHINGELOSS:
00081     if (z < 1) return 0.5 * (1 - z) * (1 - z);
00082     return 0;
00083   case HINGELOSS:
00084     if (z < 1) return 1 - z;
00085     return 0;
00086   default:
00087     ROS_ERROR("SVMSGD ERROR: Unknown loss\n");
00088     exit(-1);
00089   }
00090 }
00091 
00092 void SvmsgdAlgorithm::calibrate(const std::vector<iri_svmsgd::learn_example> &train_matrix)
00093 {
00094   if(train_matrix.size()==0)
00095   {
00096     ROS_ERROR("Empty calibration matrix!\n");
00097     exit(-1);
00098   }
00099   if(this->calibrated==true)
00100   {
00101     ROS_INFO("SVMSGD already calibrated, re-initializing and re-calibrating\n");
00102     delete [] this->w;
00103     this->bias=0;
00104   }
00105   this->d=train_matrix[0].feature_vector.size();
00106   this->w=new double[this->d];
00107   
00108   int j;
00109   int num_vec=train_matrix.size();
00110   double* c=(double*)malloc(sizeof(double)*this->d);
00111   memset(c, 0, this->d*sizeof(double));
00112 
00113   ROS_INFO("Estimating sparsity and bscale num_vec=%d num_feat=%d.\n", num_vec, this->d);
00114 
00115   /* compute average gradient size*/
00116   int n = 0;
00117   int k = 0;
00118   double m = 0;
00119   double r = 0;
00120 
00121   for (j=0; j<num_vec && m<=1000; j++, n++)
00122   {
00123     n++;
00124     r += this->d ;
00125     /* r += get_nnz_features_for_vector(train_matrix, j);  //overestimating*/
00126     add_to_dense_vec_abs(train_matrix[j].feature_vector, 1.0, c);
00127 
00128     /*waste cpu cycles for readability*/
00129     /*(only changed dims need checking)*/
00130     for(k=0; k<this->d; k++)
00131       m = c[k]>m?c[k]:m;
00132   }
00133 
00134   /* bias update scaling*/
00135   this->bscale = m/n;
00136 
00137   /* compute weight decay skip*/
00138   this->skip = (int) ((8 * n * this->d) / r);
00139   ROS_INFO("using %d examples. skip=%d  bscale=%.6f\n", n, this->skip, this->bscale);
00140 
00141   free(c);
00142   this->calibrated=true;
00143   this->count=this->skip;
00144 }
00145 
00146 // SvmsgdAlgorithm Public API
00147 
00148 void SvmsgdAlgorithm::process_new_example(std::vector<float> &new_example, double y)
00149 {
00150   double eta = 1.0 / (this->lambda * this->t);
00151   double z = y * (dot(new_example, this->w, this->d) + this->bias);
00152 
00153   if ( (z < 1) || (this->loss_type >= LOGLOSS) ) {
00154     double etd = eta * this->dloss(z);
00155     this->add_to_dense_vec(new_example, etd * y / this->wscale, this->w);
00156 
00157     if (this->use_bias) {
00158       if (this->use_reg_bias)
00159         this->bias *= 1 - eta * this->lambda * this->bscale;
00160       this->bias += etd * y * this->bscale;
00161     }
00162   }
00163 
00164   if (--this->count <= 0) {
00165     double r = 1 - eta * this->lambda * this->skip;
00166     if (r < 0.8)
00167       r = pow(1 - eta * this->lambda, this->skip);
00168 
00169     for (int i_scale=0; i_scale < this->d; i_scale++)
00170       this->w[i_scale]*=r;
00171     this->count = this->skip;
00172   }
00173   this->t++;
00174 }


iri_svmsgd
Author(s): Arnau Ramisa
autogenerated on Fri Dec 6 2013 23:13:11