Go to the documentation of this file.00001 #include "svmsgd_alg.h"
00002
00003 SvmsgdAlgorithm::SvmsgdAlgorithm(void)
00004 {
00005 this->loss_type=LOGLOSS;
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
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
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
00126 add_to_dense_vec_abs(train_matrix[j].feature_vector, 1.0, c);
00127
00128
00129
00130 for(k=0; k<this->d; k++)
00131 m = c[k]>m?c[k]:m;
00132 }
00133
00134
00135 this->bscale = m/n;
00136
00137
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
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 }