SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MulticlassModel.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) 2012 Fernando José Iglesias García
00008  * Copyright (C) 2012 Fernando José Iglesias García
00009  */
00010 
00011 #include <shogun/features/DotFeatures.h>
00012 #include <shogun/mathematics/Math.h>
00013 #include <shogun/structure/MulticlassModel.h>
00014 #include <shogun/structure/MulticlassSOLabels.h>
00015 
00016 using namespace shogun;
00017 
00018 CMulticlassModel::CMulticlassModel()
00019 : CStructuredModel()
00020 {
00021     init();
00022 }
00023 
00024     CMulticlassModel::CMulticlassModel(CFeatures* features, CStructuredLabels* labels)
00025 : CStructuredModel(features, labels)
00026 {
00027     init();
00028 }
00029 
00030 CMulticlassModel::~CMulticlassModel()
00031 {
00032 }
00033 
00034 int32_t CMulticlassModel::get_dim() const
00035 {
00036     // TODO make the casts safe!
00037     int32_t num_classes = ((CMulticlassSOLabels*) m_labels)->get_num_classes();
00038     int32_t feats_dim   = ((CDotFeatures*) m_features)->get_dim_feature_space();
00039 
00040     return feats_dim*num_classes;
00041 }
00042 
00043 SGVector< float64_t > CMulticlassModel::get_joint_feature_vector(int32_t feat_idx, CStructuredData* y)
00044 {
00045     SGVector< float64_t > psi( get_dim() );
00046     psi.zero();
00047 
00048     SGVector< float64_t > x = ((CDotFeatures*) m_features)->
00049         get_computed_dot_feature_vector(feat_idx);
00050     CRealNumber* r = CRealNumber::obtain_from_generic(y);
00051     ASSERT(r != NULL)
00052     float64_t label_value = r->value;
00053 
00054     for ( index_t i = 0, j = label_value*x.vlen ; i < x.vlen ; ++i, ++j )
00055         psi[j] = x[i];
00056 
00057     return psi;
00058 }
00059 
00060 CResultSet* CMulticlassModel::argmax(
00061         SGVector< float64_t > w,
00062         int32_t feat_idx,
00063         bool const training)
00064 {
00065     CDotFeatures* df = (CDotFeatures*) m_features;
00066     int32_t feats_dim   = df->get_dim_feature_space();
00067 
00068     if ( training )
00069     {
00070         CMulticlassSOLabels* ml = (CMulticlassSOLabels*) m_labels;
00071         m_num_classes = ml->get_num_classes();
00072     }
00073     else
00074     {
00075         REQUIRE(m_num_classes > 0, "The model needs to be trained before "
00076                 "using it for prediction\n");
00077     }
00078 
00079     int32_t dim = get_dim();
00080     ASSERT(dim == w.vlen);
00081 
00082     // Find the class that gives the maximum score
00083 
00084     float64_t score = 0, ypred = 0;
00085     float64_t max_score = -CMath::INFTY;
00086 
00087     for ( int32_t c = 0 ; c < m_num_classes ; ++c )
00088     {
00089         score = df->dense_dot(feat_idx, w.vector+c*feats_dim, feats_dim);
00090         if ( training )
00091             score += delta_loss(feat_idx, c);
00092 
00093         if ( score > max_score )
00094         {
00095             max_score = score;
00096             ypred = c;
00097         }
00098     }
00099 
00100     // Build the CResultSet object to return
00101     CResultSet* ret = new CResultSet();
00102     CRealNumber* y  = new CRealNumber(ypred);
00103     SG_REF(y);
00104 
00105     ret->psi_pred = get_joint_feature_vector(feat_idx, y);
00106     ret->score    = max_score;
00107     ret->argmax   = y;
00108     if ( training )
00109     {
00110         ret->delta     = CStructuredModel::delta_loss(feat_idx, y);
00111         ret->psi_truth = CStructuredModel::get_joint_feature_vector(
00112                     feat_idx, feat_idx);
00113         ret->score    -= SGVector< float64_t >::dot(w.vector,
00114                     ret->psi_truth.vector, dim);
00115     }
00116 
00117     return ret;
00118 }
00119 
00120 float64_t CMulticlassModel::delta_loss(CStructuredData* y1, CStructuredData* y2)
00121 {
00122     CRealNumber* rn1 = CRealNumber::obtain_from_generic(y1);
00123     CRealNumber* rn2 = CRealNumber::obtain_from_generic(y2);
00124     ASSERT(rn1 != NULL);
00125     ASSERT(rn2 != NULL);
00126 
00127     return delta_loss(rn1->value, rn2->value);
00128 }
00129 
00130 float64_t CMulticlassModel::delta_loss(int32_t y1_idx, float64_t y2)
00131 {
00132     REQUIRE(y1_idx >= 0 || y1_idx < m_labels->get_num_labels(),
00133             "The label index must be inside [0, num_labels-1]\n");
00134 
00135     CRealNumber* rn1 = CRealNumber::obtain_from_generic(m_labels->get_label(y1_idx));
00136     float64_t ret = delta_loss(rn1->value, y2);
00137     SG_UNREF(rn1);
00138 
00139     return ret;
00140 }
00141 
00142 float64_t CMulticlassModel::delta_loss(float64_t y1, float64_t y2)
00143 {
00144     return (y1 == y2) ? 0 : 1;
00145 }
00146 
00147 void CMulticlassModel::init_opt(
00148         SGMatrix< float64_t > & A,
00149         SGVector< float64_t > a,
00150         SGMatrix< float64_t > B,
00151         SGVector< float64_t > & b,
00152         SGVector< float64_t > lb,
00153         SGVector< float64_t > ub,
00154         SGMatrix< float64_t > & C)
00155 {
00156     C = SGMatrix< float64_t >::create_identity_matrix(get_dim(), 1);
00157 }
00158 
00159 void CMulticlassModel::init()
00160 {
00161     SG_ADD(&m_num_classes, "m_num_classes", "The number of classes",
00162             MS_NOT_AVAILABLE);
00163 
00164     m_num_classes = 0;
00165 }
00166 
00167 float64_t CMulticlassModel::risk(float64_t* subgrad, float64_t* W, TMultipleCPinfo* info)
00168 {
00169     CDotFeatures* X=(CDotFeatures*)m_features;
00170     CMulticlassSOLabels* y=(CMulticlassSOLabels*)m_labels;
00171     m_num_classes = y->get_num_classes();
00172     uint32_t from, to;
00173 
00174     if (info)
00175     {
00176         from=info->_from;
00177         to=(info->N == 0) ? X->get_num_vectors() : from+info->N;
00178     } else {
00179         from=0;
00180         to=X->get_num_vectors();
00181     }
00182 
00183     uint32_t num_classes=y->get_num_classes();
00184     uint32_t feats_dim=X->get_dim_feature_space();
00185     const uint32_t w_dim=get_dim();
00186 
00187     float64_t R=0.0;
00188     for (uint32_t i=0; i<w_dim; i++)
00189         subgrad[i] = 0;
00190 
00191     float64_t Rtmp=0.0;
00192     float64_t Rmax=0.0;
00193     float64_t loss=0.0;
00194     uint32_t yhat=0;
00195     uint32_t GT=0;
00196     CRealNumber* GT_rn=NULL;
00197 
00198     /* loop through examples */
00199     for(uint32_t i=from; i<to; ++i)
00200     {
00201         Rmax=-CMath::INFTY;
00202         GT_rn=CRealNumber::obtain_from_generic(y->get_label(i));
00203         GT=(uint32_t)GT_rn->value;
00204 
00205         for (uint32_t c = 0; c < num_classes; ++c)
00206         {
00207             loss=(c == GT) ? 0.0 : 1.0;
00208             Rtmp=loss+X->dense_dot(i, W+c*feats_dim, feats_dim)
00209                 -X->dense_dot(i, W+GT*feats_dim, feats_dim);
00210 
00211             if (Rtmp > Rmax)
00212             {
00213                 Rmax=Rtmp;
00214                 yhat=c;
00215             }
00216         }
00217         R += Rmax;
00218 
00219         X->add_to_dense_vec(1.0, i, subgrad+yhat*feats_dim, feats_dim);
00220         X->add_to_dense_vec(-1.0, i, subgrad+GT*feats_dim, feats_dim);
00221 
00222         SG_UNREF(GT_rn);
00223     }
00224 
00225     return R;
00226 }
00227 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation