SHOGUN  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
OnlineLibLinear.cpp
Go to the documentation of this file.
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  * Modifications (W) 2013 Thoralf Klein
00010  * Copyright (c) 2007-2009 The LIBLINEAR Project.
00011  * Copyright (C) 2007-2010 Fraunhofer Institute FIRST and Max-Planck-Society
00012  */
00013 
00014 #include <shogun/classifier/svm/OnlineLibLinear.h>
00015 #include <shogun/features/streaming/StreamingDenseFeatures.h>
00016 #include <shogun/features/streaming/StreamingSparseFeatures.h>
00017 #include <shogun/lib/Time.h>
00018 
00019 using namespace shogun;
00020 
00021 COnlineLibLinear::COnlineLibLinear()
00022         : COnlineLinearMachine()
00023 {
00024         init();
00025 }
00026 
00027 COnlineLibLinear::COnlineLibLinear(float64_t C_reg)
00028 {
00029         init();
00030         C1=C_reg;
00031         C2=C_reg;
00032         use_bias=true;
00033 }
00034 
00035 COnlineLibLinear::COnlineLibLinear(
00036         float64_t C_reg, CStreamingDotFeatures* traindat)
00037 {
00038         init();
00039         C1=C_reg;
00040         C2=C_reg;
00041         use_bias=true;
00042 
00043         set_features(traindat);
00044 }
00045 
00046 COnlineLibLinear::COnlineLibLinear(COnlineLibLinear *mch)
00047 {
00048     init();
00049     C1 = mch->C1;
00050     C2 = mch->C2;
00051     use_bias = mch->use_bias;
00052 
00053     set_features(mch->features);
00054 
00055     w_dim = mch->w_dim;
00056     if (w_dim > 0)
00057     {
00058         w = SG_MALLOC(float32_t, w_dim);
00059         memcpy(w, mch->w, w_dim*sizeof(float32_t));
00060     }
00061     else
00062     {
00063         w = NULL;
00064     }
00065     bias = mch->bias;
00066 }
00067 
00068 
00069 void COnlineLibLinear::init()
00070 {
00071         C1=1;
00072         C2=1;
00073         use_bias=false;
00074 
00075         m_parameters->add(&C1, "C1",  "C Cost constant 1.");
00076         m_parameters->add(&C2, "C2",  "C Cost constant 2.");
00077         m_parameters->add(&use_bias, "use_bias",  "Indicates if bias is used.");
00078 }
00079 
00080 COnlineLibLinear::~COnlineLibLinear()
00081 {
00082 }
00083 
00084 void COnlineLibLinear::start_train()
00085 {
00086     Cp = C1;
00087     Cn = C2;
00088     PGmax_old = CMath::INFTY;
00089     PGmin_old = -CMath::INFTY;
00090     PGmax_new = -CMath::INFTY;
00091     PGmin_new = CMath::INFTY;
00092 
00093     diag[0]=0;diag[1]=0;diag[2]=0;
00094     upper_bound[0]=Cn;upper_bound[1]=0;upper_bound[2]=Cp;
00095 
00096     bias = 0;
00097 
00098     PGmax_new = -CMath::INFTY;
00099     PGmin_new = CMath::INFTY;
00100 
00101     v = 0;
00102     nSV = 0;
00103 }
00104 
00105 void COnlineLibLinear::stop_train()
00106 {
00107     float64_t gap = PGmax_new - PGmin_new;
00108 
00109     SG_DONE()
00110     SG_INFO("Optimization finished.\n")
00111 
00112     // calculate objective value
00113     for (int32_t i=0; i<w_dim; i++)
00114         v += w[i]*w[i];
00115     v += bias*bias;
00116 
00117     SG_INFO("Objective value = %lf\n", v/2)
00118     SG_INFO("nSV = %d\n", nSV)
00119     SG_INFO("gap = %g\n", gap)
00120 }
00121 
00122 void COnlineLibLinear::train_one(SGVector<float32_t> ex, float64_t label)
00123 {
00124     alpha_current = 0;
00125     if (label > 0)
00126         y_current = +1;
00127     else
00128         y_current = -1;
00129 
00130     QD = diag[y_current + 1];
00131     // Dot product of vector with itself
00132     QD += SGVector<float32_t>::dot(ex.vector, ex.vector, ex.vlen);
00133 
00134     // Dot product of vector with learned weights
00135     G = SGVector<float32_t>::dot(ex.vector, w, w_dim);
00136 
00137     if (use_bias)
00138         G += bias;
00139     G = G*y_current - 1;
00140     // LINEAR TERM PART?
00141 
00142     C = upper_bound[y_current + 1];
00143     G += alpha_current*diag[y_current + 1]; // Can be eliminated, since diag = 0 vector
00144 
00145     PG = 0;
00146     if (alpha_current == 0) // This condition will always be true in the online version
00147     {
00148         if (G > PGmax_old)
00149         {
00150             return;
00151         }
00152         else if (G < 0)
00153             PG = G;
00154     }
00155     else if (alpha_current == C)
00156     {
00157         if (G < PGmin_old)
00158         {
00159             return;
00160         }
00161         else if (G > 0)
00162             PG = G;
00163     }
00164     else
00165         PG = G;
00166 
00167     PGmax_new = CMath::max(PGmax_new, PG);
00168     PGmin_new = CMath::min(PGmin_new, PG);
00169 
00170     if (fabs(PG) > 1.0e-12)
00171     {
00172         float64_t alpha_old = alpha_current;
00173         alpha_current = CMath::min(CMath::max(alpha_current - G/QD, 0.0), C);
00174         d = (alpha_current - alpha_old) * y_current;
00175 
00176         for (int32_t i=0; i < w_dim; ++i)
00177             w[i] += d*ex[i];
00178 
00179 
00180         if (use_bias)
00181             bias += d;
00182     }
00183 
00184     v += alpha_current*(alpha_current*diag[y_current + 1] - 2);
00185     if (alpha_current > 0)
00186         nSV++;
00187 }
00188 
00189 void COnlineLibLinear::train_one(SGSparseVector<float32_t> ex, float64_t label)
00190 {
00191     alpha_current = 0;
00192     if (label > 0)
00193         y_current = +1;
00194     else
00195         y_current = -1;
00196 
00197     QD = diag[y_current + 1];
00198     // Dot product of vector with itself
00199     QD += SGSparseVector<float32_t>::sparse_dot(ex, ex);
00200 
00201     // Dot product of vector with learned weights
00202     G = ex.dense_dot(1.0,w,w_dim,0.0);
00203 
00204     if (use_bias)
00205         G += bias;
00206     G = G*y_current - 1;
00207     // LINEAR TERM PART?
00208 
00209     C = upper_bound[y_current + 1];
00210     G += alpha_current*diag[y_current + 1]; // Can be eliminated, since diag = 0 vector
00211 
00212     PG = 0;
00213     if (alpha_current == 0) // This condition will always be true in the online version
00214     {
00215         if (G > PGmax_old)
00216         {
00217             return;
00218         }
00219         else if (G < 0)
00220             PG = G;
00221     }
00222     else if (alpha_current == C)
00223     {
00224         if (G < PGmin_old)
00225         {
00226             return;
00227         }
00228         else if (G > 0)
00229             PG = G;
00230     }
00231     else
00232         PG = G;
00233 
00234     PGmax_new = CMath::max(PGmax_new, PG);
00235     PGmin_new = CMath::min(PGmin_new, PG);
00236 
00237     if (fabs(PG) > 1.0e-12)
00238     {
00239         float64_t alpha_old = alpha_current;
00240         alpha_current = CMath::min(CMath::max(alpha_current - G/QD, 0.0), C);
00241         d = (alpha_current - alpha_old) * y_current;
00242 
00243         for (int32_t i=0; i < ex.num_feat_entries; i++)
00244             w[ex.features[i].feat_index] += d*ex.features[i].entry;
00245 
00246 
00247         if (use_bias)
00248             bias += d;
00249     }
00250 
00251     v += alpha_current*(alpha_current*diag[y_current + 1] - 2);
00252     if (alpha_current > 0)
00253         nSV++;
00254 }
00255 
00256 void COnlineLibLinear::train_example(CStreamingDotFeatures *feature, float64_t label)
00257 {
00258     features->expand_if_required(w, w_dim);
00259 
00260     if (features->get_feature_class() == C_STREAMING_DENSE) {
00261         CStreamingDenseFeatures<float32_t> *feat =
00262             dynamic_cast<CStreamingDenseFeatures<float32_t> *>(feature);
00263         if (feat == NULL)
00264             SG_ERROR("Expected streaming dense feature <float32_t>\n")
00265 
00266         train_one(feat->get_vector(), label);
00267     }
00268     else if (features->get_feature_class() == C_STREAMING_SPARSE) {
00269         CStreamingSparseFeatures<float32_t> *feat =
00270             dynamic_cast<CStreamingSparseFeatures<float32_t> *>(feature);
00271         if (feat == NULL)
00272             SG_ERROR("Expected streaming sparse feature <float32_t>\n")
00273 
00274         train_one(feat->get_vector(), label);
00275     }
00276     else {
00277         SG_NOTIMPLEMENTED
00278     }
00279 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation