GURLS++  2.0.00
C++ Implementation of GURLS Matlab Toolbox
utils.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends