![]() |
GURLS++
2.0.00
C++ Implementation of GURLS Matlab Toolbox
|
00001 00002 00003 /* 00004 * The GURLS Package in C++ 00005 * 00006 * Copyright (C) 2011-1013, IIT@MIT Lab 00007 * All rights reserved. 00008 * 00009 * authors: M. Santoro 00010 * email: msantoro@mit.edu 00011 * website: http://cbcl.mit.edu/IIT@MIT/IIT@MIT.html 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions 00015 * are met: 00016 * 00017 * * Redistributions of source code must retain the above 00018 * copyright notice, this list of conditions and the following 00019 * disclaimer. 00020 * * Redistributions in binary form must reproduce the above 00021 * copyright notice, this list of conditions and the following 00022 * disclaimer in the documentation and/or other materials 00023 * provided with the distribution. 00024 * * Neither the name(s) of the copyright holders nor the names 00025 * of its contributors or of the Massacusetts Institute of 00026 * Technology or of the Italian Institute of Technology may be 00027 * used to endorse or promote products derived from this software 00028 * without specific prior written permission. 00029 * 00030 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00031 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00032 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00033 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00034 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00035 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00036 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00037 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00038 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00039 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00040 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00041 * POSSIBILITY OF SUCH DAMAGE. 00042 */ 00043 00044 00045 #ifndef _GURLS_HODUAL_H_ 00046 #define _GURLS_HODUAL_H_ 00047 00048 #include <cstdio> 00049 #include <cstring> 00050 #include <iostream> 00051 #include <cmath> 00052 #include <algorithm> 00053 #include <set> 00054 00055 #include "gurls++/options.h" 00056 #include "gurls++/optlist.h" 00057 #include "gurls++/gmat2d.h" 00058 #include "gurls++/gvec.h" 00059 #include "gurls++/gmath.h" 00060 00061 #include "gurls++/paramsel.h" 00062 #include "gurls++/perf.h" 00063 #include "gurls++/dual.h" 00064 00065 namespace gurls { 00066 00072 template <typename T> 00073 class ParamSelHoDual: public ParamSelection<T>{ 00074 00075 public: 00094 GurlsOptionsList* execute(const gMat2D<T>& X, const gMat2D<T>& Y, const GurlsOptionsList& opt); 00095 00096 protected: 00100 virtual void eig_function(T* A, T* L, int A_rows_cols, unsigned long n, const GurlsOptionsList &opt); 00101 00102 virtual unsigned long getRank(unsigned long last, unsigned long n, unsigned long d, bool linearKernel, const GurlsOptionsList &opt); 00103 }; 00104 00105 00111 template <typename T> 00112 class ParamSelHoDualr: public ParamSelHoDual<T>{ 00113 00114 protected: 00118 virtual void eig_function(T* A, T* L, int A_rows_cols, unsigned long n, const GurlsOptionsList &opt); 00119 00120 virtual unsigned long getRank(unsigned long last, unsigned long n, unsigned long d, bool linearKernel, const GurlsOptionsList &opt); 00121 }; 00122 00123 00124 00125 00126 template<typename T> 00127 void ParamSelHoDual<T>::eig_function(T* A, T* L, int A_rows_cols, unsigned long , const GurlsOptionsList &) 00128 { 00129 eig_sm(A, L, A_rows_cols); 00130 } 00131 00132 template<typename T> 00133 void ParamSelHoDualr<T>::eig_function(T* A, T* L, int A_rows_cols, unsigned long n, const GurlsOptionsList &opt) 00134 { 00135 T* V = NULL; 00136 unsigned long k = static_cast<unsigned long>(gurls::round((opt.getOptAsNumber("eig_percentage")*n)/100.0)); 00137 random_svd(A, A_rows_cols, A_rows_cols, A, L, V, k); 00138 } 00139 00140 template<typename T> 00141 unsigned long ParamSelHoDual<T>::getRank(unsigned long last, unsigned long , unsigned long d, bool linearKernel, const GurlsOptionsList &) 00142 { 00143 if(linearKernel) 00144 return std::min<unsigned long> (last,d); 00145 else 00146 return last; 00147 } 00148 00149 template<typename T> 00150 unsigned long ParamSelHoDualr<T>::getRank(unsigned long , unsigned long n, unsigned long , bool , const GurlsOptionsList &opt) 00151 { 00152 return static_cast<unsigned long>(gurls::round((opt.getOptAsNumber("eig_percentage")*n)/100.0)); 00153 } 00154 00155 template <typename T> 00156 GurlsOptionsList *ParamSelHoDual<T>::execute(const gMat2D<T>& X, const gMat2D<T>& Y, const GurlsOptionsList &opt) 00157 { 00158 // [n,T] = size(y); 00159 const unsigned long n = Y.rows(); 00160 const unsigned long t = Y.cols(); 00161 00162 const unsigned long x_rows = X.rows(); 00163 const unsigned long d = X.cols(); 00164 00165 00166 GurlsOptionsList* nestedOpt = new GurlsOptionsList("nested"); 00167 nestedOpt->copyOpt("kernel", opt); 00168 00169 nestedOpt->addOpt("predkernel", new GurlsOptionsList("predkernel")); 00170 00171 00172 const GurlsOptionsList* split = opt.getOptAs<GurlsOptionsList>("split"); 00173 00174 const gMat2D< unsigned long > &indices_mat = split->getOptValue<OptMatrix<gMat2D< unsigned long > > >("indices"); 00175 const gMat2D< unsigned long > &lasts_mat = split->getOptValue<OptMatrix<gMat2D< unsigned long > > >("lasts"); 00176 00177 const unsigned long *lasts = lasts_mat.getData(); 00178 const unsigned long* indices_buffer = indices_mat.getData(); 00179 00180 00181 const GurlsOptionsList* kernel = opt.getOptAs<GurlsOptionsList>("kernel"); 00182 const gMat2D<T> &K = kernel->getOptValue<OptMatrix<gMat2D<T> > >("K"); 00183 const bool linearKernel = kernel->getOptAsString("type") == "linear"; 00184 00185 const unsigned long k_rows = K.rows(); 00186 00187 int tot = static_cast<int>(std::ceil( opt.getOptAsNumber("nlambda"))); 00188 int nholdouts = static_cast<int>(std::ceil( opt.getOptAsNumber("nholdouts"))); 00189 00190 gMat2D<T> *LAMBDA = new gMat2D<T>(1, t); 00191 T* lambdas = LAMBDA->getData(); 00192 set(lambdas, (T)0.0, t); 00193 00194 gMat2D<T>* acc_avg_mat = new gMat2D<T>(tot, t); 00195 T* acc_avg = acc_avg_mat->getData(); 00196 set(acc_avg, (T)0.0, tot*t); 00197 00198 // for nh = 1:opt.nholdouts 00199 GurlsOptionsList* optimizer = new GurlsOptionsList("optimizer"); 00200 00201 Performance<T>* perfClass = Performance<T>::factory(opt.getOptAsString("hoperf")); 00202 PredDual<T> dual; 00203 00204 nestedOpt->addOpt("optimizer",optimizer); 00205 00206 gMat2D<T>* perf_mat = new gMat2D<T>(nholdouts, tot*t); 00207 T* perf = perf_mat->getData(); 00208 00209 gMat2D<T>* guesses_mat = new gMat2D<T>(nholdouts, tot); 00210 T* ret_guesses = guesses_mat->getData(); 00211 00212 gMat2D<T>* lambdas_round_mat = new gMat2D<T>(nholdouts, t); 00213 T* lambdas_round = lambdas_round_mat->getData(); 00214 00215 for(int nh=0; nh<nholdouts; ++nh) 00216 { 00217 unsigned long last = lasts[nh]; 00218 unsigned long* tr = new unsigned long[last]; 00219 unsigned long* va = new unsigned long[n-last]; 00220 00221 //copy int tr indices_ from n*nh to last 00222 copy<unsigned long>(tr,indices_buffer + n*nh, last); 00223 //copy int va indices_ from n*nh+last to n*nh+n 00224 copy<unsigned long>(va,(indices_buffer+ n*nh+last), n-last); 00225 00226 00227 //Get K(tr,tr) from K 00228 T* Q = new T[last*last]; 00229 copy_submatrix(Q, K.getData(), k_rows, last, last, tr, tr); 00230 00231 T *L = new T[last]; 00232 eig_function(Q, L, last, n, opt); 00233 00234 unsigned long r = getRank(last, n, d, linearKernel, opt); 00235 00236 if(!linearKernel) 00237 { 00238 // opt.predkernel.K = opt.kernel.K(va,tr);%nva x ntr 00239 gMat2D<T>* predK = new gMat2D<T>(n-last, last); 00240 00241 copy_submatrix(predK->getData(), K.getData(), k_rows, n-last, last, va, tr); 00242 00243 GurlsOptionsList* predkernel = nestedOpt->getOptAs<GurlsOptionsList>("predkernel"); 00244 00245 predkernel->removeOpt("K"); 00246 predkernel->addOpt("K", new OptMatrix<gMat2D<T> >(*predK)); 00247 } 00248 00249 T* guesses = lambdaguesses(L, last, r, last, tot, (T)(opt.getOptAsNumber("smallnumber"))); 00250 00251 // ap = zeros(tot,T); 00252 T* ap = new T[tot*t]; 00253 00254 T* Ytr = new T[last*t]; 00255 subMatrixFromRows(Y.getData(), n, t, tr, last, Ytr); 00256 00257 // QtY = Q'*y(tr,:); 00258 T* Qty = new T[last*t]; 00259 00260 dot(Q, Ytr, Qty, last, last, last, t, last, t, CblasTrans, CblasNoTrans, CblasColMajor); 00261 00262 delete [] Ytr; 00263 00264 // for i = 1:tot 00265 // opt.rls.X = X(tr,:); 00266 00267 gMat2D<T>* rlsX = new gMat2D<T>(last, d); 00268 subMatrixFromRows(X.getData(), x_rows, d, tr, last, rlsX->getData()); 00269 00270 delete [] tr; 00271 00272 optimizer->removeOpt("X"); 00273 optimizer->addOpt("X", new OptMatrix<gMat2D<T> >(*rlsX)); 00274 00275 00276 gMat2D<T>* xx = new gMat2D<T>(n-last, d); 00277 subMatrixFromRows(X.getData(), x_rows, d, va, n-last, xx->getData()); 00278 00279 gMat2D<T>* yy = new gMat2D<T>(n-last, t); 00280 subMatrixFromRows(Y.getData(), n, t, va, n-last, yy->getData()); 00281 00282 delete [] va; 00283 00284 gMat2D<T>* C = new gMat2D<T>(last, t); 00285 optimizer->removeOpt("C"); 00286 optimizer->addOpt("C", new OptMatrix<gMat2D<T> >(*C)); 00287 00288 00289 gMat2D<T>* W = NULL; 00290 00291 if(linearKernel) 00292 { 00293 W = new gMat2D<T>(d, t); 00294 00295 optimizer->removeOpt("W"); 00296 optimizer->addOpt("W", new OptMatrix<gMat2D<T> >(*W)); 00297 } 00298 00299 T* work = new T[last*(last+1)]; 00300 00301 for(int i=0; i<tot; ++i) 00302 { 00303 // opt.rls.C = rls_eigen(Q,L,QtY,guesses(i),ntr); 00304 rls_eigen(Q, L, Qty, C->getData(), guesses[i], last, last, last, last, last, t, work); 00305 00306 if(linearKernel) 00307 { 00308 // opt.rls.W = X(tr,:)'*opt.rls.C; % dxT = (ntrxd)'*ntrxT last*d last*last 00309 dot(rlsX->getData(), C->getData(), W->getData(), last, d, last, t, d, t, CblasTrans, CblasNoTrans, CblasColMajor); 00310 } 00311 // else 00312 // opt.predkernel.K = opt.kernel.K(va,tr);%nva x ntr 00313 // (see above) 00314 00315 00316 OptMatrix<gMat2D<T> >* ret_pred = dual.execute(*xx, *yy, *nestedOpt); 00317 00318 nestedOpt->addOpt("pred", ret_pred); 00319 00320 // opt.perf = opt.hoperf(Xva,yva,opt); 00321 GurlsOptionsList* ret_perf = perfClass->execute(*xx, *yy, *nestedOpt); 00322 00323 gMat2D<T> &forho_vec = ret_perf->getOptValue<OptMatrix<gMat2D<T> > >("forho"); 00324 00325 // for t = 1:T 00326 // ap(i,t) = opt.perf.forho(t); 00327 copy(ap+i, forho_vec.getData(), t, tot, 1); 00328 00329 nestedOpt->removeOpt("pred"); 00330 00331 delete ret_perf; 00332 00333 }//for tot 00334 00335 delete [] Q; 00336 delete [] Qty; 00337 delete [] L; 00338 delete [] work; 00339 00340 delete xx; 00341 delete yy; 00342 00343 //[dummy,idx] = max(ap,[],1); 00344 work = NULL; 00345 unsigned long* idx = new unsigned long[t]; 00346 indicesOfMax(ap, tot, t, idx, work, 1); 00347 00348 00349 //vout.lambdas_round{nh} = guesses(idx); 00350 T* lambdas_nh = new T[t]; 00351 copyLocations(idx, guesses, t, tot, lambdas_nh); 00352 00353 copy(lambdas_round +nh, lambdas_nh, t, nholdouts, 1); 00354 00355 //add lambdas_nh to lambdas 00356 axpy< T >(t, (T)1, lambdas_nh, 1, lambdas, 1); 00357 00358 delete [] lambdas_nh; 00359 delete [] idx; 00360 00361 // vout.perf{nh} = ap; 00362 copy(perf + nh, ap, tot*t, nholdouts, 1); 00363 00364 axpy(tot*t, (T)1, ap, 1, acc_avg, 1); 00365 00366 // vout.guesses{nh} = guesses; 00367 copy(ret_guesses + nh, guesses, tot, nholdouts, 1); 00368 00369 delete [] guesses; 00370 delete [] ap; 00371 }//for nholdouts 00372 00373 delete nestedOpt; 00374 delete perfClass; 00375 00376 00377 GurlsOptionsList* paramsel; 00378 00379 if(opt.hasOpt("paramsel")) 00380 { 00381 GurlsOptionsList* tmp_opt = new GurlsOptionsList("tmp"); 00382 tmp_opt->copyOpt("paramsel", opt); 00383 00384 paramsel = GurlsOptionsList::dynacast(tmp_opt->getOpt("paramsel")); 00385 tmp_opt->removeOpt("paramsel", false); 00386 delete tmp_opt; 00387 00388 paramsel->removeOpt("perf"); 00389 paramsel->removeOpt("guesses"); 00390 paramsel->removeOpt("acc_avg"); 00391 paramsel->removeOpt("lambdas"); 00392 paramsel->removeOpt("lambdas_round"); 00393 } 00394 else 00395 paramsel = new GurlsOptionsList("paramsel"); 00396 00397 00398 00399 paramsel->addOpt("perf", new OptMatrix<gMat2D<T> >(*perf_mat)); 00400 paramsel->addOpt("guesses", new OptMatrix<gMat2D<T> >(*guesses_mat)); 00401 00402 // if numel(vout.lambdas_round) > 1 00403 // lambdas = cell2mat(vout.lambdas_round'); 00404 // vout.lambdas = mean(lambdas); 00405 // else 00406 // vout.lambdas = vout.lambdas_round{1}; 00407 // end 00408 if(nholdouts>1) 00409 { 00410 scal(t, (T)1.0/nholdouts, lambdas, 1); 00411 scal(t, (T)1.0/nholdouts, acc_avg, 1); 00412 } 00413 00414 paramsel->addOpt("acc_avg", new OptMatrix<gMat2D<T> >(*acc_avg_mat)); 00415 00416 00417 paramsel->addOpt("lambdas", new OptMatrix<gMat2D<T> >(*LAMBDA)); 00418 paramsel->addOpt("lambdas_round", new OptMatrix<gMat2D<T> >(*lambdas_round_mat)); 00419 00420 return paramsel; 00421 } 00422 00423 00424 } 00425 00426 #endif // _GURLS_HODUAL_H_