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  * 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/features/streaming/StreamingDenseFeatures.h>
00015 #include <shogun/lib/Time.h>
00016 
00017 using namespace shogun;
00018 
00019 COnlineLibLinear::COnlineLibLinear()
00020         : COnlineLinearMachine()
00021 {
00022         init();
00023 }
00024 
00025 COnlineLibLinear::COnlineLibLinear(float64_t C_reg)
00026 {
00027         init();
00028         C1=C_reg;
00029         C2=C_reg;
00030         use_bias=true;
00031 }
00032 
00033 COnlineLibLinear::COnlineLibLinear(
00034         float64_t C_reg, CStreamingDotFeatures* traindat)
00035 {
00036         init();
00037         C1=C_reg;
00038         C2=C_reg;
00039         use_bias=true;
00040 
00041         set_features(traindat);
00042 }
00043 
00044 COnlineLibLinear::COnlineLibLinear(COnlineLibLinear *mch)
00045 {
00046     init();
00047     C1 = mch->C1;
00048     C2 = mch->C2;
00049     use_bias = mch->use_bias;
00050 
00051     set_features(mch->features);
00052 
00053     w_dim = mch->w_dim;
00054     if (w_dim > 0)
00055     {
00056         w = SG_MALLOC(float32_t, w_dim);
00057         memcpy(w, mch->w, w_dim*sizeof(float32_t));
00058     }
00059     else
00060     {
00061         w = NULL;
00062     }
00063     bias = mch->bias;
00064 }
00065 
00066 
00067 void COnlineLibLinear::init()
00068 {
00069         C1=1;
00070         C2=1;
00071         use_bias=false;
00072 
00073         m_parameters->add(&C1, "C1",  "C Cost constant 1.");
00074         m_parameters->add(&C2, "C2",  "C Cost constant 2.");
00075         m_parameters->add(&use_bias, "use_bias",  "Indicates if bias is used.");
00076 }
00077 
00078 COnlineLibLinear::~COnlineLibLinear()
00079 {
00080 }
00081 
00082 void COnlineLibLinear::start_train()
00083 {
00084     Cp = C1;
00085     Cn = C2;
00086     PGmax_old = CMath::INFTY;
00087     PGmin_old = -CMath::INFTY;
00088     PGmax_new = -CMath::INFTY;
00089     PGmin_new = CMath::INFTY;
00090 
00091     diag[0]=0;diag[1]=0;diag[2]=0;
00092     upper_bound[0]=Cn;upper_bound[1]=0;upper_bound[2]=Cp;
00093 
00094     bias = 0;
00095 
00096     PGmax_new = -CMath::INFTY;
00097     PGmin_new = CMath::INFTY;
00098 
00099     v = 0;
00100     nSV = 0;
00101 }
00102 
00103 void COnlineLibLinear::stop_train()
00104 {
00105     float64_t gap = PGmax_new - PGmin_new;
00106 
00107     SG_DONE();
00108     SG_INFO("Optimization finished.\n");
00109 
00110     // calculate objective value
00111     for (int32_t i=0; i<w_dim; i++)
00112         v += w[i]*w[i];
00113     v += bias*bias;
00114 
00115     SG_INFO("Objective value = %lf\n", v/2);
00116     SG_INFO("nSV = %d\n", nSV);
00117     SG_INFO("gap = %g\n", gap);
00118 }
00119 
00120 void COnlineLibLinear::train_one(SGVector<float32_t> ex, float64_t label)
00121 {
00122     alpha_current = 0;
00123     if (label > 0)
00124         y_current = +1;
00125     else
00126         y_current = -1;
00127 
00128     QD = diag[y_current + 1];
00129     // Dot product of vector with itself
00130     QD += SGVector<float32_t>::dot(ex.vector, ex.vector, ex.vlen);
00131 
00132     if (ex.vlen > w_dim)
00133     {
00134         w = SG_REALLOC(float32_t, w, ex.vlen);
00135         memset(&w[w_dim], 0, (ex.vlen - w_dim)*sizeof(float32_t));
00136         w_dim = ex.vlen;
00137     }
00138 
00139     G = SGVector<float32_t>::dot(ex.vector, w, w_dim);
00140     if (use_bias)
00141         G += bias;
00142     G = G*y_current - 1;
00143     // LINEAR TERM PART?
00144 
00145     C = upper_bound[y_current + 1];
00146     G += alpha_current*diag[y_current + 1]; // Can be eliminated, since diag = 0 vector
00147 
00148     PG = 0;
00149     if (alpha_current == 0) // This condition will always be true in the online version
00150     {
00151         if (G > PGmax_old)
00152         {
00153             return;
00154         }
00155         else if (G < 0)
00156             PG = G;
00157     }
00158     else if (alpha_current == C)
00159     {
00160         if (G < PGmin_old)
00161         {
00162             return;
00163         }
00164         else if (G > 0)
00165             PG = G;
00166     }
00167     else
00168         PG = G;
00169 
00170     PGmax_new = CMath::max(PGmax_new, PG);
00171     PGmin_new = CMath::min(PGmin_new, PG);
00172 
00173     if (fabs(PG) > 1.0e-12)
00174     {
00175         float64_t alpha_old = alpha_current;
00176         alpha_current = CMath::min(CMath::max(alpha_current - G/QD, 0.0), C);
00177         d = (alpha_current - alpha_old) * y_current;
00178 
00179         for (int32_t i=0; i < w_dim; ++i)
00180             w[i] += d*ex[i];
00181 
00182 
00183         if (use_bias)
00184             bias += d;
00185     }
00186 
00187     v += alpha_current*(alpha_current*diag[y_current + 1] - 2);
00188     if (alpha_current > 0)
00189         nSV++;
00190 }
00191 
00192 void COnlineLibLinear::train_example(CStreamingDotFeatures *feature, float64_t label)
00193 {
00194     CStreamingDenseFeatures<float32_t> *feat =
00195         dynamic_cast<CStreamingDenseFeatures<float32_t> *>(feature);
00196     if (feat == NULL)
00197         SG_ERROR("Expected streaming dense feature <float32_t>\n");
00198 
00199     train_one(feat->get_vector(), label);
00200 }
00201 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation