9 #include <eigen3/Eigen/Dense>    15 #include "../Generic/debug.hpp"    16 #include "../Generic/generics.hpp"    20 template < 
typename T >
    30     FOS( Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > x, Eigen::Matrix< T, Eigen::Dynamic, 1 > y );
    34     Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > ReturnBetas();
    35     unsigned int ReturnOptimIndex();
    36     Eigen::Matrix< T, Eigen::Dynamic, 1 > ReturnCoefficients();
    37     Eigen::Matrix< T, Eigen::Dynamic, 1 > ReturnSupport();
    40     Eigen::Matrix< T, Eigen::Dynamic, 1 > avfos_fit;
    42     unsigned int optim_index;
    45     std::vector< T > GenerateLambdaGrid(
const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &X,
    46                                         const Eigen::Matrix<T, Eigen::Dynamic, 1 > &Y,
    50     bool ComputeStatsCond(
    52         unsigned int stats_it,
    54         const std::vector<T>& lambdas,
    55         const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
    56         const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& Betas );
    58     T duality_gap_target( T gamma, T C, T r_stats_it, 
unsigned int n );
    59     T dual_objective ( 
const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X, \
    60                        const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
    61                        const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta, \
    63     T primal_objective( 
const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X, \
    64                         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
    65                         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta, \
    69         const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
    70         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
    71         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta );
    74         const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
    75         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
    76         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta,
    77         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_prime,
    80     Eigen::Matrix< T, Eigen::Dynamic, 1 > update_beta_ista (
    81         const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
    82         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
    83         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta,
    87     Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > 
ISTA (
    88         const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X, \
    89         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
    90         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0, \
    91         unsigned int num_iterations, \
    95     Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > Betas;
    96     Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > old_Betas;
    98     Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > X;
    99     Eigen::Matrix< T, Eigen::Dynamic, 1 > Y;
   102     const unsigned int M = 100;
   109     unsigned int statsIt = 1;
   111     unsigned int n = 0, p = 0;
   113     std::vector< T > lambda_grid;
   115     unsigned int loop_index = 0;
   119 template< 
typename T >
   129 FOS< T >::FOS(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> x, Eigen::Matrix<T, Eigen::Dynamic, 1 > y ) : X( x ), Y( y ) {
   130     static_assert(std::is_floating_point< T >::value, 
"FOS can only be used with floating point types.");
   133 template < 
typename T >
   138 template < 
typename T >
   143 template < 
typename T >
   148 template < 
typename T >
   153 template < 
typename T >
   156     T C_t = 
static_cast<T
>( C );
   157     T n_t = 
static_cast<T
>( X.rows() );
   165 template < 
typename T >
   166 T compute_lp_norm( T& matrix, 
int norm_type ) {
   167     return matrix.template lpNorm< norm_type >();
   170 template < 
typename T >
   171 T compute_sqr_norm( T& matrix ) {
   172     return matrix.squaredNorm();
   177 template < 
typename T >
   187                               unsigned int stats_it,
   189                               const std::vector<T> &lambdas,
   190                               const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
   191                               const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& Betas ) {
   193     bool stats_cond = 
true;
   195     for ( 
unsigned int i = 1; i <= stats_it; i++ ) {
   197         Eigen::Matrix< T, Eigen::Dynamic, 1 > beta_k = Betas.col( i - 1 );
   198         T rk = lambdas.at( i - 1 );
   200         Eigen::Matrix< T, Eigen::Dynamic, 1 > beta_diff = Betas.col( stats_it - 1 );
   202         T abs_max_betas = beta_diff.cwiseAbs().maxCoeff();
   204         T n = 
static_cast<T
>( X.rows() );
   206         T check_parameter = n*abs_max_betas / ( r_stats_it + rk );
   208         stats_cond &= ( check_parameter <= C );
   215 template < 
typename T >
   221         const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
   224     T rMax = 2.0*( X.transpose() * Y ).
template lpNorm< Eigen::Infinity >();
   231 template < 
typename T >
   244     T n_f = 
static_cast<T
>( n );
   249 template < 
typename T >
   251                               const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
   252                               const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta, \
   255     Eigen::Matrix< T, Eigen::Dynamic, 1 > error = Y - X*Beta;
   256     T f_beta = error.squaredNorm() + r_stats_it*Beta.template lpNorm < 1 >();
   262 template < 
typename T >
   264                              const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
   265                              const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta, \
   269     T s_chunk =  r_stats_it / ( 2.0*X.transpose()*( X*Beta - Y ) ).template lpNorm< Eigen::Infinity >();
   270     T s_chunk_prime = ( - 
static_cast<T
>( Y.transpose()*( X*Beta - Y ) ) )/( Y - X*Beta ).squaredNorm();
   271     T s = std::min( std::max( - s_chunk, s_chunk_prime ), s_chunk );
   274     Eigen::Matrix< T, Eigen::Dynamic, 1 > nu_tilde = 2.0*s/r_stats_it*( X*Beta - Y );
   276     T d_nu = 
square( r_stats_it )/4.0*( nu_tilde + 2.0/r_stats_it*Y ).squaredNorm() - Y.squaredNorm();
   281 template < 
typename T >
   283     const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
   284     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
   285     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta ) {
   287     return (X*Beta - Y).squaredNorm();
   291 template < 
typename T >
   293     const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
   294     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
   295     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta,
   296     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_prime,
   299     Eigen::Matrix< T, Eigen::Dynamic, 1 > f_beta = X*Beta_prime - Y;
   300     T taylor_term_0 = f_beta.squaredNorm();
   302     Eigen::Matrix< T, Eigen::Dynamic, 1 > f_grad = 2.0*X.transpose()*( f_beta );
   303     Eigen::Matrix< T, Eigen::Dynamic, 1 > beta_diff = ( Beta - Beta_prime );
   305     T taylor_term_1 = f_grad.transpose()*beta_diff;
   307     T taylor_term_2 = L/2.0*beta_diff.squaredNorm();
   309     return taylor_term_0 + taylor_term_1 + taylor_term_2;
   312 template < 
typename T >
   314     const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
   315     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
   316     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta,
   320     Eigen::Matrix< T, Eigen::Dynamic, 1 > f_grad = 2.0*( X.transpose()*( X*Beta - Y ) );
   321     Eigen::Matrix< T, Eigen::Dynamic, 1 > beta_to_modify = Beta - (1.0/L)*f_grad;
   323     return beta_to_modify.unaryExpr( 
SoftThres<T>( thres/L ) );
   327 template < 
typename T >
   328 Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >  
FOS<T>::ISTA (
   329     const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X, \
   330     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y, \
   331     const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0, \
   332     unsigned int num_iterations, \
   339     Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta = Beta_0;
   341     for( 
unsigned int i = 0; i < num_iterations; i++ ) {
   343         unsigned int counter = 0;
   345         Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta_temp = update_beta_ista( X, Y, Beta, L, lambda );
   350         while( ( f_beta( X, Y, Beta_temp ) > f_beta_tilda( X, Y, Beta_temp, Beta, L ) ) ) {
   355             Beta_temp = update_beta_ista( X, Y, Beta, L, lambda );
   359         Beta = update_beta_ista( X, Y, Beta, L, lambda );
   369 template< 
typename T >
   382     lambda_grid = GenerateLambdaGrid( X, Y, M );
   384     bool statsCont = 
true;
   385     unsigned int statsIt = 1;
   387     Betas = Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >::Zero( X.cols(), M );
   391     while( statsCont && ( statsIt < M ) ) {
   397         old_Betas = Betas.col( statsIt - 2 );
   398         T rStatsIt = lambda_grid.at( statsIt - 1 );
   406             T duality_gap = primal_objective( X, Y, old_Betas, rStatsIt ) + dual_objective( X, Y, old_Betas, rStatsIt );
   409             unsigned int n = 
static_cast< unsigned int >( X.rows() );
   410             T gap_target = duality_gap_target( gamma, C, rStatsIt, n );
   412             DEBUG_PRINT( 
"Duality gap is " << duality_gap << 
" gap target is " << gap_target );
   415             if( duality_gap <= gap_target ) {
   417                 DEBUG_PRINT( 
"Duality gap is below specified threshold, exiting inner loop." );
   418                 Betas.col( statsIt - 1 ) = old_Betas;
   426                 Betas.col( statsIt - 1 ) = 
ISTA( X, Y, old_Betas, 1, L_k_less_1, rStatsIt );
   427                 old_Betas = Betas.col( statsIt - 1 );
   433         statsCont = ComputeStatsCond( C, statsIt, rStatsIt, lambda_grid, X, Betas );
   436     avfos_fit = Betas.col( statsIt - 2 );
   437     lambda = lambda_grid.at( statsIt - 2 );
   438     optim_index = statsIt;
   440     std::cout << 
"Stopping Index: " << optim_index << std::endl;
 
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > Normalize(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Set the mean of a matrix to 0 and the standard deviation to 1. 
void Algorithm()
Run the main FOS algorithm. 
std::vector< T > LogScaleVector(T lower_bound, T upper_bound, unsigned int num_elements)
Generate a vector of logarithmically equally spaced points. 
Soft Threshold functor used to apply hdim::soft_threshold to each element in a matrix or vector...
#define DEBUG_PRINT(x,...)
T square(T &val)
Compute the square of a value. 
Run the Iterative Shrinking and Thresholding Algorthim. 
FOS(Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > x, Eigen::Matrix< T, Eigen::Dynamic, 1 > y)
Initialize a new algorithm, and instantiate member attributes X and Y.