/* * Compute p-val using Wald test. * * @param betas A vector of beta values * @param invInf Inverse of corresponding information matrix. * * @return chiSq The test statistic * @return p-value. */ double LogisticRegression::getStats(const vector<double> &betas, const vector<vector<double> > invInf, double &chiS){ if(betas.size() != invInf.size()) return 2.0; int sz = betas.size()-1; // Make vector and matrix. alglib::real_1d_array vBetas; alglib::real_1d_array vTemp; alglib::real_1d_array singleNum; alglib::real_2d_array vInvInf; vBetas.setlength(sz+1); vTemp.setlength(sz+1); singleNum.setlength(1); vInvInf.setlength(sz+1, sz+1); for(unsigned int i=0;i < betas.size();i++){ vBetas(i) = betas.at(i); for(unsigned int j=0;j < betas.size() ; j++){ vInvInf(i,j) = invInf.at(i).at(j); } } alglib::matinvreport report; alglib::ae_int_t reportInfo; rmatrixinverse(vInvInf, reportInfo, report); if(reportInfo != 1) return 2.0; // Check condition number. if (report.r1 < condition_number_limit){ throw ConditionNumberEx(1.0/report.r1); } // betas' * vInvInf * betas (vInvInf has been inverted) matrixvectormultiply(vInvInf,0,sz,0,sz,false, vBetas,0,sz,1.0,vTemp,0,sz,0.0); alglib::real_2d_array vBetasTemp; vBetasTemp.setlength(sz+1,1); for(int i=0;i<=sz;i++) vBetasTemp(i,0) = vBetas(i); matrixvectormultiply(vBetasTemp,0,sz,0,0,true, vTemp,0,sz,1.0,singleNum,0,0,0.0); chiS = singleNum(0); try{ return Statistics::chi2prob(chiS, betas.size()); }catch(StatsException){ chiS = -1; return 2.0; } }
void internalschurdecomposition(ap::real_2d_array& h, int n, int tneeded, int zneeded, ap::real_1d_array& wr, ap::real_1d_array& wi, ap::real_2d_array& z, int& info) { ap::real_1d_array work; int i; int i1; int i2; int ierr; int ii; int itemp; int itn; int its; int j; int k; int l; int maxb; int nr; int ns; int nv; double absw; double ovfl; double smlnum; double tau; double temp; double tst1; double ulp; double unfl; ap::real_2d_array s; ap::real_1d_array v; ap::real_1d_array vv; ap::real_1d_array workc1; ap::real_1d_array works1; ap::real_1d_array workv3; ap::real_1d_array tmpwr; ap::real_1d_array tmpwi; bool initz; bool wantt; bool wantz; double cnst; bool failflag; int p1; int p2; int p3; int p4; double vt; // // Set the order of the multi-shift QR algorithm to be used. // If you want to tune algorithm, change this values // ns = 12; maxb = 50; // // Now 2 < NS <= MAXB < NH. // maxb = ap::maxint(3, maxb); ns = ap::minint(maxb, ns); // // Initialize // cnst = 1.5; work.setbounds(1, ap::maxint(n, 1)); s.setbounds(1, ns, 1, ns); v.setbounds(1, ns+1); vv.setbounds(1, ns+1); wr.setbounds(1, ap::maxint(n, 1)); wi.setbounds(1, ap::maxint(n, 1)); workc1.setbounds(1, 1); works1.setbounds(1, 1); workv3.setbounds(1, 3); tmpwr.setbounds(1, ap::maxint(n, 1)); tmpwi.setbounds(1, ap::maxint(n, 1)); ap::ap_error::make_assertion(n>=0, "InternalSchurDecomposition: incorrect N!"); ap::ap_error::make_assertion(tneeded==0||tneeded==1, "InternalSchurDecomposition: incorrect TNeeded!"); ap::ap_error::make_assertion(zneeded==0||zneeded==1||zneeded==2, "InternalSchurDecomposition: incorrect ZNeeded!"); wantt = tneeded==1; initz = zneeded==2; wantz = zneeded!=0; info = 0; // // Initialize Z, if necessary // if( initz ) { z.setbounds(1, n, 1, n); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { if( i==j ) { z(i,j) = 1; } else { z(i,j) = 0; } } } } // // Quick return if possible // if( n==0 ) { return; } if( n==1 ) { wr(1) = h(1,1); wi(1) = 0; return; } // // Set rows and columns 1 to N to zero below the first // subdiagonal. // for(j = 1; j <= n-2; j++) { for(i = j+2; i <= n; i++) { h(i,j) = 0; } } // // Test if N is sufficiently small // if( ns<=2||ns>n||maxb>=n ) { // // Use the standard double-shift algorithm // internalauxschur(wantt, wantz, n, 1, n, h, wr, wi, 1, n, z, work, workv3, workc1, works1, info); // // fill entries under diagonal blocks of T with zeros // if( wantt ) { j = 1; while(j<=n) { if( wi(j)==0 ) { for(i = j+1; i <= n; i++) { h(i,j) = 0; } j = j+1; } else { for(i = j+2; i <= n; i++) { h(i,j) = 0; h(i,j+1) = 0; } j = j+2; } } } return; } unfl = ap::minrealnumber; ovfl = 1/unfl; ulp = 2*ap::machineepsilon; smlnum = unfl*(n/ulp); // // I1 and I2 are the indices of the first row and last column of H // to which transformations must be applied. If eigenvalues only are // being computed, I1 and I2 are set inside the main loop. // if( wantt ) { i1 = 1; i2 = n; } // // ITN is the total number of multiple-shift QR iterations allowed. // itn = 30*n; // // The main loop begins here. I is the loop index and decreases from // IHI to ILO in steps of at most MAXB. Each iteration of the loop // works with the active submatrix in rows and columns L to I. // Eigenvalues I+1 to IHI have already converged. Either L = ILO or // H(L,L-1) is negligible so that the matrix splits. // i = n; while(true) { l = 1; if( i<1 ) { // // fill entries under diagonal blocks of T with zeros // if( wantt ) { j = 1; while(j<=n) { if( wi(j)==0 ) { for(i = j+1; i <= n; i++) { h(i,j) = 0; } j = j+1; } else { for(i = j+2; i <= n; i++) { h(i,j) = 0; h(i,j+1) = 0; } j = j+2; } } } // // Exit // return; } // // Perform multiple-shift QR iterations on rows and columns ILO to I // until a submatrix of order at most MAXB splits off at the bottom // because a subdiagonal element has become negligible. // failflag = true; for(its = 0; its <= itn; its++) { // // Look for a single small subdiagonal element. // for(k = i; k >= l+1; k--) { tst1 = fabs(h(k-1,k-1))+fabs(h(k,k)); if( tst1==0 ) { tst1 = upperhessenberg1norm(h, l, i, l, i, work); } if( fabs(h(k,k-1))<=ap::maxreal(ulp*tst1, smlnum) ) { break; } } l = k; if( l>1 ) { // // H(L,L-1) is negligible. // h(l,l-1) = 0; } // // Exit from loop if a submatrix of order <= MAXB has split off. // if( l>=i-maxb+1 ) { failflag = false; break; } // // Now the active submatrix is in rows and columns L to I. If // eigenvalues only are being computed, only the active submatrix // need be transformed. // if( !wantt ) { i1 = l; i2 = i; } if( its==20||its==30 ) { // // Exceptional shifts. // for(ii = i-ns+1; ii <= i; ii++) { wr(ii) = cnst*(fabs(h(ii,ii-1))+fabs(h(ii,ii))); wi(ii) = 0; } } else { // // Use eigenvalues of trailing submatrix of order NS as shifts. // copymatrix(h, i-ns+1, i, i-ns+1, i, s, 1, ns, 1, ns); internalauxschur(false, false, ns, 1, ns, s, tmpwr, tmpwi, 1, ns, z, work, workv3, workc1, works1, ierr); for(p1 = 1; p1 <= ns; p1++) { wr(i-ns+p1) = tmpwr(p1); wi(i-ns+p1) = tmpwi(p1); } if( ierr>0 ) { // // If DLAHQR failed to compute all NS eigenvalues, use the // unconverged diagonal elements as the remaining shifts. // for(ii = 1; ii <= ierr; ii++) { wr(i-ns+ii) = s(ii,ii); wi(i-ns+ii) = 0; } } } // // Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns)) // where G is the Hessenberg submatrix H(L:I,L:I) and w is // the vector of shifts (stored in WR and WI). The result is // stored in the local array V. // v(1) = 1; for(ii = 2; ii <= ns+1; ii++) { v(ii) = 0; } nv = 1; for(j = i-ns+1; j <= i; j++) { if( wi(j)>=0 ) { if( wi(j)==0 ) { // // real shift // p1 = nv+1; ap::vmove(&vv(1), &v(1), ap::vlen(1,p1)); matrixvectormultiply(h, l, l+nv, l, l+nv-1, false, vv, 1, nv, 1.0, v, 1, nv+1, -wr(j)); nv = nv+1; } else { if( wi(j)>0 ) { // // complex conjugate pair of shifts // p1 = nv+1; ap::vmove(&vv(1), &v(1), ap::vlen(1,p1)); matrixvectormultiply(h, l, l+nv, l, l+nv-1, false, v, 1, nv, 1.0, vv, 1, nv+1, -2*wr(j)); itemp = vectoridxabsmax(vv, 1, nv+1); temp = 1/ap::maxreal(fabs(vv(itemp)), smlnum); p1 = nv+1; ap::vmul(&vv(1), ap::vlen(1,p1), temp); absw = pythag2(wr(j), wi(j)); temp = temp*absw*absw; matrixvectormultiply(h, l, l+nv+1, l, l+nv, false, vv, 1, nv+1, 1.0, v, 1, nv+2, temp); nv = nv+2; } } // // Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero, // reset it to the unit vector. // itemp = vectoridxabsmax(v, 1, nv); temp = fabs(v(itemp)); if( temp==0 ) { v(1) = 1; for(ii = 2; ii <= nv; ii++) { v(ii) = 0; } } else { temp = ap::maxreal(temp, smlnum); vt = 1/temp; ap::vmul(&v(1), ap::vlen(1,nv), vt); } } } // // Multiple-shift QR step // for(k = l; k <= i-1; k++) { // // The first iteration of this loop determines a reflection G // from the vector V and applies it from left and right to H, // thus creating a nonzero bulge below the subdiagonal. // // Each subsequent iteration determines a reflection G to // restore the Hessenberg form in the (K-1)th column, and thus // chases the bulge one step toward the bottom of the active // submatrix. NR is the order of G. // nr = ap::minint(ns+1, i-k+1); if( k>l ) { p1 = k-1; p2 = k+nr-1; ap::vmove(v.getvector(1, nr), h.getcolumn(p1, k, p2)); } generatereflection(v, nr, tau); if( k>l ) { h(k,k-1) = v(1); for(ii = k+1; ii <= i; ii++) { h(ii,k-1) = 0; } } v(1) = 1; // // Apply G from the left to transform the rows of the matrix in // columns K to I2. // applyreflectionfromtheleft(h, tau, v, k, k+nr-1, k, i2, work); // // Apply G from the right to transform the columns of the // matrix in rows I1 to min(K+NR,I). // applyreflectionfromtheright(h, tau, v, i1, ap::minint(k+nr, i), k, k+nr-1, work); if( wantz ) { // // Accumulate transformations in the matrix Z // applyreflectionfromtheright(z, tau, v, 1, n, k, k+nr-1, work); } } } // // Failure to converge in remaining number of iterations // if( failflag ) { info = i; return; } // // A submatrix of order <= MAXB in rows and columns L to I has split // off. Use the double-shift QR algorithm to handle it. // internalauxschur(wantt, wantz, n, l, i, h, wr, wi, 1, n, z, work, workv3, workc1, works1, info); if( info>0 ) { return; } // // Decrement number of remaining iterations, and return to start of // the main loop with a new value of I. // itn = itn-its; i = l-1; } }
bool generalizedsymmetricdefiniteevdreduce(ap::real_2d_array& a, int n, bool isuppera, const ap::real_2d_array& b, bool isupperb, int problemtype, ap::real_2d_array& r, bool& isupperr) { bool result; ap::real_2d_array t; ap::real_1d_array w1; ap::real_1d_array w2; ap::real_1d_array w3; int i; int j; double v; ap::ap_error::make_assertion(n>0, "GeneralizedSymmetricDefiniteEVDReduce: N<=0!"); ap::ap_error::make_assertion(problemtype==1||problemtype==2||problemtype==3, "GeneralizedSymmetricDefiniteEVDReduce: incorrect ProblemType!"); result = true; // // Problem 1: A*x = lambda*B*x // // Reducing to: // C*y = lambda*y // C = L^(-1) * A * L^(-T) // x = L^(-T) * y // if( problemtype==1 ) { // // Factorize B in T: B = LL' // t.setbounds(1, n, 1, n); if( isupperb ) { for(i = 1; i <= n; i++) { ap::vmove(t.getcolumn(i, i, n), b.getrow(i, i, n)); } } else { for(i = 1; i <= n; i++) { ap::vmove(&t(i, 1), &b(i, 1), ap::vlen(1,i)); } } if( !choleskydecomposition(t, n, false) ) { result = false; return result; } // // Invert L in T // if( !invtriangular(t, n, false, false) ) { result = false; return result; } // // Build L^(-1) * A * L^(-T) in R // w1.setbounds(1, n); w2.setbounds(1, n); r.setbounds(1, n, 1, n); for(j = 1; j <= n; j++) { // // Form w2 = A * l'(j) (here l'(j) is j-th column of L^(-T)) // ap::vmove(&w1(1), &t(j, 1), ap::vlen(1,j)); symmetricmatrixvectormultiply(a, isuppera, 1, j, w1, 1.0, w2); if( isuppera ) { matrixvectormultiply(a, 1, j, j+1, n, true, w1, 1, j, 1.0, w2, j+1, n, 0.0); } else { matrixvectormultiply(a, j+1, n, 1, j, false, w1, 1, j, 1.0, w2, j+1, n, 0.0); } // // Form l(i)*w2 (here l(i) is i-th row of L^(-1)) // for(i = 1; i <= n; i++) { v = ap::vdotproduct(&t(i, 1), &w2(1), ap::vlen(1,i)); r(i,j) = v; } } // // Copy R to A // for(i = 1; i <= n; i++) { ap::vmove(&a(i, 1), &r(i, 1), ap::vlen(1,n)); } // // Copy L^(-1) from T to R and transpose // isupperr = true; for(i = 1; i <= n; i++) { for(j = 1; j <= i-1; j++) { r(i,j) = 0; } } for(i = 1; i <= n; i++) { ap::vmove(r.getrow(i, i, n), t.getcolumn(i, i, n)); } return result; } // // Problem 2: A*B*x = lambda*x // or // problem 3: B*A*x = lambda*x // // Reducing to: // C*y = lambda*y // C = U * A * U' // B = U'* U // if( problemtype==2||problemtype==3 ) { // // Factorize B in T: B = U'*U // t.setbounds(1, n, 1, n); if( isupperb ) { for(i = 1; i <= n; i++) { ap::vmove(&t(i, i), &b(i, i), ap::vlen(i,n)); } } else { for(i = 1; i <= n; i++) { ap::vmove(t.getrow(i, i, n), b.getcolumn(i, i, n)); } } if( !choleskydecomposition(t, n, true) ) { result = false; return result; } // // Build U * A * U' in R // w1.setbounds(1, n); w2.setbounds(1, n); w3.setbounds(1, n); r.setbounds(1, n, 1, n); for(j = 1; j <= n; j++) { // // Form w2 = A * u'(j) (here u'(j) is j-th column of U') // ap::vmove(&w1(1), &t(j, j), ap::vlen(1,n-j+1)); symmetricmatrixvectormultiply(a, isuppera, j, n, w1, 1.0, w3); ap::vmove(&w2(j), &w3(1), ap::vlen(j,n)); ap::vmove(&w1(j), &t(j, j), ap::vlen(j,n)); if( isuppera ) { matrixvectormultiply(a, 1, j-1, j, n, false, w1, j, n, 1.0, w2, 1, j-1, 0.0); } else { matrixvectormultiply(a, j, n, 1, j-1, true, w1, j, n, 1.0, w2, 1, j-1, 0.0); } // // Form u(i)*w2 (here u(i) is i-th row of U) // for(i = 1; i <= n; i++) { v = ap::vdotproduct(&t(i, i), &w2(i), ap::vlen(i,n)); r(i,j) = v; } } // // Copy R to A // for(i = 1; i <= n; i++) { ap::vmove(&a(i, 1), &r(i, 1), ap::vlen(1,n)); } if( problemtype==2 ) { // // Invert U in T // if( !invtriangular(t, n, true, false) ) { result = false; return result; } // // Copy U^-1 from T to R // isupperr = true; for(i = 1; i <= n; i++) { for(j = 1; j <= i-1; j++) { r(i,j) = 0; } } for(i = 1; i <= n; i++) { ap::vmove(&r(i, i), &t(i, i), ap::vlen(i,n)); } } else { // // Copy U from T to R and transpose // isupperr = false; for(i = 1; i <= n; i++) { for(j = i+1; j <= n; j++) { r(i,j) = 0; } } for(i = 1; i <= n; i++) { ap::vmove(r.getcolumn(i, i, n), t.getrow(i, i, n)); } } } return result; }
/** * Compute the ordinary least squares estimation of the solution to a linear regression * * @param data The regression input. Each inner vector should be a single variable (so column maj order) * @param response The response variable. * @return betas The estimate of regression coefficients */ vector<double> LinearRegression::leastSquares(const vector<vector<double> > &data, const vector<double> &response){ int sz = data.size(); if(sz < 0) throw LinearRegressionException(); int indivSz = response.size(); vector<double> betas; alglib::real_1d_array vecResp; alglib::real_1d_array vecBetas; alglib::real_2d_array vecData; alglib::real_2d_array tempSquare; alglib::real_1d_array tempWork; vecResp.setlength(indivSz); vecBetas.setlength(sz); vecData.setlength(indivSz,sz); tempSquare.setlength(sz,sz); tempWork.setlength(indivSz+1); // Transfer into the matrices. for(unsigned int i=0;i<data.size();i++){ for(unsigned int j=0;j < data.at(0).size();j++){ vecData(j,i) = data.at(i).at(j); } } for(unsigned int i=0;i<response.size();i++) vecResp(i) = response.at(i); /// X'*X matrixmatrixmultiply(vecData,0,indivSz-1,0,sz-1,true, vecData,0,indivSz-1,0,sz-1,false,1.0, tempSquare,0,sz-1,0,sz-1,0.0,tempWork); alglib::matinvreport report; alglib::ae_int_t reportInfo ; rmatrixinverse(tempSquare, reportInfo, report); if(reportInfo != 1){ throw LinearRegressionException(); } if (report.r1 > LINEAR_REGRESSION_CONDITION_NUMBER_LIMIT){ throw ConditionNumberEx(1.0/report.r1); } /// X'*beta matrixvectormultiply(vecData,0,indivSz-1,0,sz-1,true, vecResp,0,indivSz-1,1.0, tempWork,0,sz-1,0.0); /// tempSquare * tempWork matrixvectormultiply(tempSquare,0,sz-1,0,sz-1,false, tempWork,0,sz-1,1.0, vecBetas,0,sz-1,0.0); for(int i=0;i<sz;i++) betas.push_back(vecBetas(i)); return betas; }
bool GetScore(ap::template_2d_array<float,true>& Responses, ap::template_1d_array<unsigned short int, true>& Code, parameters tMUD, ap::template_1d_array<short int,true>& trialnr, ap::template_1d_array<double,true>& windowlen, int numchannels, int NumberOfSequences, int NumberOfChoices, int mode, ap::real_2d_array &pscore) { /////////////////////////////////////////////////////////////////////// // Section: Define variables int row_Responses, col_Responses, row_MUD, col_MUD, dslen, count, max, NumberOfEpochs, numVariables; bool flag = true; ap::real_2d_array Responses_double; ap::template_2d_array<float, true> Responses_copy; ap::real_2d_array DATA; ap::real_2d_array tmp_MUD; ap::real_1d_array score; ap::real_1d_array weights; vector<short int> trial; //vector<short int> trial_copy; vector<int> range; vector<int> code_indx; vector<short int>::iterator it; /////////////////////////////////////////////////////////////////////// // Section: Get Dimmensions row_Responses = Responses.gethighbound(1)+1; col_Responses = Responses.gethighbound(0)+1; row_MUD = tMUD.MUD.gethighbound(1)+1; col_MUD = tMUD.MUD.gethighbound(0)+1; /////////////////////////////////////////////////////////////////////// // Section: Extract from the signal only the channels containing the "in" variables numVariables = static_cast<int>( col_Responses/static_cast<double>( numchannels ) ); Responses_copy.setbounds(0, row_Responses-1, 0, numVariables*(tMUD.channels.gethighbound(1)+1)-1); Responses_double.setbounds(0, row_Responses-1, 0, numVariables*(tMUD.channels.gethighbound(1)+1)-1); for (int i=0; i<row_Responses; i++) { for (int j=0; j<tMUD.channels.gethighbound(1)+1; j++) { ap::vmove(Responses_copy.getrow(i, j*numVariables, ((j+1)*numVariables)-1), Responses.getrow(i, static_cast<int>(tMUD.channels(j)-1)*numVariables, static_cast<int>(tMUD.channels(j)*numVariables)-1)); } } for (int i=0; i<row_Responses; i++) { for (int j=0; j<numVariables*(tMUD.channels.gethighbound(1)+1); j++) Responses_double(i,j) = static_cast<double>( Responses_copy(i,j) ); } for (int i=0; i<row_Responses; i++) trial.push_back(trialnr(i)); /////////////////////////////////////////////////////////////////////// // Section: Downsampling the MUD dslen = ap::iceil((row_MUD-1)/tMUD.DF)+1; tmp_MUD.setbounds(0, dslen, 0, col_MUD-1); for (int j=0; j<col_MUD; j++) { for (int i=0; i<dslen; i++) { if (j==0) tmp_MUD(i,0) = tMUD.MUD(i*tMUD.DF, 0)-1; if (j==1) { tmp_MUD(i,1) = tMUD.MUD(i*tMUD.DF, 1) - windowlen(0); tmp_MUD(i,1) = ap::ifloor(tmp_MUD(i,1)/tMUD.DF)+1; tmp_MUD(i,1) = tmp_MUD(i,1) + (tmp_MUD(i,0)*numVariables); } if (j==2) tmp_MUD(i,2) = tMUD.MUD(i*tMUD.DF, 2); } } /////////////////////////////////////////////////////////////////////// // Section: Computing the score DATA.setbounds(0, row_Responses-1, 0, dslen-1); score.setbounds(0, row_Responses-1); weights.setbounds(0, dslen-1); double valor; for (int i=0; i<dslen; i++) { valor = tmp_MUD(i,1); ap::vmove(DATA.getcolumn(i, 0, row_Responses-1), Responses_double.getcolumn(static_cast<int>( tmp_MUD(i,1) ), 0, row_Responses-1)); valor = DATA(0,i); weights(i) = tmp_MUD(i,2); } matrixvectormultiply(DATA, 0, row_Responses-1, 0, dslen-1, FALSE, weights, 0, dslen-1, 1, score, 0, row_Responses-1, 0); /////////////////////////////////////////////////////////////////////// // Section: Make sure that the epochs are not outside of the boundaries #if 0 // jm Mar 18, 2011 trial_copy = trial; it = unique(trial_copy.begin(), trial_copy.end()); trial_copy.resize(it-trial_copy.begin()); max = *max_element(trial_copy.begin(), trial_copy.end()); #else // jm max = *max_element(trial.begin(), trial.end()); #endif // jm count = 0; for (size_t i=0; i<trial.size(); i++) { if (trial[i] == max) count++; } if (count == NumberOfSequences*NumberOfChoices) NumberOfEpochs = *max_element(trial.begin(), trial.end()); else NumberOfEpochs = *max_element(trial.begin(), trial.end())-1; /////////////////////////////////////////////////////////////////////// // Section: Create a matrix with the scores for each sequence pscore.setbounds(0, NumberOfChoices-1, 0, (NumberOfEpochs*NumberOfSequences)-1); for (int i=0; i<NumberOfEpochs; i++) { for (size_t j=0; j<trial.size(); j++) { if (trial[j] == i+1) range.push_back(static_cast<int>(j)); } if ((range.size() != 0) && (range.size() == NumberOfSequences*NumberOfChoices)) { for (int k=0; k<NumberOfChoices; k++) { for (size_t j=0; j<range.size(); j++) { if (Code(range[j]) == k+1) code_indx.push_back(range[j]); } for (size_t j=0; j<code_indx.size(); j++) { if (code_indx.size() == NumberOfSequences) pscore(k,static_cast<int>((i*NumberOfSequences)+j)) = score(code_indx[j]); } code_indx.clear(); } flag = true; } else { flag = false; break; } range.clear(); } return flag; }
bool testblas(bool silent) { bool result; int pass; int passcount; int n; int i; int i1; int i2; int j; int j1; int j2; int l; int k; int r; int i3; int j3; int col1; int col2; int row1; int row2; ap::real_1d_array x1; ap::real_1d_array x2; ap::real_2d_array a; ap::real_2d_array b; ap::real_2d_array c1; ap::real_2d_array c2; double err; double e1; double e2; double e3; double v; double scl1; double scl2; double scl3; bool was1; bool was2; bool trans1; bool trans2; double threshold; bool n2errors; bool hsnerrors; bool amaxerrors; bool mverrors; bool iterrors; bool cterrors; bool mmerrors; bool waserrors; n2errors = false; amaxerrors = false; hsnerrors = false; mverrors = false; iterrors = false; cterrors = false; mmerrors = false; waserrors = false; threshold = 10000*ap::machineepsilon; // // Test Norm2 // passcount = 1000; e1 = 0; e2 = 0; e3 = 0; scl2 = 0.5*ap::maxrealnumber; scl3 = 2*ap::minrealnumber; for(pass = 1; pass <= passcount; pass++) { n = 1+ap::randominteger(1000); i1 = ap::randominteger(10); i2 = n+i1-1; x1.setbounds(i1, i2); x2.setbounds(i1, i2); for(i = i1; i <= i2; i++) { x1(i) = 2*ap::randomreal()-1; } v = 0; for(i = i1; i <= i2; i++) { v = v+ap::sqr(x1(i)); } v = sqrt(v); e1 = ap::maxreal(e1, fabs(v-vectornorm2(x1, i1, i2))); for(i = i1; i <= i2; i++) { x2(i) = scl2*x1(i); } e2 = ap::maxreal(e2, fabs(v*scl2-vectornorm2(x2, i1, i2))); for(i = i1; i <= i2; i++) { x2(i) = scl3*x1(i); } e3 = ap::maxreal(e3, fabs(v*scl3-vectornorm2(x2, i1, i2))); } e2 = e2/scl2; e3 = e3/scl3; n2errors = ap::fp_greater_eq(e1,threshold)||ap::fp_greater_eq(e2,threshold)||ap::fp_greater_eq(e3,threshold); // // Testing VectorAbsMax, Column/Row AbsMax // x1.setbounds(1, 5); x1(1) = 2.0; x1(2) = 0.2; x1(3) = -1.3; x1(4) = 0.7; x1(5) = -3.0; amaxerrors = vectoridxabsmax(x1, 1, 5)!=5||vectoridxabsmax(x1, 1, 4)!=1||vectoridxabsmax(x1, 2, 4)!=3; n = 30; x1.setbounds(1, n); a.setbounds(1, n, 1, n); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { a(i,j) = 2*ap::randomreal()-1; } } was1 = false; was2 = false; for(pass = 1; pass <= 1000; pass++) { j = 1+ap::randominteger(n); i1 = 1+ap::randominteger(n); i2 = i1+ap::randominteger(n+1-i1); ap::vmove(x1.getvector(i1, i2), a.getcolumn(j, i1, i2)); if( vectoridxabsmax(x1, i1, i2)!=columnidxabsmax(a, i1, i2, j) ) { was1 = true; } i = 1+ap::randominteger(n); j1 = 1+ap::randominteger(n); j2 = j1+ap::randominteger(n+1-j1); ap::vmove(&x1(j1), &a(i, j1), ap::vlen(j1,j2)); if( vectoridxabsmax(x1, j1, j2)!=rowidxabsmax(a, j1, j2, i) ) { was2 = true; } } amaxerrors = amaxerrors||was1||was2; // // Testing upper Hessenberg 1-norm // a.setbounds(1, 3, 1, 3); x1.setbounds(1, 3); a(1,1) = 2; a(1,2) = 3; a(1,3) = 1; a(2,1) = 4; a(2,2) = -5; a(2,3) = 8; a(3,1) = 99; a(3,2) = 3; a(3,3) = 1; hsnerrors = ap::fp_greater(fabs(upperhessenberg1norm(a, 1, 3, 1, 3, x1)-11),threshold); // // Testing MatrixVectorMultiply // a.setbounds(2, 3, 3, 5); x1.setbounds(1, 3); x2.setbounds(1, 2); a(2,3) = 2; a(2,4) = -1; a(2,5) = -1; a(3,3) = 1; a(3,4) = -2; a(3,5) = 2; x1(1) = 1; x1(2) = 2; x1(3) = 1; x2(1) = -1; x2(2) = -1; matrixvectormultiply(a, 2, 3, 3, 5, false, x1, 1, 3, 1.0, x2, 1, 2, 1.0); matrixvectormultiply(a, 2, 3, 3, 5, true, x2, 1, 2, 1.0, x1, 1, 3, 1.0); e1 = fabs(x1(1)+5)+fabs(x1(2)-8)+fabs(x1(3)+1)+fabs(x2(1)+2)+fabs(x2(2)+2); x1(1) = 1; x1(2) = 2; x1(3) = 1; x2(1) = -1; x2(2) = -1; matrixvectormultiply(a, 2, 3, 3, 5, false, x1, 1, 3, 1.0, x2, 1, 2, 0.0); matrixvectormultiply(a, 2, 3, 3, 5, true, x2, 1, 2, 1.0, x1, 1, 3, 0.0); e2 = fabs(x1(1)+3)+fabs(x1(2)-3)+fabs(x1(3)+1)+fabs(x2(1)+1)+fabs(x2(2)+1); mverrors = ap::fp_greater_eq(e1+e2,threshold); // // testing inplace transpose // n = 10; a.setbounds(1, n, 1, n); b.setbounds(1, n, 1, n); x1.setbounds(1, n-1); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { a(i,j) = ap::randomreal(); } } passcount = 10000; was1 = false; for(pass = 1; pass <= passcount; pass++) { i1 = 1+ap::randominteger(n); i2 = i1+ap::randominteger(n-i1+1); j1 = 1+ap::randominteger(n-(i2-i1)); j2 = j1+(i2-i1); copymatrix(a, i1, i2, j1, j2, b, i1, i2, j1, j2); inplacetranspose(b, i1, i2, j1, j2, x1); for(i = i1; i <= i2; i++) { for(j = j1; j <= j2; j++) { if( ap::fp_neq(a(i,j),b(i1+(j-j1),j1+(i-i1))) ) { was1 = true; } } } } iterrors = was1; // // testing copy and transpose // n = 10; a.setbounds(1, n, 1, n); b.setbounds(1, n, 1, n); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { a(i,j) = ap::randomreal(); } } passcount = 10000; was1 = false; for(pass = 1; pass <= passcount; pass++) { i1 = 1+ap::randominteger(n); i2 = i1+ap::randominteger(n-i1+1); j1 = 1+ap::randominteger(n); j2 = j1+ap::randominteger(n-j1+1); copyandtranspose(a, i1, i2, j1, j2, b, j1, j2, i1, i2); for(i = i1; i <= i2; i++) { for(j = j1; j <= j2; j++) { if( ap::fp_neq(a(i,j),b(j,i)) ) { was1 = true; } } } } cterrors = was1; // // Testing MatrixMatrixMultiply // n = 10; a.setbounds(1, 2*n, 1, 2*n); b.setbounds(1, 2*n, 1, 2*n); c1.setbounds(1, 2*n, 1, 2*n); c2.setbounds(1, 2*n, 1, 2*n); x1.setbounds(1, n); x2.setbounds(1, n); for(i = 1; i <= 2*n; i++) { for(j = 1; j <= 2*n; j++) { a(i,j) = ap::randomreal(); b(i,j) = ap::randomreal(); } } passcount = 1000; was1 = false; for(pass = 1; pass <= passcount; pass++) { for(i = 1; i <= 2*n; i++) { for(j = 1; j <= 2*n; j++) { c1(i,j) = 2.1*i+3.1*j; c2(i,j) = c1(i,j); } } l = 1+ap::randominteger(n); k = 1+ap::randominteger(n); r = 1+ap::randominteger(n); i1 = 1+ap::randominteger(n); j1 = 1+ap::randominteger(n); i2 = 1+ap::randominteger(n); j2 = 1+ap::randominteger(n); i3 = 1+ap::randominteger(n); j3 = 1+ap::randominteger(n); trans1 = ap::fp_greater(ap::randomreal(),0.5); trans2 = ap::fp_greater(ap::randomreal(),0.5); if( trans1 ) { col1 = l; row1 = k; } else { col1 = k; row1 = l; } if( trans2 ) { col2 = k; row2 = r; } else { col2 = r; row2 = k; } scl1 = ap::randomreal(); scl2 = ap::randomreal(); matrixmatrixmultiply(a, i1, i1+row1-1, j1, j1+col1-1, trans1, b, i2, i2+row2-1, j2, j2+col2-1, trans2, scl1, c1, i3, i3+l-1, j3, j3+r-1, scl2, x1); naivematrixmatrixmultiply(a, i1, i1+row1-1, j1, j1+col1-1, trans1, b, i2, i2+row2-1, j2, j2+col2-1, trans2, scl1, c2, i3, i3+l-1, j3, j3+r-1, scl2); err = 0; for(i = 1; i <= l; i++) { for(j = 1; j <= r; j++) { err = ap::maxreal(err, fabs(c1(i3+i-1,j3+j-1)-c2(i3+i-1,j3+j-1))); } } if( ap::fp_greater(err,threshold) ) { was1 = true; break; } } mmerrors = was1; // // report // waserrors = n2errors||amaxerrors||hsnerrors||mverrors||iterrors||cterrors||mmerrors; if( !silent ) { printf("TESTING BLAS\n"); printf("VectorNorm2: "); if( n2errors ) { printf("FAILED\n"); } else { printf("OK\n"); } printf("AbsMax (vector/row/column): "); if( amaxerrors ) { printf("FAILED\n"); } else { printf("OK\n"); } printf("UpperHessenberg1Norm: "); if( hsnerrors ) { printf("FAILED\n"); } else { printf("OK\n"); } printf("MatrixVectorMultiply: "); if( mverrors ) { printf("FAILED\n"); } else { printf("OK\n"); } printf("InplaceTranspose: "); if( iterrors ) { printf("FAILED\n"); } else { printf("OK\n"); } printf("CopyAndTranspose: "); if( cterrors ) { printf("FAILED\n"); } else { printf("OK\n"); } printf("MatrixMatrixMultiply: "); if( mmerrors ) { printf("FAILED\n"); } else { printf("OK\n"); } if( waserrors ) { printf("TEST FAILED\n"); } else { printf("TEST PASSED\n"); } printf("\n\n"); } result = !waserrors; return result; }
/************************************************************************* Weighted constained linear least squares fitting. This is variation of LSFitLinearW(), which searchs for min|A*x=b| given that K additional constaints C*x=bc are satisfied. It reduces original task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW() is called. INPUT PARAMETERS: Y - array[0..N-1] Function values in N points. W - array[0..N-1] Weights corresponding to function values. Each summand in square sum of approximation deviations from given values is multiplied by the square of corresponding weight. FMatrix - a table of basis functions values, array[0..N-1, 0..M-1]. FMatrix[I,J] - value of J-th basis function in I-th point. CMatrix - a table of constaints, array[0..K-1,0..M]. I-th row of CMatrix corresponds to I-th linear constraint: CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] N - number of points used. N>=1. M - number of basis functions, M>=1. K - number of constraints, 0 <= K < M K=0 corresponds to absence of constraints. OUTPUT PARAMETERS: Info - error code: * -4 internal SVD decomposition subroutine failed (very rare and for degenerate systems only) * -3 either too many constraints (M or more), degenerate constraints (some constraints are repetead twice) or inconsistent constraints were specified. * -1 incorrect N/M/K were specified * 1 task is solved C - decomposition coefficients, array[0..M-1] Rep - fitting report. Following fields are set: * RMSError rms error on the (X,Y). * AvgError average error on the (X,Y). * AvgRelError average relative error on the non-zero Y * MaxError maximum error NON-WEIGHTED ERRORS ARE CALCULATED IMPORTANT: this subroitine doesn't calculate task's condition number for K<>0. SEE ALSO LSFitLinear LSFitLinearC LSFitLinearWC -- ALGLIB -- Copyright 07.09.2009 by Bochkanov Sergey *************************************************************************/ void lsfitlinearwc(ap::real_1d_array y, const ap::real_1d_array& w, const ap::real_2d_array& fmatrix, ap::real_2d_array cmatrix, int n, int m, int k, int& info, ap::real_1d_array& c, lsfitreport& rep) { int i; int j; ap::real_1d_array tau; ap::real_2d_array q; ap::real_2d_array f2; ap::real_1d_array tmp; ap::real_1d_array c0; double v; if( n<1||m<1||k<0 ) { info = -1; return; } if( k>=m ) { info = -3; return; } // // Solve // if( k==0 ) { // // no constraints // lsfitlinearinternal(y, w, fmatrix, n, m, info, c, rep); } else { // // First, find general form solution of constraints system: // * factorize C = L*Q // * unpack Q // * fill upper part of C with zeros (for RCond) // // We got C=C0+Q2'*y where Q2 is lower M-K rows of Q. // rmatrixlq(cmatrix, k, m, tau); rmatrixlqunpackq(cmatrix, k, m, tau, m, q); for(i = 0; i <= k-1; i++) { for(j = i+1; j <= m-1; j++) { cmatrix(i,j) = 0.0; } } if( ap::fp_less(rmatrixlurcondinf(cmatrix, k),1000*ap::machineepsilon) ) { info = -3; return; } tmp.setlength(k); for(i = 0; i <= k-1; i++) { if( i>0 ) { v = ap::vdotproduct(&cmatrix(i, 0), 1, &tmp(0), 1, ap::vlen(0,i-1)); } else { v = 0; } tmp(i) = (cmatrix(i,m)-v)/cmatrix(i,i); } c0.setlength(m); for(i = 0; i <= m-1; i++) { c0(i) = 0; } for(i = 0; i <= k-1; i++) { v = tmp(i); ap::vadd(&c0(0), 1, &q(i, 0), 1, ap::vlen(0,m-1), v); } // // Second, prepare modified matrix F2 = F*Q2' and solve modified task // tmp.setlength(ap::maxint(n, m)+1); f2.setlength(n, m-k); matrixvectormultiply(fmatrix, 0, n-1, 0, m-1, false, c0, 0, m-1, -1.0, y, 0, n-1, 1.0); matrixmatrixmultiply(fmatrix, 0, n-1, 0, m-1, false, q, k, m-1, 0, m-1, true, 1.0, f2, 0, n-1, 0, m-k-1, 0.0, tmp); lsfitlinearinternal(y, w, f2, n, m-k, info, tmp, rep); rep.taskrcond = -1; if( info<=0 ) { return; } // // then, convert back to original answer: C = C0 + Q2'*Y0 // c.setlength(m); ap::vmove(&c(0), 1, &c0(0), 1, ap::vlen(0,m-1)); matrixvectormultiply(q, k, m-1, 0, m-1, true, tmp, 0, m-k-1, 1.0, c, 0, m-1, 1.0); } }
// Perform exact (and slower) NR test using the exact fisher information matrix. vector<double> LogisticRegression::newtonRaphson(const vector<vector<double> > &data, const vector<double> &response, vector<vector<double> > &invInfMatrix, double startVal) { vector<double> betas; // Variables used in the computation: alglib::real_1d_array tempBetas; alglib::real_2d_array tempData; alglib::real_2d_array tempDataTrans; alglib::real_1d_array oldExpY; alglib::real_2d_array hessian; // holds data' * w * data. Returned in last input param. alglib::real_1d_array expY; alglib::real_1d_array W; // holds diagonal of the w matrix above. alglib::real_1d_array adjy; alglib::real_1d_array work; double stop_var = 1e-10; int iter = 0; int maxIter = 200; int numVars = data.size(); if(numVars < 1){ throw NewtonRaphsonFailureEx(); } int numSamples = data.at(0).size(); if(numSamples < 1){ throw NewtonRaphsonFailureEx(); } tempBetas.setlength(numVars); tempData.setlength(numSamples,numVars); tempDataTrans.setlength(numVars, numSamples); oldExpY.setlength(numSamples); expY.setlength(numSamples); hessian.setlength(numVars, numVars); adjy.setlength(numSamples); W.setlength(numSamples); work.setlength(numVars); for(int i=0;i < numVars; i++){ for(int j=0;j < numSamples; j++){ tempData(j,i) = data.at(i).at(j); } tempBetas(i) = startVal; } for(int i=0;i < numSamples;i++){ oldExpY(i) = -1; adjy(i) = 0; // makes valgrind happier. } // End initial setup. // In each iteration, create a hessian and a first derivative. while(iter < maxIter){ //adjy <- data * tempBetas (get new y guess) matrixvectormultiply(tempData, 0, numSamples-1,0,numVars-1,false, tempBetas, 0, numVars-1, 1.0, adjy, 0, numSamples-1, 0.0); // adjy = 1 / (1 + exp(-adjy)) for(int i=0;i < numSamples; i++){ expY(i) = 1 / (1 + exp(-adjy(i))); } // build deriv. for(int i=0;i < numSamples; i++){ W(i) = expY(i) * (1 - expY(i)); } // adjy = adjy + (y-expy) ./ deriv for(int i=0;i<numSamples;i++){ adjy(i) = adjy(i) + (response.at(i) - expY(i)) / W(i); } // build data' * w * data // set to hessian. // Also doing secondary computation (see inside) for(int i=0; i < numVars; i++){ for(int j=0; j < numVars; j++) hessian(i,j) = 0.0; } for(int indiv=0; indiv < numSamples; ++indiv){ for(int i = 0; i < numVars; i++){ for(int j = 0; j < numVars; j++){ hessian(i,j) += W(indiv) * tempData(indiv, j) * tempData(indiv, i); } // NOTE: as a speedup, I'm also computing X' * W tempDataTrans(i, indiv) = W(indiv) * tempData(indiv, i); } } alglib::matinvreport report; alglib::ae_int_t reportInfo; rmatrixinverse(hessian, reportInfo, report); if(reportInfo != 1 ){ throw SingularMatrixEx(); } // Check condition number. if (report.r1 < condition_number_limit){ throw ConditionNumberEx(1.0/report.r1); } // work <- X'W * adjy matrixvectormultiply(tempDataTrans,0,numVars-1,0,numSamples-1,false, adjy,0,numSamples-1,1, work,0,numVars-1,0.0); // tempBetas <= invHessian * work matrixvectormultiply(hessian,0,numVars-1,0,numVars-1,false, work,0,numVars-1,1.0, tempBetas,0,numVars-1,0.0); #if DEBUG_NR cout << "Betas "; for(int i=0;i < numVars;i++) cout << tempBetas(i) << " " ; cout << endl; #endif double stop = 0.0; // Could be computed as a 1-norm. // This should be done as a sum of abs diff. for(int i=0;i < numSamples;i++){ stop += abs(expY(i) - oldExpY(i)); } if (stop < numSamples*stop_var){ break; } oldExpY = expY; iter++; } if(iter == maxIter){ throw NewtonRaphsonIterationEx(); } betas.clear(); for(int i=0;i<numVars;i++){ betas.push_back(tempBetas(i)); } for(int i=0;i<numVars;i++){ for(int j=0;j<numVars;j++){ invInfMatrix.at(i).at(j) = hessian(i,j); } } //dumpMatrix(invInfMatrix); return betas; }
/* * @depricated * * NR implementation by RTG. * * Note on matrix vector multiplication: * void matrixmatrixmultiply(const alglib::real_2d_array& a, * int ai1, * int ai2, * int aj1, * int aj2, * bool transa, * const alglib::real_2d_array& b, * int bi1, * int bi2, * int bj1, * int bj2, * bool transb, * double alpha, * alglib::real_2d_array& c, * int ci1, * int ci2, * int cj1, * int cj2, * double beta, * alglib::real_1d_array& work); * * transa is true if transposed. * Operation is: c = A * alpha * b + beta * C * * * @input const vector<vector<double>> data holds explantory variables. each inner vector is a variable. * @input const vector<double> response holds response variable. * @input vector<double> Place to return the information matrix inverse. Column major order. * Expects correct size. */ vector<double> LogisticRegression::newtonRaphsonFast(const vector<vector<double> > &data, const vector<double> &response , vector<vector<double> > &invInfMatrix, double startVal) { vector<double> betas; // Variables used in the computation: alglib::real_1d_array tempBetas; alglib::real_2d_array tempData; alglib::real_1d_array oldExpY; alglib::real_2d_array tempDeriv; // holds data' * w * data. Returned in last input param. alglib::real_1d_array expY; alglib::real_1d_array adjy; double stop_var = 1e-10; int iter = 0; int maxIter = 200; int numVars = data.size(); if(numVars < 1){ throw NewtonRaphsonFailureEx(); } int numSamples = data.at(0).size(); if(numSamples < 1){ throw NewtonRaphsonFailureEx(); } tempBetas.setlength(numVars); tempData.setlength(numSamples,numVars); oldExpY.setlength(numSamples); expY.setlength(numSamples); tempDeriv.setlength(numVars,numVars); adjy.setlength(numSamples); for(int i=0;i < numVars; i++){ for(int j=0;j < numSamples; j++){ tempData(j,i) = data.at(i).at(j); } tempBetas(i) = startVal; } for(int i=0;i < numSamples;i++){ oldExpY(i) = -1; adjy(i) = 0; // makes valgrind happier. } while(iter < maxIter){ //data * tempBetas matrixvectormultiply(tempData, 0, numSamples-1,0,numVars-1,false, tempBetas, 0, numVars-1, 1.0, adjy, 0, numSamples-1, 0.0); for(int i=0;i < numSamples; i++){ expY(i) = 1 / (1 + exp(-adjy(i))); } // build deriv. double deriv = -100000; for(int i=0;i < numSamples; i++){ if(expY(i) * (1 - expY(i)) > deriv) deriv = expY(i) * (1 - expY(i)); } if(stop_var * 0.001 > deriv) deriv = stop_var * 0.001; // adjy = adjy + (y-expy) ./ deriv for(int i=0;i<numSamples;i++){ adjy(i) = adjy(i) + (response.at(i) - expY(i)) / deriv; } // build data' * w * data alglib::real_1d_array work; work.setlength(numSamples); // This temporary workspace must be one larger than the longest // row or column that will be seen. Otherwise, the program // crashes or - worse! - corrupts data. matrixmatrixmultiply(tempData,0,numSamples-1,0,numVars-1,true, tempData,0,numSamples-1,0,numVars-1,false,deriv, tempDeriv,0,numVars-1,0,numVars-1,0.0,work); #if DEBUG_NR cout << "A' * w * A " << endl; cout << tempDeriv(0,0) << " " << tempDeriv(0,1) << endl; cout << tempDeriv(1,0) << " " << tempDeriv(1,1) << endl; cout << endl; #endif alglib::matinvreport report; alglib::ae_int_t reportInfo; rmatrixinverse(tempDeriv, reportInfo, report); if( reportInfo != 1 ){ throw SingularMatrixEx(); } #if DEBUG_NR cout << "inv(A' * w * A) " << endl; cout << tempDeriv(0,0) << " " << tempDeriv(0,1) << endl; cout << tempDeriv(1,0) << " " << tempDeriv(1,1) << endl; cout << endl; #endif matrixvectormultiply(tempData,0,numSamples-1,0,numVars-1,true, adjy,0,numSamples-1,deriv, work,0,numVars-1,0.0); matrixvectormultiply(tempDeriv,0,numVars-1,0,numVars-1,false, work,0,numVars-1,1.0, tempBetas,0,numVars-1,0.0); #if DEBUG_NR cout << "Betas "; for(int i=0;i < numVars;i++) cout << tempBetas(i) << " " ; cout << endl; #endif double stop = 0.0; for(int i=0;i < numSamples;i++){ stop += abs(expY(i) - oldExpY(i)); } if (stop < numSamples*stop_var){ break; } oldExpY = expY; iter++; } if(iter == maxIter){ throw NewtonRaphsonIterationEx(); } betas.clear(); for(int i=0;i<numVars;i++){ betas.push_back(tempBetas(i)); } for(int i=0;i<numVars;i++){ for(int j=0;j<numVars;j++){ invInfMatrix.at(i).at(j) = tempDeriv(i,j); } } return betas; }