![]() |
GURLS++
2.0.00
C++ Implementation of GURLS Matlab Toolbox
|
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_