コード例 #1
0
ファイル: test_svi.c プロジェクト: masa4u/clibs
static void target_func(double* p, double *f, double* g, int n, void* data) {
	int i;
	lbfgsb_param *param = (lbfgsb_param*)data;
	double weight = 0, error = 0, consts = 0.0, consts2 = 0.0;
	double sum = 0.0;

	for(i = 0; i < param->moneyness_size; i++) {
		double x = param->log_moneyness[i];
		double sig = param->quotes[i];
		double var_vec = sig*sig;
		double var_cal = svi(p, x);
		error += exp(x*3.0) * pow(var_cal - var_vec, 2);
		consts += user_min(var_cal, 0.0) * -0.1;
	}
	// calculate constraints 1
	consts = exp(user_max(p[1] * (1.0 + fabs(p[4])) * param->T - 4.0, 0.0) ) - 1.0;
	consts2= exp(consts) - 1.0;
	*f = error + consts + consts2;
}
コード例 #2
0
/*************************************************************************
Internal linear regression subroutine
*************************************************************************/
static void lrinternal(const ap::real_2d_array& xy,
     const ap::real_1d_array& s,
     int npoints,
     int nvars,
     int& info,
     linearmodel& lm,
     lrreport& ar)
{
    ap::real_2d_array a;
    ap::real_2d_array u;
    ap::real_2d_array vt;
    ap::real_2d_array vm;
    ap::real_2d_array xym;
    ap::real_1d_array b;
    ap::real_1d_array sv;
    ap::real_1d_array t;
    ap::real_1d_array svi;
    ap::real_1d_array work;
    int i;
    int j;
    int k;
    int ncv;
    int na;
    int nacv;
    double r;
    double p;
    double epstol;
    lrreport ar2;
    int offs;
    linearmodel tlm;

    epstol = 1000;
    
    //
    // Check for errors in data
    //
    if( npoints<nvars||nvars<1 )
    {
        info = -1;
        return;
    }
    for(i = 0; i <= npoints-1; i++)
    {
        if( ap::fp_less_eq(s(i),0) )
        {
            info = -2;
            return;
        }
    }
    info = 1;
    
    //
    // Create design matrix
    //
    a.setbounds(0, npoints-1, 0, nvars-1);
    b.setbounds(0, npoints-1);
    for(i = 0; i <= npoints-1; i++)
    {
        r = 1/s(i);
        ap::vmove(&a(i, 0), &xy(i, 0), ap::vlen(0,nvars-1), r);
        b(i) = xy(i,nvars)/s(i);
    }
    
    //
    // Allocate W:
    // W[0]     array size
    // W[1]     version number, 0
    // W[2]     NVars (minus 1, to be compatible with external representation)
    // W[3]     coefficients offset
    //
    lm.w.setbounds(0, 4+nvars-1);
    offs = 4;
    lm.w(0) = 4+nvars;
    lm.w(1) = lrvnum;
    lm.w(2) = nvars-1;
    lm.w(3) = offs;
    
    //
    // Solve problem using SVD:
    //
    // 0. check for degeneracy (different types)
    // 1. A = U*diag(sv)*V'
    // 2. T = b'*U
    // 3. w = SUM((T[i]/sv[i])*V[..,i])
    // 4. cov(wi,wj) = SUM(Vji*Vjk/sv[i]^2,K=1..M)
    //
    // see $15.4 of "Numerical Recipes in C" for more information
    //
    t.setbounds(0, nvars-1);
    svi.setbounds(0, nvars-1);
    ar.c.setbounds(0, nvars-1, 0, nvars-1);
    vm.setbounds(0, nvars-1, 0, nvars-1);
    if( !rmatrixsvd(a, npoints, nvars, 1, 1, 2, sv, u, vt) )
    {
        info = -4;
        return;
    }
    if( ap::fp_less_eq(sv(0),0) )
    {
        
        //
        // Degenerate case: zero design matrix.
        //
        for(i = offs; i <= offs+nvars-1; i++)
        {
            lm.w(i) = 0;
        }
        ar.rmserror = lrrmserror(lm, xy, npoints);
        ar.avgerror = lravgerror(lm, xy, npoints);
        ar.avgrelerror = lravgrelerror(lm, xy, npoints);
        ar.cvrmserror = ar.rmserror;
        ar.cvavgerror = ar.avgerror;
        ar.cvavgrelerror = ar.avgrelerror;
        ar.ncvdefects = 0;
        ar.cvdefects.setbounds(0, nvars-1);
        ar.c.setbounds(0, nvars-1, 0, nvars-1);
        for(i = 0; i <= nvars-1; i++)
        {
            for(j = 0; j <= nvars-1; j++)
            {
                ar.c(i,j) = 0;
            }
        }
        return;
    }
    if( ap::fp_less_eq(sv(nvars-1),epstol*ap::machineepsilon*sv(0)) )
    {
        
        //
        // Degenerate case, non-zero design matrix.
        //
        // We can leave it and solve task in SVD least squares fashion.
        // Solution and covariance matrix will be obtained correctly,
        // but CV error estimates - will not. It is better to reduce
        // it to non-degenerate task and to obtain correct CV estimates.
        //
        for(k = nvars; k >= 1; k--)
        {
            if( ap::fp_greater(sv(k-1),epstol*ap::machineepsilon*sv(0)) )
            {
                
                //
                // Reduce
                //
                xym.setbounds(0, npoints-1, 0, k);
                for(i = 0; i <= npoints-1; i++)
                {
                    for(j = 0; j <= k-1; j++)
                    {
                        r = ap::vdotproduct(&xy(i, 0), &vt(j, 0), ap::vlen(0,nvars-1));
                        xym(i,j) = r;
                    }
                    xym(i,k) = xy(i,nvars);
                }
                
                //
                // Solve
                //
                lrinternal(xym, s, npoints, k, info, tlm, ar2);
                if( info!=1 )
                {
                    return;
                }
                
                //
                // Convert back to un-reduced format
                //
                for(j = 0; j <= nvars-1; j++)
                {
                    lm.w(offs+j) = 0;
                }
                for(j = 0; j <= k-1; j++)
                {
                    r = tlm.w(offs+j);
                    ap::vadd(&lm.w(offs), &vt(j, 0), ap::vlen(offs,offs+nvars-1), r);
                }
                ar.rmserror = ar2.rmserror;
                ar.avgerror = ar2.avgerror;
                ar.avgrelerror = ar2.avgrelerror;
                ar.cvrmserror = ar2.cvrmserror;
                ar.cvavgerror = ar2.cvavgerror;
                ar.cvavgrelerror = ar2.cvavgrelerror;
                ar.ncvdefects = ar2.ncvdefects;
                ar.cvdefects.setbounds(0, nvars-1);
                for(j = 0; j <= ar.ncvdefects-1; j++)
                {
                    ar.cvdefects(j) = ar2.cvdefects(j);
                }
                ar.c.setbounds(0, nvars-1, 0, nvars-1);
                work.setbounds(1, nvars);
                matrixmatrixmultiply(ar2.c, 0, k-1, 0, k-1, false, vt, 0, k-1, 0, nvars-1, false, 1.0, vm, 0, k-1, 0, nvars-1, 0.0, work);
                matrixmatrixmultiply(vt, 0, k-1, 0, nvars-1, true, vm, 0, k-1, 0, nvars-1, false, 1.0, ar.c, 0, nvars-1, 0, nvars-1, 0.0, work);
                return;
            }
        }
        info = -255;
        return;
    }
    for(i = 0; i <= nvars-1; i++)
    {
        if( ap::fp_greater(sv(i),epstol*ap::machineepsilon*sv(0)) )
        {
            svi(i) = 1/sv(i);
        }
        else
        {
            svi(i) = 0;
        }
    }
    for(i = 0; i <= nvars-1; i++)
    {
        t(i) = 0;
    }
    for(i = 0; i <= npoints-1; i++)
    {
        r = b(i);
        ap::vadd(&t(0), &u(i, 0), ap::vlen(0,nvars-1), r);
    }
    for(i = 0; i <= nvars-1; i++)
    {
        lm.w(offs+i) = 0;
    }
    for(i = 0; i <= nvars-1; i++)
    {
        r = t(i)*svi(i);
        ap::vadd(&lm.w(offs), &vt(i, 0), ap::vlen(offs,offs+nvars-1), r);
    }
    for(j = 0; j <= nvars-1; j++)
    {
        r = svi(j);
        ap::vmove(vm.getcolumn(j, 0, nvars-1), vt.getrow(j, 0, nvars-1), r);
    }
    for(i = 0; i <= nvars-1; i++)
    {
        for(j = i; j <= nvars-1; j++)
        {
            r = ap::vdotproduct(&vm(i, 0), &vm(j, 0), ap::vlen(0,nvars-1));
            ar.c(i,j) = r;
            ar.c(j,i) = r;
        }
    }
    
    //
    // Leave-1-out cross-validation error.
    //
    // NOTATIONS:
    // A            design matrix
    // A*x = b      original linear least squares task
    // U*S*V'       SVD of A
    // ai           i-th row of the A
    // bi           i-th element of the b
    // xf           solution of the original LLS task
    //
    // Cross-validation error of i-th element from a sample is
    // calculated using following formula:
    //
    //     ERRi = ai*xf - (ai*xf-bi*(ui*ui'))/(1-ui*ui')     (1)
    //
    // This formula can be derived from normal equations of the
    // original task
    //
    //     (A'*A)x = A'*b                                    (2)
    //
    // by applying modification (zeroing out i-th row of A) to (2):
    //
    //     (A-ai)'*(A-ai) = (A-ai)'*b
    //
    // and using Sherman-Morrison formula for updating matrix inverse
    //
    // NOTE 1: b is not zeroed out since it is much simpler and
    // does not influence final result.
    //
    // NOTE 2: some design matrices A have such ui that 1-ui*ui'=0.
    // Formula (1) can't be applied for such cases and they are skipped
    // from CV calculation (which distorts resulting CV estimate).
    // But from the properties of U we can conclude that there can
    // be no more than NVars such vectors. Usually
    // NVars << NPoints, so in a normal case it only slightly
    // influences result.
    //
    ncv = 0;
    na = 0;
    nacv = 0;
    ar.rmserror = 0;
    ar.avgerror = 0;
    ar.avgrelerror = 0;
    ar.cvrmserror = 0;
    ar.cvavgerror = 0;
    ar.cvavgrelerror = 0;
    ar.ncvdefects = 0;
    ar.cvdefects.setbounds(0, nvars-1);
    for(i = 0; i <= npoints-1; i++)
    {
        
        //
        // Error on a training set
        //
        r = ap::vdotproduct(&xy(i, 0), &lm.w(offs), ap::vlen(0,nvars-1));
        ar.rmserror = ar.rmserror+ap::sqr(r-xy(i,nvars));
        ar.avgerror = ar.avgerror+fabs(r-xy(i,nvars));
        if( ap::fp_neq(xy(i,nvars),0) )
        {
            ar.avgrelerror = ar.avgrelerror+fabs((r-xy(i,nvars))/xy(i,nvars));
            na = na+1;
        }
        
        //
        // Error using fast leave-one-out cross-validation
        //
        p = ap::vdotproduct(&u(i, 0), &u(i, 0), ap::vlen(0,nvars-1));
        if( ap::fp_greater(p,1-epstol*ap::machineepsilon) )
        {
            ar.cvdefects(ar.ncvdefects) = i;
            ar.ncvdefects = ar.ncvdefects+1;
            continue;
        }
        r = s(i)*(r/s(i)-b(i)*p)/(1-p);
        ar.cvrmserror = ar.cvrmserror+ap::sqr(r-xy(i,nvars));
        ar.cvavgerror = ar.cvavgerror+fabs(r-xy(i,nvars));
        if( ap::fp_neq(xy(i,nvars),0) )
        {
            ar.cvavgrelerror = ar.cvavgrelerror+fabs((r-xy(i,nvars))/xy(i,nvars));
            nacv = nacv+1;
        }
        ncv = ncv+1;
    }
    if( ncv==0 )
    {
        
        //
        // Something strange: ALL ui are degenerate.
        // Unexpected...
        //
        info = -255;
        return;
    }
    ar.rmserror = sqrt(ar.rmserror/npoints);
    ar.avgerror = ar.avgerror/npoints;
    if( na!=0 )
    {
        ar.avgrelerror = ar.avgrelerror/na;
    }
    ar.cvrmserror = sqrt(ar.cvrmserror/ncv);
    ar.cvavgerror = ar.cvavgerror/ncv;
    if( nacv!=0 )
    {
        ar.cvavgrelerror = ar.cvavgrelerror/nacv;
    }
}