![]() |
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 * author: 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 00048 #ifndef _GURLS_UTILS_H_ 00049 #define _GURLS_UTILS_H_ 00050 00051 #include <map> 00052 #include <algorithm> 00053 00054 #include "gurls++/gmath.h" 00055 #include "gurls++/gmat2d.h" 00056 00057 #include "gurls++/optlist.h" 00058 #include "gurls++/optfunction.h" 00059 #include "gurls++/optmatrix.h" 00060 00061 #include "gurls++/primal.h" 00062 #include "gurls++/macroavg.h" 00063 00064 #include <set> 00065 00066 #include <boost/random/normal_distribution.hpp> 00067 #include <boost/random/mersenne_twister.hpp> 00068 00069 namespace gurls { 00070 00075 template<typename T> 00076 class LtCompare{ 00077 public: 00078 bool operator()(const T&a, const T&b){ return gurls::lt(a, b);} 00079 }; 00080 00091 template <typename T> 00092 T precrec_driver(const T* out, const T* gt, const unsigned long N, T* work) 00093 { 00094 std::multimap<T, T, LtCompare<T> > data; 00095 00096 for (unsigned long i = 0; i < N; i++) 00097 data.insert(std::pair<T,T>(-out[i], gt[i])); 00098 00099 typename std::multimap<T, T, LtCompare<T> >::iterator it = data.begin(); 00100 typename std::multimap<T, T, LtCompare<T> >::iterator end = data.end(); 00101 00102 00103 T* tp = work; 00104 T* fp = tp+N; 00105 T* prec = fp+N; 00106 T* rec = prec+N; 00107 00108 unsigned long tpcumsum = 0; 00109 unsigned long fpcumsum = 0; 00110 00111 unsigned long idx = 0; 00112 while (it != end) 00113 { 00114 tp[idx] = static_cast<T>(gurls::gt(it->second, (T)0.0) ? tpcumsum+=1 : tpcumsum); 00115 fp[idx] = static_cast<T>(gurls::lt(it->second, (T)0.0) ? fpcumsum+=1 : fpcumsum); 00116 00117 ++it; 00118 ++idx; 00119 } 00120 00121 for (idx = 0; idx < N; ++idx) 00122 { 00123 rec[idx] = tp[idx]/(T)tpcumsum; 00124 prec[idx] = tp[idx]/(tp[idx]+fp[idx]); 00125 } 00126 00127 // compute average precision 00128 T ap = 0.0; 00129 T p = 0.0; 00130 T t = 0.0; 00131 00132 LtCompare<T> comp; 00133 00134 const int stepsNumber = 11; 00135 const T incr = static_cast<T>(0.1); 00136 00137 for(int steps = 0; steps<stepsNumber; ++steps) 00138 { 00139 p = 0.0; 00140 for (idx = 0; idx < N; ++idx) 00141 { 00142 if ( gurls::gt(rec[idx], t) || gurls::eq(rec[idx], t)) 00143 p = std::max<T, LtCompare<T> >(p, prec[idx], comp); 00144 } 00145 ap += p; 00146 t += incr; 00147 } 00148 00149 return ap/((T)stepsNumber); 00150 } 00151 00161 template <typename T> 00162 T precrec_driver(const T* out, const T* gt, const unsigned long N) 00163 { 00164 T* work = new T[4*N]; 00165 00166 T ret = precrec_driver(out, gt, N, work); 00167 00168 delete [] work; 00169 00170 return ret; 00171 } 00172 00191 template <typename T> 00192 GurlsOptionsList* rls_pegasos_driver(const T* X, const T* bY, const GurlsOptionsList& opt, 00193 const int X_rows, const int X_cols, 00194 const int bY_rows, const int bY_cols) 00195 { 00196 // lambda = opt.singlelambda(opt.paramsel.lambdas); 00197 const gMat2D<T> &ll = opt.getOptValue<OptMatrix<gMat2D<T> > >("paramsel.lambdas"); 00198 T lambda = opt.getOptAs<OptFunction>("singlelambda")->getValue(ll.getData(), ll.getSize()); 00199 00200 00201 // [n,d] = size(X); 00202 const int n = X_rows; 00203 const int d = X_cols; 00204 00205 // [T] = size(bY,2); 00206 const int t = bY_cols; 00207 00208 00209 // cfr = opt.cfr; 00210 00211 // W = cfr.W; %dxT 00212 const GurlsOptionsList* optimizer = opt.getOptAs<GurlsOptionsList>("optimizer"); 00213 00214 const gMat2D<T> &W_mat = optimizer->getOptValue<OptMatrix<gMat2D<T> > >("W"); 00215 gMat2D<T> *W = new gMat2D<T>(W_mat.rows(), W_mat.cols()); 00216 copy(W->getData(), W_mat.getData(), W_mat.getSize()); 00217 00218 // W_sum = cfr.W_sum; 00219 const gMat2D<T> &W_sum_mat = optimizer->getOptValue<OptMatrix<gMat2D<T> > >("W_sum"); 00220 gMat2D<T> *W_sum = new gMat2D<T>(W_sum_mat.rows(), W_sum_mat.cols()); 00221 copy(W_sum->getData(), W_sum_mat.getData(), W_sum_mat.getSize()); 00222 00223 // count = cfr.count; 00224 int count = static_cast<int>(optimizer->getOptAsNumber("count")); 00225 00226 // t0 = cfr.t0; 00227 T t0 = static_cast<T>(optimizer->getOptAsNumber("t0")); 00228 00229 00230 unsigned long * seq = new unsigned long[n]; 00231 T* xt = new T[d]; 00232 T* y_hat = new T[t]; 00233 T* r = new T[t]; 00234 const int W_size = d*t; 00235 T* xtr = new T[W_size]; 00236 00237 // %% Initialization 00238 // iter = 0; 00239 int iter; 00240 00241 const T thr = sqrt(t/lambda); 00242 00243 // seq = randperm(n); 00244 randperm(n, seq); 00245 00246 for(iter = 0; iter<n; ++iter) 00247 { 00248 // while iter < n, 00249 // iter = iter + 1; 00250 // idx = seq(iter); 00251 const unsigned long idx = seq[iter]; 00252 00253 // %% Stepsize 00254 00255 // %% Update Equations 00256 // xt = X(idx,:); %1xd 00257 getRow(X, n, d, idx, xt); 00258 00259 // y_hat = (xt*W); %1xT 00260 dot(xt, W->getData(), y_hat, 1, d, d, t, 1, t, CblasNoTrans, CblasNoTrans, CblasColMajor); 00261 00262 // r = bY(idx,:) - y_hat; %1xT 00263 getRow(bY, bY_rows, t, idx, r); 00264 axpy(t, (T)-1.0, y_hat, 1, r, 1); 00265 00266 00267 // eta = 1.0/(lambda*(count + t0)); 00268 const T eta = ((T)1.0)/(lambda*(count + t0)); 00269 00270 // W = (1 - lambda*eta)*W + eta*xt'*r; %dxT 00271 const T coeff = (T)1.0 - (lambda*eta); 00272 00273 scal(W_size, coeff, W->getData(), 1); 00274 00275 dot(xt, r, xtr, d, 1, 1, t, d, t, CblasNoTrans, CblasNoTrans, CblasColMajor); 00276 00277 axpy(W_size, eta, xtr, 1, W->getData(), 1); 00278 00279 // %% Projection onto the ball with radius sqrt(T/lambda) 00280 // nW = norm(W,'fro'); %Frobenius norm 00281 00282 T tmp = dot(W_size, W->getData(), 1, W->getData(), 1); 00283 T nW = sqrt(tmp); 00284 00285 00286 // if nW > sqrt(T/lambda) 00287 if( gt(nW, thr) ) 00288 { 00289 // W = (W/nW)*sqrt(T/lambda); 00290 set(xtr, (T)0.0, W_size); 00291 axpy(W_size, thr/nW, W->getData(), 1, xtr, 1); 00292 copy(W->getData(), xtr, W_size); 00293 } 00294 00295 // %% Averaging 00296 00297 // W_sum = W_sum + W; 00298 axpy(W_size, (T)1.0, W->getData(), 1, W_sum->getData(), 1); 00299 00300 // count = count + 1; 00301 ++count; 00302 00303 // %% Testing 00304 // if(mod(count,n) == 1) 00305 // fprintf('\n\tObjective : %f',obj_primal(W, X, bY, lambda)); 00306 // cfr.acc_last(end+1) = test_classifier (W,opt); 00307 // fprintf('\n\tLast Acc: %f', cfr.acc_last(end)); 00308 // cfr.acc_avg(end+1) = test_classifier (W_sum/count,opt); 00309 // fprintf('\n\tAvg Acc: %f\n', cfr.acc_avg(end)); 00310 // end 00311 00312 } 00313 00314 delete[] seq; 00315 delete[] xt; 00316 delete[] y_hat; 00317 delete[] r; 00318 delete[] xtr; 00319 00320 GurlsOptionsList* ret = new GurlsOptionsList("optimizer"); 00321 00322 // cfr.W = W; 00323 ret->addOpt("W", new OptMatrix<gMat2D<T> >(*W)); 00324 00325 // cfr.W_last = W; 00326 00327 // cfr.W_sum = W_sum; 00328 ret->addOpt("W_sum", new OptMatrix<gMat2D<T> >(*W_sum)); 00329 00330 // cfr.count = count; 00331 ret->addOpt("count", new OptNumber(count)); 00332 00333 // cfr.iter = iter; 00334 ret->addOpt("iter", new OptNumber(iter)); 00335 00336 ret->addOpt("t0", new OptNumber(t0)); 00337 00338 // cfr.C = []; 00339 gMat2D<T>* emptyC = new gMat2D<T>(); 00340 ret->addOpt("C", new OptMatrix<gMat2D<T> >(*emptyC)); 00341 00342 // cfr.X = []; 00343 gMat2D<T>* emptyX = new gMat2D<T>(); 00344 ret->addOpt("X", new OptMatrix<gMat2D<T> >(*emptyX)); 00345 00346 return ret; 00347 00348 } 00349 00350 00363 // function [acc] = test_classifier (W, opt) 00364 template <typename T> 00365 T test_classifier(T* W, GurlsOptionsList& opt, const int rows, const int cols) 00366 { 00367 //opt.rls.W = W; 00368 00369 GurlsOptionsList* optimizer = GurlsOptionsList::dynacast(opt.getOpt("optimizer")); 00370 00371 gMat2D<T> *W_mat = NULL; 00372 if(!optimizer->hasOpt("W")) 00373 { 00374 W_mat = new gMat2D<T>(rows,cols); 00375 optimizer->addOpt("W", new OptMatrix<gMat2D<T> >(*W_mat)); 00376 } 00377 else 00378 { 00379 GurlsOption *W_opt = optimizer->getOpt("W"); 00380 W_mat = &(OptMatrix<gMat2D<T> >::dynacast(W_opt))->getValue(); 00381 } 00382 00383 gMat2D<T> W_t(W, W_mat->cols(), W_mat->rows(), false); 00384 W_t.transpose(*W_mat); 00385 00386 GurlsOption *x = opt.getOpt("Xte"); 00387 gMat2D<T>* X = &(OptMatrix< gMat2D<T> >::dynacast(x))->getValue(); 00388 GurlsOption *y = opt.getOpt("yte"); 00389 gMat2D<T>* Y = &(OptMatrix< gMat2D<T> >::dynacast(y))->getValue(); 00390 00391 //opt.pred = pred_primal(opt.Xte, opt.yte, opt); 00392 PredPrimal<T> pp; 00393 pp.execute(*X, *Y, opt); 00394 00395 //opt.perf = perf_macroavg(opt.Xte, opt.yte, opt); 00396 PerfMacroAvg<T> ma; 00397 ma.execute(*X, *Y, opt); 00398 00399 //acc = mean([opt.perf.acc]); 00400 GurlsOptionsList* perf = GurlsOptionsList::dynacast(opt.getOpt("perf")); 00401 GurlsOption *perf_opt = perf->getOpt("acc"); 00402 gMat2D<T> *acc_mat = &(OptMatrix<gMat2D<T> >::dynacast(perf_opt))->getValue(); 00403 00404 T res; 00405 mean<T>(acc_mat->getData(), &res, 1, acc_mat->getSize(), 1); 00406 00407 return res; 00408 } 00409 00421 template <typename T> 00422 void distance(const T* A, const T* B, const int rows, const int A_cols, const int B_cols, T* D) 00423 { 00424 set(D, (T)0.0, A_cols*B_cols); 00425 00426 //for i = 1:na 00427 for(int i=0; i< A_cols; ++i) 00428 // for j = 1:nb 00429 for(int j=0; j< B_cols; ++j) 00430 // for k = 1:dim_a 00431 for(int k=0; k<rows; ++k) 00432 { 00433 // d(i,j) = d(i,j) + (a(k,i) - b(k,j))^2; 00434 const double diff = A[k+rows*i]-B[k+rows*j]; 00435 D[i+A_cols*j] += diff*diff; 00436 } 00437 00438 } 00439 00450 template <typename T> 00451 void distance_transposed(const T* A, const T* B, const int cols, const int A_rows, const int B_rows, T* D) 00452 { 00453 set(D, (T)0.0, A_rows*B_rows); 00454 00455 for(int i=0; i< A_rows; ++i) 00456 for(int j=0; j< B_rows; ++j) 00457 for(int k=0; k<cols; ++k) 00458 { 00459 // d(i,j) = d(i,j) + (a(i,k) - b(j,k))^2; 00460 const T diff = A[i+A_rows*k]-B[j+B_rows*k]; 00461 D[i+A_rows*j] += diff*diff; 00462 } 00463 00464 } 00465 00477 template <typename T> 00478 void distance_transposed_vm(const T* A, const T* B, const int cols, const int B_rows, T* D, const int size, const int incrA = 1) 00479 { 00480 int j; 00481 00482 //#pragma omp parallel for private(j) 00483 for(j=0; j< size; ++j) 00484 { 00485 const T* B_it = B+j; 00486 const T* A_it = A; 00487 00488 T Dj = 0; 00489 00490 for(int k=0; k<cols; ++k) 00491 { 00492 // d(j) = d(j) + (a(k) - b(j,k))^2; 00493 const T diff = *A_it - *B_it; 00494 Dj += diff*diff; 00495 00496 A_it += incrA; 00497 B_it += B_rows; 00498 } 00499 00500 D[j] = Dj; 00501 } 00502 } 00503 00504 00519 template <typename T> 00520 void random_svd(const T* A, const unsigned long A_rows, const unsigned long A_cols, 00521 T* U, T* S, T* V, 00522 unsigned long k = 6, unsigned long its = 2, unsigned long l = 0) 00523 { 00524 // U: (A_rows,k) 00525 // S: (k) 00526 // V: (A_cols, k) 00527 00528 if(l < k) 00529 l = k+2; 00530 00531 if((k > A_rows) || (k > A_cols)) 00532 throw gException("k must be <= the smallest dimension of A"); 00533 00534 // % 00535 // % SVD A directly if (its+1)*l >= m/1.25 or (its+1)*l >= n/1.25. 00536 // % 00537 00538 // if(((its+1)*l >= m/1.25) || ((its+1)*l >= n/1.25)) 00539 00540 const T thr1 = static_cast<T>(A_rows/1.25); 00541 const T thr2 = static_cast<T>(A_cols/1.25); 00542 const T block_dim = static_cast<T>((its+1)*l); 00543 00544 if(gt(block_dim, thr1) || eq(block_dim, thr1) || gt(block_dim, thr2) || eq(block_dim, thr2)) 00545 { 00546 // [U,S,V] = svd(A,'econ'); 00547 T *Q, *L, *Vt; 00548 int Q_rows, Q_cols; 00549 int L_len; 00550 int Vt_rows, Vt_cols; 00551 00552 svd(A, Q, L, Vt, A_rows, A_cols, Q_rows, Q_cols, L_len, Vt_rows, Vt_cols, true); 00553 00554 // % 00555 // % Retain only the leftmost k columns of U, the leftmost k columns of V, 00556 // % and the uppermost leftmost k x k block of S. 00557 // % 00558 00559 // U = U(:,1:k); 00560 copy(U, Q, k*Q_rows); 00561 delete[] Q; 00562 00563 // S = S(1:k,1:k); 00564 copy(S, L, k); 00565 delete[] L; 00566 00567 // V = V(:,1:k); 00568 if(V != NULL) 00569 { 00570 T* tr = new T[Vt_cols*Vt_rows]; 00571 00572 transpose(Vt, Vt_rows, Vt_cols, tr); 00573 00574 copy(V, tr, k*Vt_cols); 00575 delete[] tr; 00576 } 00577 delete[] Vt; 00578 00579 return; 00580 } 00581 00582 const T randMax = static_cast<T>(RAND_MAX); 00583 const T one = static_cast<T>(1.0); 00584 const T two = static_cast<T>(2.0); 00585 00586 // if(m >= n) 00587 if(A_rows >= A_cols) 00588 { 00589 const int H_len = A_rows*l; 00590 00591 T* H = new T[H_len]; 00592 T* tmp = new T[A_cols*l]; 00593 00594 // % 00595 // % Apply A to a random matrix, obtaining H. 00596 // % 00597 // H = A*(2*rand(n,l)-ones(n,l)); 00598 for(T *it =tmp, *end = tmp +(A_cols*l); it != end; ++it) 00599 *it = (two* rand()/randMax) - one; 00600 00601 dot(A, tmp, H, A_rows, A_cols, A_cols, l, A_rows, l, CblasNoTrans, CblasNoTrans, CblasColMajor); 00602 00603 // % 00604 // % Initialize F to its final size and fill its leftmost block with H. 00605 // % 00606 // F(1:m, 1:l) = H; 00607 const unsigned long F_cols = static_cast<unsigned long>(block_dim); 00608 T* F = new T[A_rows*F_cols]; 00609 copy(F, H, H_len); 00610 00611 // % 00612 // % Apply A*A' to H a total of its times, 00613 // % augmenting F with the new H each time. 00614 // % 00615 00616 // for it = 1:its 00617 for(unsigned long iter = 1; iter<=its; ++iter) 00618 { 00619 // H = (H'*A)'; 00620 // H = A*H; 00621 dot(H, A, tmp, A_rows, l, A_rows, A_cols, l, A_cols, CblasTrans, CblasNoTrans, CblasColMajor); 00622 dot(A, tmp, H, A_rows, A_cols, l, A_cols, A_rows, l, CblasNoTrans, CblasTrans, CblasColMajor); 00623 00624 // F(1:m, (1+it*l):((it+1)*l)) = H; 00625 copy(F + (H_len*iter), H, H_len); 00626 } 00627 00628 delete[] H; 00629 00630 // % 00631 // % Form a matrix Q whose columns constitute an orthonormal basis 00632 // % for the columns of F. 00633 // % 00634 // [Q,R,E] = qr(F,0); 00635 const unsigned long Q_cols = std::min(A_rows, F_cols); 00636 T* Q = new T[A_rows*Q_cols]; 00637 T* R = NULL; 00638 int* E = new int [F_cols]; 00639 00640 qr_econ(F, A_rows, F_cols, Q, R, E); 00641 00642 delete[] E; 00643 delete[] F; 00644 00645 // % 00646 // % SVD Q'*A to obtain approximations to the singular values 00647 // % and right singular vectors of A; adjust the left singular vectors 00648 // % of Q'*A to approximate the left singular vectors of A. 00649 // % 00650 // [U2,S,V] = svd(Q'*A,'econ'); 00651 T *U2, *L, *Vt; 00652 int U2_rows, U2_cols; 00653 int L_len; 00654 int Vt_rows, Vt_cols; 00655 00656 delete[] tmp; 00657 tmp = new T[Q_cols*A_cols]; 00658 00659 dot(Q, A, tmp, A_rows, Q_cols, A_rows, A_cols, Q_cols, A_cols, CblasTrans, CblasNoTrans, CblasColMajor); 00660 svd(tmp , U2, L, Vt, Q_cols, A_cols, U2_rows, U2_cols, L_len, Vt_rows, Vt_cols, true); 00661 00662 // U = Q*U2; 00663 delete[] tmp; 00664 tmp = new T[A_rows*U2_cols]; 00665 dot(Q, U2, tmp, A_rows, Q_cols, U2_rows, U2_cols, A_rows, U2_cols, CblasNoTrans, CblasNoTrans, CblasColMajor); 00666 00667 // clear Q U2; 00668 delete[] Q; 00669 delete[] U2; 00670 00671 // % 00672 // % Retain only the leftmost k columns of U, the leftmost k columns of V, 00673 // % and the uppermost leftmost k x k block of S. 00674 // % 00675 // U = U(:,1:k); 00676 copy(U, tmp, k*A_rows); 00677 delete[] tmp; 00678 00679 // V = V(:,1:k); 00680 if(V != NULL) 00681 { 00682 T* tr = new T[Vt_cols*Vt_rows]; 00683 00684 transpose(Vt, Vt_rows, Vt_cols, tr); 00685 00686 copy(V, tr, k*Vt_cols); 00687 delete[] tr; 00688 } 00689 delete[] Vt; 00690 00691 00692 // S = S(1:k,1:k); 00693 copy(S, L, k); 00694 delete[] L; 00695 00696 } 00697 else 00698 { 00699 // % 00700 // % Apply A' to a random matrix, obtaining H. 00701 // % 00702 00703 const int H_len = A_cols*l; 00704 00705 // H = ((2*rand(l,m)-ones(l,m))*A)'; 00706 T* H = new T[H_len]; 00707 T* tmp = new T[l*A_rows]; 00708 00709 for(T *it =tmp, *end = tmp +(l*A_rows); it != end; ++it) 00710 *it = (two* rand()/randMax) - one; 00711 00712 dot(A, tmp, H, A_rows, A_cols, l, A_rows, A_cols, l, CblasTrans, CblasTrans, CblasColMajor); 00713 00714 00715 // % 00716 // % Initialize F to its final size and fill its leftmost block with H. 00717 // % 00718 // F = zeros(n,(its+1)*l); 00719 // F(1:n, 1:l) = H; 00720 00721 const unsigned long F_cols = static_cast<unsigned long>(block_dim); 00722 T* F = new T[A_cols*F_cols]; 00723 copy(F, H, H_len); 00724 00725 // % 00726 // % Apply A'*A to H a total of its times, 00727 // % augmenting F with the new H each time. 00728 // % 00729 // for it = 1:its 00730 for(unsigned long iter = 1; iter<=its; ++iter) 00731 { 00732 // H = A*H; 00733 dot(A, H, tmp, A_rows, A_cols, A_cols, l, A_rows, l, CblasNoTrans, CblasNoTrans, CblasColMajor); 00734 00735 // H = (H'*A)'; 00736 dot(A, tmp, H, A_rows, A_cols, A_rows, l, A_cols, l, CblasTrans, CblasNoTrans, CblasColMajor); 00737 00738 // F(1:n, (1+it*l):((it+1)*l)) = H; 00739 copy(F + (H_len*iter), H, H_len); 00740 } 00741 00742 delete[] H; 00743 00744 // % 00745 // % Form a matrix Q whose columns constitute an orthonormal basis 00746 // % for the columns of F. 00747 // % 00748 00749 // [Q,R,E] = qr(F,0); 00750 const unsigned long Q_cols = std::min(A_cols, F_cols); 00751 T* Q = new T[A_cols*Q_cols]; 00752 T* R = NULL; 00753 int* E = new int [F_cols]; 00754 00755 qr_econ(F, A_cols, F_cols, Q, R, E); 00756 00757 delete[] E; 00758 delete[] F; 00759 00760 // % 00761 // % SVD A*Q to obtain approximations to the singular values 00762 // % and left singular vectors of A; adjust the right singular vectors 00763 // % of A*Q to approximate the right singular vectors of A. 00764 // % 00765 00766 // [U,S,V2] = svd(A*Q,'econ'); 00767 T *U2, *L, *Vt; 00768 int U2_rows, U2_cols; 00769 int L_len; 00770 int Vt_rows, Vt_cols; 00771 00772 delete[] tmp; 00773 tmp = new T[A_rows*Q_cols]; 00774 00775 dot(A, Q, tmp, A_rows, A_cols, A_cols, Q_cols, A_rows, Q_cols, CblasNoTrans, CblasNoTrans, CblasColMajor); 00776 svd(tmp, U2, L, Vt, A_rows, Q_cols, U2_rows, U2_cols, L_len, Vt_rows, Vt_cols, true); 00777 00778 // V = Q*V2; 00779 delete[] tmp; 00780 if(V != NULL) 00781 { 00782 tmp = new T[A_cols*Vt_rows]; 00783 dot(Q, Vt, tmp, A_cols, Q_cols, Vt_rows, Vt_cols, A_cols, Vt_rows, CblasNoTrans, CblasTrans, CblasColMajor); 00784 } 00785 00786 delete[] Vt; 00787 delete[] Q; 00788 00789 // % 00790 // % Retain only the leftmost k columns of U, the leftmost k columns of V, 00791 // % and the uppermost leftmost k x k block of S. 00792 // % 00793 00794 // U = U(:,1:k); 00795 copy(U, U2, k*U2_rows); 00796 delete[] U2; 00797 00798 // V = V(:,1:k); 00799 if(V != NULL) 00800 copy(V, tmp, k*A_cols); 00801 00802 delete[] tmp; 00803 00804 // S = S(1:k,1:k); 00805 copy(S, L, k); 00806 delete[] L; 00807 00808 } 00809 } 00810 00814 template<typename T> 00815 void GInverseDiagonal(const T* Q, const T* L, const T* lambda, T* Z, 00816 const int Q_rows, const int Q_cols, 00817 const int L_length, const int lambda_length) 00818 { 00819 00820 T* work = new T[(Q_rows*Q_cols)+L_length]; 00821 00822 GInverseDiagonal(Q, L, lambda, Z, Q_rows, Q_cols, L_length, lambda_length, work); 00823 00824 delete [] work; 00825 } 00826 00830 template<typename T> 00831 void GInverseDiagonal(const T* Q, const T* L, const T* lambda, T* Z, 00832 const int Q_rows, const int Q_cols, 00833 const int L_length, const int lambda_length, T* work) 00834 { 00835 //function Z = GInverseDiagonal( Q, L, lambda ) 00836 00837 //n = size(Q, 1); -> Q_rows 00838 //t = size(lambda, 2); -> lambda_length 00839 00840 //Z = zeros(n, t); 00841 00842 //D = Q.^(2); 00843 const int Q_size = Q_rows*Q_cols; 00844 T* D = work;// size Q_size 00845 mult(Q, Q, D, Q_size); 00846 00847 T* d = work+Q_size; // size L_length 00848 00849 //for i = 1 : t 00850 for(int i=0; i<lambda_length; ++i) 00851 { 00852 // d = L + (n*lambda(i)); 00853 set(d, Q_rows*lambda[i] , L_length); 00854 axpy(L_length, (T)1.0, L, 1, d, 1); 00855 00856 // d = d.^(-1); 00857 setReciprocal(d, L_length); 00858 00859 // Z(:,i) = D*d; 00860 gemv(CblasNoTrans, Q_rows, Q_cols, (T)1.0, D, Q_cols, d, 1, (T)0.0, Z+(i*lambda_length), 1); 00861 } 00862 00863 } 00864 00865 template<typename T> 00866 gMat2D<T>* rls_primal_driver(T* K, const T* Xty, const unsigned long n, const unsigned long d, const unsigned long Yd, const T lambda) 00867 { 00868 gMat2D<T> *W = NULL; 00869 00870 std::set<T*> garbage; 00871 00872 try{ // Try solving it with cholesky first. 00873 00874 const T coeff = n*static_cast<T>(lambda); 00875 unsigned long i=0; 00876 for(T* it = K; i<d; ++i, it+=d+1) 00877 *it += coeff; 00878 00879 // R = chol(K); 00880 T* R = new T[d*d]; 00881 garbage.insert(R); 00882 cholesky(K, d, d, R); 00883 00884 // cfr.W = R\(R'\Xty); 00885 W = new gMat2D<T>(d, Yd); 00886 00887 copy(W->getData(), Xty, W->getSize()); 00888 mldivide_squared(R, W->getData(), d, d, W->rows(), W->cols(), CblasTrans); //(R'\Xty) 00889 mldivide_squared(R, W->getData(), d, d, W->rows(), W->cols(), CblasNoTrans); //R\(R'\Xty) 00890 00891 delete[] R; 00892 garbage.erase(R); 00893 } 00894 catch (gException& /*gex*/) 00895 { 00896 00897 for(typename std::set<T*>::iterator it = garbage.begin(); it != garbage.end(); ++it) 00898 delete[] (*it); 00899 00900 if(W != NULL) 00901 delete W; 00902 00903 T *Q, *L, *Vt; 00904 int Q_rows, Q_cols; 00905 int L_len; 00906 int Vt_rows, Vt_cols; 00907 00908 svd(K, Q, L, Vt, d, d, Q_rows, Q_cols, L_len, Vt_rows, Vt_cols); 00909 00910 // QtXtY = Q'*Xty; 00911 T* QtXtY = new T[Q_cols*Yd]; 00912 dot(Q, Xty, QtXtY, Q_rows, Q_cols, d, Yd, Q_cols, Yd, CblasTrans, CblasNoTrans, CblasColMajor); 00913 00914 // % regularization is done inside rls_eigen 00915 W = new gMat2D<T>(Q_rows, Yd); 00916 T* work = new T[L_len*(Q_rows+1)]; 00917 rls_eigen(Q, L, QtXtY, W->getData(), lambda, n, Q_rows, Q_cols, L_len, Q_cols, Yd, work); 00918 00919 delete [] QtXtY; 00920 delete [] work; 00921 00922 delete [] Q; 00923 delete [] L; 00924 delete [] Vt; 00925 00926 } 00927 00928 return W; 00929 00930 } 00931 00932 template<typename T> 00933 gMat2D<T>* rp_apply_real(const T *X, const T *W, const unsigned long n, const unsigned long d, const unsigned long D) 00934 { 00935 00936 gMat2D<T> *G = new gMat2D<T>(n, 2*D); 00937 00938 // V = X*W; 00939 T *V = G->getData() + (n*D); 00940 dot(X, W, V, n, d, d, D, n, D, CblasNoTrans, CblasNoTrans, CblasColMajor); 00941 00942 00943 // G = [cos(V) sin(V)]; 00944 for(T *G_it = G->getData(), *const V_end = V+(n*D); V != V_end; ++G_it, ++V) 00945 { 00946 *G_it = cos(*V); 00947 *V = sin(*V); 00948 } 00949 00950 return G; 00951 } 00952 00953 template<typename T> 00954 gMat2D<T>* rp_apply_real(const gMat2D<T> &X, const gMat2D<T> &W) 00955 { 00956 const unsigned long n = X.rows(); 00957 const unsigned long d = X.cols(); 00958 const unsigned long D = W.cols(); 00959 00960 return rp_apply_real(X.getData(), W.getData(), n, d, D); 00961 } 00962 00963 template<typename T> 00964 gMat2D<T>* rp_projections(const unsigned long d, const unsigned long D) 00965 { 00966 // W = sqrt(2)*randn(d,D); 00967 boost::random::mt19937 gen; 00968 boost::random::normal_distribution<T> g(0.0, (T)sqrt(2.0)); 00969 00970 gMat2D<T> *W = new gMat2D<T>(d, D); 00971 for(T* W_it = W->getData(), *const W_end = W_it + (d*D); W_it != W_end; ++W_it) 00972 *W_it = g(gen); 00973 00974 return W; 00975 } 00976 00977 template<typename T> 00978 gMat2D<T>* rp_factorize_large_real(const gMat2D<T> &X, const gMat2D<T> &y, const unsigned long D, 00979 const unsigned long psize, T* XtX, T*Xty) 00980 { 00981 00982 // d = size(X,2); 00983 // n = size(X,1); 00984 // T = size(y,2); 00985 00986 const unsigned long d = X.cols(); 00987 const unsigned long n = X.rows(); 00988 const unsigned long t = y.cols(); 00989 00990 // W = rp_projections(d,D,kernel); 00991 gMat2D<T>* W = rp_projections<T>(d, D); 00992 00993 const unsigned long D2 = 2*D; 00994 00995 // GG = zeros(D*2,D*2); 00996 set(XtX, (T)0.0, D2*D2); 00997 00998 // Gy = zeros(D*2,T); 00999 set(Xty, (T)0.0, D2*t); 01000 01001 01002 T* Xi = new T[psize*d]; 01003 T* yi = new T[psize*t]; 01004 01005 const T alpha = (T)1.0; 01006 const T beta = (T)1.0; 01007 01008 // for i=1:psize:n 01009 for(unsigned long i=0; i< n; i+=psize) 01010 { 01011 // bend = min(i+psize-1,n); 01012 unsigned long bend = std::min(i+psize, n); 01013 01014 // Gi = rp_apply_real(X(i:bend,:),W); 01015 // yi = y(i:bend,:); 01016 01017 unsigned long rows = bend-i; 01018 01019 const T *X_it = X.getData() + i, *y_it = y.getData() + i; 01020 T *Xi_it = Xi, *yi_it = yi; 01021 01022 for(unsigned long j=0; j<d; ++j, X_it+=n, Xi_it+=rows) 01023 copy(Xi_it, X_it, rows); 01024 01025 for(unsigned long j=0; j<t; ++j, y_it+=n, yi_it+=rows) 01026 copy(yi_it, y_it, rows); 01027 01028 gMat2D<T> *Gi = rp_apply_real(Xi, W->getData(), rows, d, D); 01029 01030 // GG = GG + Gi'*Gi; 01031 gemm(CblasTrans, CblasNoTrans, D2, D2, rows, alpha, Gi->getData(), rows, Gi->getData(), rows, beta, XtX, D2); 01032 01033 // Gy = Gy + Gi'*yi; 01034 gemm(CblasTrans, CblasNoTrans, D2, t, rows, alpha, Gi->getData(), rows, yi, rows, beta, Xty, D2); 01035 01036 delete Gi; 01037 } 01038 01039 delete [] Xi; 01040 delete [] yi; 01041 01042 return W; 01043 } 01044 01045 } 01046 01047 #endif // _GURLS_UTILS_H_