Esempio n. 1
0
RcppExport SEXP admm_lasso_precond(SEXP x_, 
                                   SEXP y_, 
                                   SEXP family_,
                                   SEXP lambda_,
                                   SEXP nlambda_, 
                                   SEXP lmin_ratio_,
                                   SEXP penalty_factor_,
                                   SEXP standardize_, 
                                   SEXP intercept_,
                                   SEXP opts_)
{
BEGIN_RCPP

    //Rcpp::NumericMatrix xx(x_);
    //Rcpp::NumericVector yy(y_);
    
    
    Rcpp::NumericMatrix xx(x_);
    Rcpp::NumericVector yy(y_);
    
    const int n = xx.rows();
    const int p = xx.cols();
    
    MatrixXd datX(n, p);
    VectorXd datY(n);
    
    // Copy data 
    std::copy(xx.begin(), xx.end(), datX.data());
    std::copy(yy.begin(), yy.end(), datY.data());
    
    //MatrixXd datX(as<MatrixXd>(x_));
    //VectorXd datY(as<VectorXd>(y_));
    
    //const int n = datX.rows();
    //const int p = datX.cols();

    //MatrixXf datX(n, p);
    //VectorXf datY(n);

    // Copy data and convert type from double to float
    //std::copy(xx.begin(), xx.end(), datX.data());
    //std::copy(yy.begin(), yy.end(), datY.data());

    // In glmnet, we minimize
    //   1/(2n) * ||y - X * beta||^2 + lambda * ||beta||_1
    // which is equivalent to minimizing
    //   1/2 * ||y - X * beta||^2 + n * lambda * ||beta||_1
    ArrayXd lambda(as<ArrayXd>(lambda_));
    int nlambda = lambda.size();
    

    List opts(opts_);
    const int maxit        = as<int>(opts["maxit"]);
    const int irls_maxit     = as<int>(opts["irls_maxit"]);
    const double irls_tol    = as<double>(opts["irls_tol"]);
    const double eps_abs   = as<double>(opts["eps_abs"]);
    const double eps_rel   = as<double>(opts["eps_rel"]);
    const double rho       = as<double>(opts["rho"]);
    bool standardize   = as<bool>(standardize_);
    bool intercept     = as<bool>(intercept_);
    bool intercept_bin = intercept;
    
    CharacterVector family(as<CharacterVector>(family_));
    ArrayXd penalty_factor(as<ArrayXd>(penalty_factor_));
    
    // don't standardize if not linear model. 
    // fit intercept the dumb way if it is wanted
    bool fullbetamat = false;
    int add = 0;
    if (family(0) != "gaussian")
    {
        standardize = false;
        intercept = false;
        
        if (intercept_bin)
        {
            fullbetamat = true;
            add = 1;
            // dont penalize the intercept
            ArrayXd penalty_factor_tmp(p+1);
            
            penalty_factor_tmp << 0, penalty_factor;
            penalty_factor.swap(penalty_factor_tmp);
            
            VectorXd v(n);
            v.fill(1);
            MatrixXd datX_tmp(n, p+1);
            
            datX_tmp << v, datX;
            datX.swap(datX_tmp);
            
            datX_tmp.resize(0,0);
        }
    }
    
    DataStd<double> datstd(n, p + add, standardize, intercept);
    datstd.standardize(datX, datY);
    
    // initialize pointers 
    FADMMBasePrecond<Eigen::VectorXd, Eigen::SparseVector<double>, Eigen::VectorXd> *solver_tall = NULL; // obj doesn't point to anything yet
    ADMMBase<Eigen::SparseVector<double>, Eigen::VectorXd, Eigen::VectorXd> *solver_wide = NULL; // obj doesn't point to anything yet
    //ADMMLassoTall *solver_tall;
    //ADMMLassoWide *solver_wide;
    

    // initialize classes
    if(n > 2 * p)
    {
        solver_tall = new ADMMLassoTallPrecond(datX, datY, penalty_factor, eps_abs, eps_rel);
    } else
    {
        solver_wide = new ADMMLassoWide(datX, datY, penalty_factor, eps_abs, eps_rel);
    }

    
    if (nlambda < 1) {
        
        double lmax = 0.0;
        
        if(n > 2 * p) 
        {
            lmax = solver_tall->get_lambda_zero() / n * datstd.get_scaleY();
        } else
        {
            lmax = solver_wide->get_lambda_zero() / n * datstd.get_scaleY();
        }
        double lmin = as<double>(lmin_ratio_) * lmax;
        lambda.setLinSpaced(as<int>(nlambda_), std::log(lmax), std::log(lmin));
        lambda = lambda.exp();
        nlambda = lambda.size();
    }


    SpMat beta(p + 1, nlambda);
    beta.reserve(Eigen::VectorXi::Constant(nlambda, std::min(n, p)));

    IntegerVector niter(nlambda);
    double ilambda = 0.0;

    for(int i = 0; i < nlambda; i++)
    {
        ilambda = lambda[i] * n / datstd.get_scaleY();
        if(n > 2 * p)
        {
            if(i == 0)
                solver_tall->init(ilambda, rho);
            else
                solver_tall->init_warm(ilambda);

            niter[i] = solver_tall->solve(maxit);
            SpVec res = solver_tall->get_gamma();
            double beta0 = 0.0;
            if (!fullbetamat)
            {
                datstd.recover(beta0, res);
            }
            write_beta_matrix(beta, i, beta0, res, fullbetamat);
        } else {
            
            if(i == 0)
                solver_wide->init(ilambda, rho);
            else
                solver_wide->init_warm(ilambda, i);

            niter[i] = solver_wide->solve(maxit);
            SpVec res = solver_wide->get_beta();
            double beta0 = 0.0;
            if (!fullbetamat)
            {
                datstd.recover(beta0, res);
            }
            write_beta_matrix(beta, i, beta0, res, fullbetamat);
            
        }
    }
    

    if(n > 2 * p) 
    {
        delete solver_tall;
    }
    else
    {
        delete solver_wide;
    }

    beta.makeCompressed();

    return List::create(Named("lambda") = lambda,
                        Named("beta") = beta,
                        Named("niter") = niter);

END_RCPP
}
Esempio n. 2
0
RcppExport SEXP admm_enet(SEXP x_, SEXP y_, SEXP lambda_,
                          SEXP nlambda_, SEXP lmin_ratio_,
                          SEXP standardize_, SEXP intercept_,
                          SEXP alpha_, SEXP opts_)
{
BEGIN_RCPP

#if ADMM_PROFILE > 0
    clock_t t1, t2;
    t1 = clock();
#endif

    MatrixXd datX(as<MatrixXd>(x_));
    VectorXd datY(as<VectorXd>(y_));

    // In glmnet, we minimize
    //   1/(2n) * ||y - X * beta||^2 + lambda * ||beta||_1
    // which is equivalent to minimizing
    //   1/2 * ||y - X * beta||^2 + n * lambda * ||beta||_1
    int n = datX.rows();
    int p = datX.cols();
    ArrayXd lambda(as<ArrayXd>(lambda_));
    int nlambda = lambda.size();

    List opts(opts_);
    int maxit = as<int>(opts["maxit"]);
    double eps_abs = as<double>(opts["eps_abs"]);
    double eps_rel = as<double>(opts["eps_rel"]);
    double rho_ratio = as<double>(opts["rho_ratio"]);

    double alpha = as<double>(alpha_);

    bool standardize = as<bool>(standardize_);
    bool intercept = as<bool>(intercept_);

#if ADMM_PROFILE > 0
    t2 = clock();
    Rcpp::Rcout << "part1: " << double(t2 - t1) / CLOCKS_PER_SEC << " secs.\n";
#endif

    DataStd datstd(n, p, standardize, intercept);
    datstd.standardize(datX, datY);

#if ADMM_PROFILE > 0
    t1 = clock();
    Rcpp::Rcout << "part2: " << double(t1 - t2) / CLOCKS_PER_SEC << " secs.\n";
#endif

    ADMMEnet solver(datX, datY, alpha, eps_abs, eps_rel);

#if ADMM_PROFILE > 0
    t2 = clock();
    Rcpp::Rcout << "part3: " << double(t2 - t1) / CLOCKS_PER_SEC << " secs.\n";
#endif

    if(nlambda < 1)
    {
        double lmax = solver.get_lambda_zero() / n * datstd.get_scaleY();
        double lmin = as<double>(lmin_ratio_) * lmax;
        lambda.setLinSpaced(as<int>(nlambda_), log(lmax), log(lmin));
        lambda = lambda.exp();
        nlambda = lambda.size();
    }

    SpMat beta(p + 1, nlambda);
    beta.reserve(Eigen::VectorXi::Constant(nlambda, std::min(n, p)));

    IntegerVector niter(nlambda);
    double ilambda = 0.0;

    for(int i = 0; i < nlambda; i++)
    {
        ilambda = lambda[i] * n / datstd.get_scaleY();
        if(i == 0)
            solver.init(ilambda, rho_ratio);
        else
            solver.init_warm(ilambda);

        niter[i] = solver.solve(maxit);
        SpVec res = solver.get_x();
        double beta0 = 0.0;
        datstd.recover(beta0, res);
        write_beta_matrix(beta, i, beta0, res);
    }

#if ADMM_PROFILE > 0
    t1 = clock();
    Rcpp::Rcout << "part4: " << double(t1 - t2) / CLOCKS_PER_SEC << " secs.\n";
#endif

    beta.makeCompressed();

    return List::create(Named("lambda") = lambda,
                        Named("beta") = beta,
                        Named("niter") = niter);

END_RCPP
}