HDIM  1.0.0
Packages for High Dimensional Linear Regression
coordinate_descent.hpp
1 #ifndef COORDINATE_DESCENT_H
2 #define COORDINATE_DESCENT_H
3 
4 // C System-Headers
5 //
6 // C++ System headers
7 #include <vector>
8 #include <limits>
9 #include <iomanip>
10 #include <iostream>
11 #include <type_traits>
12 #include <algorithm>
13 // Eigen Headers
14 #include <eigen3/Eigen/Dense>
15 // Boost Headers
16 //
17 // FISTA Headers
18 //
19 // Project Specific Headers
20 #include "../../Generic/debug.hpp"
21 #include "../../Generic/generics.hpp"
22 #include "../solver.hpp"
23 #include "../screeningsolver.hpp"
24 
25 namespace hdim {
26 
27 template < typename T, typename Base = internal::Solver<T> >
28 class LazyCoordinateDescent : public Base {
29 
30  public:
31  LazyCoordinateDescent( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
32  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
33  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0 );
35 
36  protected:
37  Eigen::Matrix< T, Eigen::Dynamic, 1 > update_rule(
38  const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
39  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
40  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0,
41  T lambda );
42 
43  private:
44  std::vector<T> inverse_norms;
45 
46 };
47 
48 template < typename T, typename Base >
50  const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &X,
51  const Eigen::Matrix<T, Eigen::Dynamic, 1> &Y,
52  const Eigen::Matrix<T, Eigen::Dynamic, 1> &Beta_0 ) {
53 
54  (void)Y;
55 
56  inverse_norms.reserve( Beta_0.size() );
57 
58  for( int i = 0; i < Beta_0.size() ; i++ ) {
59 
60  T X_i_norm = X.col( i ).squaredNorm();
61 
62  T inverse_norm = ( X_i_norm == 0 )?( 0.0 ):( static_cast<T>(1)/X_i_norm );
63  inverse_norms.push_back( inverse_norm );
64 
65  }
66 }
67 
68 template < typename T, typename Base >
70 
71 template < typename T, typename Base >
72 Eigen::Matrix< T, Eigen::Dynamic, 1 > LazyCoordinateDescent<T,Base>::update_rule(
73  const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
74  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
75  const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0,
76  T lambda ) {
77 
78  Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta = Beta_0;
79  Eigen::Matrix< T, Eigen::Dynamic, 1 > Residual = Y - X*Beta_0;
80 
81 
82  for( int i = 0; i < Beta.size() ; i++ ) {
83 
84  Eigen::Matrix< T, Eigen::Dynamic, 1 > X_i = X.col( i );
85 // T inverse_norm = static_cast<T>(1)/X_i.squaredNorm();
86  T inverse_norm = inverse_norms[i];
87 
88  if( Beta( i ) != static_cast<T>(0) ) {
89  Residual = Residual + X_i*Beta( i );
90  }
91 
92 
93  T threshold = lambda / ( static_cast<T>(2) ) * inverse_norm;
94  T elem = inverse_norm*X_i.transpose()*Residual;
95 
96  Beta( i ) = soft_threshold<T>( elem, threshold );
97 
98  if( Beta( i ) != static_cast<T>(0) ) {
99  Residual = Residual - X_i*Beta( i );
100  }
101 
102  }
103 
104  DEBUG_PRINT( "Norm Squared of updated Beta: " << Beta.squaredNorm() );
105 
106  return Beta;
107 }
108 
109 }
110 
111 #endif // COORDINATE_DESCENT_H
Definition: fos.hpp:18
#define DEBUG_PRINT(x,...)
Definition: debug.hpp:73