// Copyright (C) 2016 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <dlib/optimization/elastic_net.h> #include "tester.h" #include <dlib/svm.h> #include <dlib/rand.h> #include <dlib/string.h> #include <vector> #include <sstream> #include <ctime> namespace { using namespace test; using namespace dlib; using namespace std; dlib::logger dlog("test.elastic_net"); // ---------------------------------------------------------------------------------------- matrix<double,0,1> basic_elastic_net( const matrix<double>& X, const matrix<double,0,1>& Y, double ridge_lambda, double lasso_budget, double eps ) { DLIB_CASSERT(X.nc() == Y.nr(),""); typedef matrix<double,0,1> sample_type; typedef linear_kernel<sample_type> kernel_type; svm_c_linear_dcd_trainer<kernel_type> trainer; trainer.solve_svm_l2_problem(true); const double C = 1/(2*ridge_lambda); trainer.set_c(C); trainer.set_epsilon(eps); trainer.enable_shrinking(true); trainer.include_bias(false); std::vector<sample_type> samples; std::vector<double> labels; for (long r = 0; r < X.nr(); ++r) { sample_type temp = trans(rowm(X,r)); const double xmul = (1/lasso_budget); samples.push_back(temp - xmul*Y); labels.push_back(+1); samples.push_back(temp + xmul*Y); labels.push_back(-1); } svm_c_linear_dcd_trainer<kernel_type>::optimizer_state state; auto df = trainer.train(samples, labels, state); auto&& alpha = state.get_alpha(); matrix<double,0,1> betas(alpha.size()/2); for (long i = 0; i < betas.size(); ++i) betas(i) = lasso_budget*(alpha[2*i] - alpha[2*i+1]); betas /= sum(mat(alpha)); return betas; } // ---------------------------------------------------------------------------------------- class test_elastic_net : public tester { public: test_elastic_net ( ) : tester ( "test_elastic_net", "Run tests on the elastic_net object.", 0 ) { } void perform_test ( ) { matrix<double> w = {1,2,0,4, 0,0,0,0,0, 6, 7,8,0, 9, 0}; matrix<double> X = randm(w.size(),1000); matrix<double> Y = trans(X)*w; Y += 0.1*(randm(Y.nr(), Y.nc())-0.5); double ridge_lambda = 0.1; double lasso_budget = sum(abs(w)); double eps = 0.0000001; dlib::elastic_net solver(X*trans(X),X*Y); solver.set_epsilon(eps); matrix<double,0,1> results; matrix<double,0,1> results2; for (double s = 1.2; s > 0.10; s *= 0.9) { print_spinner(); dlog << LINFO << "s: "<< s; // make sure the two solvers agree. results = basic_elastic_net(X, Y, ridge_lambda, lasso_budget*s, eps); results2 = solver(ridge_lambda, lasso_budget*s); dlog << LINFO << "error: "<< max(abs(results - results2)); DLIB_TEST(max(abs(results - results2) < 1e-3)); } } } a; // ---------------------------------------------------------------------------------------- }