GURLS++  2.0.00
C++ Implementation of GURLS Matlab Toolbox
siglamhogpregr.h
00001 /*
00002  * The GURLS Package in C++
00003  *
00004  * Copyright (C) 2011-1013, IIT@MIT Lab
00005  * All rights reserved.
00006  *
00007  * authors:  M. Santoro
00008  * email:   msantoro@mit.edu
00009  * website: http://cbcl.mit.edu/IIT@MIT/IIT@MIT.html
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  *
00015  *     * Redistributions of source code must retain the above
00016  *       copyright notice, this list of conditions and the following
00017  *       disclaimer.
00018  *     * Redistributions in binary form must reproduce the above
00019  *       copyright notice, this list of conditions and the following
00020  *       disclaimer in the documentation and/or other materials
00021  *       provided with the distribution.
00022  *     * Neither the name(s) of the copyright holders nor the names
00023  *       of its contributors or of the Massacusetts Institute of
00024  *       Technology or of the Italian Institute of Technology may be
00025  *       used to endorse or promote products derived from this software
00026  *       without specific prior written permission.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00029  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00030  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00031  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00032  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00033  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00034  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00035  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00036  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00037  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00038  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00039  * POSSIBILITY OF SUCH DAMAGE.
00040  */
00041 
00042 
00043 #ifndef _GURLS_SIGLAMHOGPREGR_H_
00044 #define _GURLS_SIGLAMHOGPREGR_H_
00045 
00046 #include <cmath>
00047 
00048 
00049 #include "gurls++/options.h"
00050 #include "gurls++/optlist.h"
00051 #include "gurls++/gmat2d.h"
00052 #include "gurls++/gvec.h"
00053 #include "gurls++/gmath.h"
00054 
00055 #include "gurls++/paramsel.h"
00056 #include "gurls++/hogpregr.h"
00057 #include "gurls++/rbfkernel.h"
00058 
00059 namespace gurls {
00060 
00066 template <typename T>
00067 class ParamSelSiglamHoGPRegr: public ParamSelection<T>{
00068 
00069 public:
00073    GurlsOptionsList* execute(const gMat2D<T>& X, const gMat2D<T>& Y, const GurlsOptionsList& opt);
00074 };
00075 
00076 template <typename T>
00077 GurlsOptionsList* ParamSelSiglamHoGPRegr<T>::execute(const gMat2D<T>& X, const gMat2D<T>& Y, const GurlsOptionsList& opt)
00078 {
00079 //    [n,T]  = size(y);
00080     const unsigned long n = Y.rows();
00081     const unsigned long t = Y.cols();
00082 
00083     const unsigned long d = X.cols();
00084 
00085 
00086     GurlsOptionsList* nestedOpt = new GurlsOptionsList("nested");
00087     nestedOpt->copyOpt("nlambda", opt);
00088     nestedOpt->copyOpt("nholdouts", opt);
00089     nestedOpt->copyOpt("hoperf", opt);
00090     nestedOpt->copyOpt("split", opt);
00091     nestedOpt->copyOpt("singlelambda", opt);
00092 
00093 
00094 //    if ~isfield(opt,'kernel')
00095     if(!opt.hasOpt("kernel"))
00096     {
00097 //        opt.kernel.type = 'rbf';
00098         GurlsOptionsList* kernel = new GurlsOptionsList("kernel");
00099         kernel->addOpt("type", "rbf");
00100 
00101         nestedOpt->addOpt("kernel", kernel);
00102     }
00103     else
00104         nestedOpt->copyOpt("kernel", opt);
00105 
00106     GurlsOptionsList* kernel = nestedOpt->getOptAs<GurlsOptionsList>("kernel");
00107 
00108     gMat2D<T> *distance;
00109 
00110 //    if ~isfield(opt.kernel,'distance')
00111     if(!kernel->hasOpt("distance"))
00112     {
00113         distance = new gMat2D<T>(n, n);
00114 
00115 //        opt.kernel.distance = square_distance(X',X');
00116         distance_transposed(X.getData(), X.getData(), d, n, n, distance->getData());
00117 
00118         kernel->addOpt("distance", new OptMatrix<gMat2D<T> >(*distance));
00119     }
00120     else
00121         distance = &(kernel->getOptValue<OptMatrix<gMat2D<T> > >("distance"));
00122 
00123 
00124 //    if ~isfield(opt,'sigmamin')
00125     if(!opt.hasOpt("sigmamin"))
00126     {
00127         int d_len = n*(n-1)/2;
00128         T* distLinearized = new T[d_len];
00129 
00130 //        D = sort(opt.kernel.distance(tril(true(n),-1)));
00131 
00132         const unsigned long size = distance->cols();
00133         T* it = distLinearized;
00134         T* d_it = distance->getData();
00135 
00136         for(unsigned long i=1; i< size; ++i)
00137         {
00138             gurls::copy(it , d_it+i, size - i);
00139 
00140             it += size - i;
00141             d_it += size;
00142         }
00143 
00144         std::sort(distLinearized, distLinearized + d_len);
00145 
00146         //        firstPercentile = round(0.01*numel(D)+0.5);
00147         int firstPercentile = gurls::round((T)0.01 * d_len + (T)0.5)-1;
00148 
00149         //  opt.sigmamin = D(firstPercentile);
00150         nestedOpt->addOpt("sigmamin", new OptNumber(sqrt( distLinearized[firstPercentile]) ));
00151 
00152         delete [] distLinearized;
00153     }
00154     else
00155         nestedOpt->copyOpt("sigmamin", opt);
00156 
00157 
00158 //    if ~isfield(opt,'sigmamax')
00159     if(!opt.hasOpt("sigmamax"))
00160     {
00161 //        opt.sigmamax = sqrt(max(max(opt.kernel.distance)));
00162         double sigmaMax = sqrt(*std::max_element(distance->getData(), distance->getData()+distance->getSize()));
00163         nestedOpt->addOpt("sigmamax", new OptNumber(sigmaMax));
00164     }
00165     else
00166         nestedOpt->copyOpt("sigmamax", opt);
00167 
00168 
00169 
00170 //    if opt.sigmamin <= 0
00171     if( le(nestedOpt->getOptAsNumber("sigmamin"), 0.0))
00172     {
00173 //        opt.sigmamin = eps;
00174         nestedOpt->removeOpt("sigmamin");
00175         nestedOpt->addOpt("sigmamin", new OptNumber(std::numeric_limits<T>::epsilon()));
00176     }
00177 
00178 //    if opt.sigmamax <= 0
00179     if( le(nestedOpt->getOptAsNumber("sigmamax"), 0.0) )
00180     {
00181 //        opt.sigmamax = eps;
00182         nestedOpt->removeOpt("sigmamax");
00183         nestedOpt->addOpt("sigmamax", new OptNumber(std::numeric_limits<T>::epsilon()));
00184     }
00185 
00186     const int nsigma = static_cast<int>(opt.getOptAsNumber("nsigma"));
00187     const int nlambda = static_cast<int>(opt.getOptAsNumber("nlambda"));
00188     const T sigmamin = static_cast<T>(nestedOpt->getOptAsNumber("sigmamin"));
00189 
00190 //    q = (opt.sigmamax/opt.sigmamin)^(1/(opt.nsigma-1));
00191     T q = static_cast<T>(std::pow(nestedOpt->getOptAsNumber("sigmamax")/nestedOpt->getOptAsNumber("sigmamin"), 1.0/(nsigma-1.0)));
00192 
00193 //    PERF = zeros(opt.nsigma,opt.nlambda,T);
00194     T* perf = new T[nsigma*nlambda];
00195     set(perf, (T)0.0, nsigma*nlambda);
00196 
00197 //    sigmas = zeros(1,opt.nsigma);
00198 //    T* sigmas = new T[nsigma];
00199 
00200     T* guesses = new T[nsigma*nlambda];
00201 
00202     KernelRBF<T> rbf;
00203     ParamSelHoGPRegr<T> hogp;
00204 
00205 
00206     GurlsOptionsList* paramsel_rbf = new GurlsOptionsList("paramsel");
00207     nestedOpt->addOpt("paramsel", paramsel_rbf);
00208 
00209     T* perf_median = new T[nlambda*t];
00210     T* guesses_median = new T[nlambda];
00211 
00212     const unsigned long nholdouts = static_cast<unsigned long>(opt.getOptAsNumber("nholdouts"));
00213     T* work = new T[std::max(nholdouts, t)];
00214 
00215 //    for i = 1:opt.nsigma
00216     for(int i=0; i<nsigma; ++i)
00217     {
00218 //        sigmas(i) = (opt.sigmamin*(q^(i-1)));
00219         const T sigma = sigmamin* std::pow(q, i);
00220 
00221 //        opt.paramsel.sigma = sigmas(i);
00222         paramsel_rbf->removeOpt("sigma");
00223         paramsel_rbf->addOpt("sigma", new OptNumber(sigma));
00224 
00225 
00226 //        opt.kernel = kernel_rbf(X,y,opt);
00227         GurlsOptionsList* rbf_kernel = rbf.execute(X, Y, *nestedOpt);
00228 
00229         nestedOpt->removeOpt("kernel");
00230         nestedOpt->addOpt("kernel", rbf_kernel);
00231 
00232 
00233 //        paramsel = paramsel_hogpregr(X,y,opt);
00234         GurlsOptionsList* paramsel_hogp = hogp.execute(X, Y, *nestedOpt);
00235 
00236 
00237 //        PERF(i,:,:) = reshape(median(reshape(cell2mat(paramsel.perf')',opt.nlambda*T,nh),2),T,opt.nlambda)';
00238         gMat2D<T> &perf_mat = paramsel_hogp->getOptValue<OptMatrix<gMat2D<T> > >("perf"); //nholdouts x nlambda*t
00239         median(perf_mat.getData(), perf_mat.rows(), perf_mat.cols(), 1, perf_median, work);
00240 
00241         T* perf_it = perf + i;
00242         for(int j=0; j<nlambda; ++j, perf_it += nsigma)
00243         {
00244             getRow(perf_median, nlambda, t, j, work);
00245 
00246             *perf_it = sumv(work, t);
00247         }
00248 
00249 //        guesses(i,:) = median(cell2mat(paramsel.guesses'),1);
00250         gMat2D<T> &guesses_mat = paramsel_hogp->getOptValue<OptMatrix<gMat2D<T> > >("guesses"); // nholdouts x nlambda
00251         median(guesses_mat.getData(), guesses_mat.rows(), guesses_mat.cols(), 1, guesses_median, work);
00252         copy(guesses+i, guesses_median, nlambda, nsigma, 1);
00253 
00254         delete paramsel_hogp;
00255     }
00256 
00257     delete [] perf_median;
00258     delete [] guesses_median;
00259     delete [] work;
00260 
00261     delete nestedOpt;
00262 
00263 
00264 //    M = sum(PERF,3); % sum over classes
00265 
00266 //    [dummy,i] = max(M(:));
00267     int i = std::max_element(perf, perf +(nsigma*nlambda)) - perf;
00268 
00269 //    [m,n] = ind2sub(size(M),i);
00270     int im = i%nsigma;
00271 
00272     delete[] perf;
00273 
00274     GurlsOptionsList* paramsel = new GurlsOptionsList("paramsel");
00275 
00276 //    % opt sigma
00277 //    vout.sigma = opt.sigmamin*(q^(m-1));
00278     paramsel->addOpt("sigma", new OptNumber( sigmamin*(std::pow(q, im))) );
00279 
00280 //    % opt lambda
00281 //    vout.noises = guesses(m,n)*ones(1,T);
00282 
00283     gMat2D<T> *lambdas = new gMat2D<T>(1, t);
00284     set(lambdas->getData(), guesses[i], t);
00285 
00286     paramsel->addOpt("lambdas", new OptMatrix<gMat2D<T> >(*lambdas));
00287 
00288     delete[] guesses;
00289 
00290     return paramsel;
00291 }
00292 
00293 
00294 }
00295 
00296 #endif // _GURLS_SIGLAMHOGPREGR_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends