1 #ifndef COORDINATEDESCENTWITHSCREEN_HPP 2 #define COORDINATEDESCENTWITHSCREEN_HPP 12 #include <type_traits> 15 #include <eigen3/Eigen/Dense> 21 #include "../../Generic/debug.hpp" 22 #include "../../Generic/generics.hpp" 23 #include "../../Screening/screening_rules.hpp" 24 #include "../solver.hpp" 28 template <
typename T >
33 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
34 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0 );
37 Eigen::Matrix< T, Eigen::Dynamic, 1 >
operator()(
const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
38 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
39 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0,
41 const T duality_gap_target );
43 Eigen::Matrix< T, Eigen::Dynamic, 1 >
operator()(
44 const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
45 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
46 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0,
48 const unsigned int num_iterations );
51 std::vector<T> inverse_norms;
55 template <
typename T >
57 const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &X,
58 const Eigen::Matrix<T, Eigen::Dynamic, 1> &Y,
59 const Eigen::Matrix<T, Eigen::Dynamic, 1> &Beta_0 ) {
63 inverse_norms.reserve( Beta_0.size() );
65 for(
int i = 0; i < Beta_0.size() ; i++ ) {
67 T X_i_norm = X.col( i ).squaredNorm();
69 T inverse_norm = ( X_i_norm == 0 )?( 0.0 ):(
static_cast<T
>(1)/X_i_norm );
70 inverse_norms.push_back( inverse_norm );
75 template <
typename T >
78 template <
typename T >
80 const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
81 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
82 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0,
84 const unsigned int num_iterations ) {
86 const T lambda_half = lambda / 2.0;
88 Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta = Beta_0;
89 Eigen::Matrix< T, Eigen::Dynamic, 1 > Residual = Y - X*Beta_0;
91 Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > X_A = X;
92 Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta_A = Beta;
95 std::vector< unsigned int > active_set, inactive_set;
98 std::vector< unsigned int > universe ( X.cols() );
99 std::iota ( std::begin(universe), std::end(universe) , 0 );
101 T duality_gap_2 =
static_cast<T
>( 0 );
103 for(
unsigned int j = 0; j < num_iterations ; j ++ ) {
105 Eigen::Matrix< T, Eigen::Dynamic, 1 > nu = DualPoint( X_A, Y, Beta_A, lambda_half );
106 duality_gap_2 = DualityGap2( X_A, Y, Beta_A, nu, lambda_half );
110 T radius = std::sqrt( 2.0 * duality_gap_2 /
square( lambda ) );
111 active_set = SafeActiveSet( X, nu, radius );
113 X_A = slice( X, active_set );
114 Beta_A = slice( Beta, active_set );
116 std::set_difference( universe.begin(),
120 std::inserter(inactive_set, inactive_set.begin()) );
123 for(
const auto& active_index : active_set ) {
125 Eigen::Matrix< T, Eigen::Dynamic, 1 > X_j = X.col( active_index );
127 if( Beta( active_index ) != static_cast<T>(0) ) {
128 Residual = Residual + X_j*Beta( active_index );
131 T inverse_norm_j = inverse_norms[ active_index ];
133 T threshold = lambda_half * inverse_norm_j;
134 T elem = inverse_norm_j*X_j.transpose()*Residual;
136 Beta( active_index ) = soft_threshold<T>( elem, threshold );
138 if( Beta( active_index ) !=
static_cast<T
>(0) ) {
139 Residual = Residual - X_j*Beta( active_index );
144 for(
const auto& inactive_index : inactive_set ) {
145 Beta( inactive_index ) = 0.0;
148 DEBUG_PRINT(
"Norm Squared of updated Beta: " << Beta.squaredNorm() );
155 template <
typename T >
157 const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& X,
158 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Y,
159 const Eigen::Matrix< T, Eigen::Dynamic, 1 >& Beta_0,
161 const T duality_gap_target ) {
163 const T lambda_half = lambda / 2.0;
164 const T dgt_half = duality_gap_target / 2.0;
166 Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta = Beta_0;
167 Eigen::Matrix< T, Eigen::Dynamic, 1 > Residual = Y - X*Beta_0;
169 Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > X_A = X;
170 Eigen::Matrix< T, Eigen::Dynamic, 1 > Beta_A = Beta;
173 std::vector< unsigned int > active_set, inactive_set;
176 std::vector< unsigned int > universe ( X.cols() );
177 std::iota ( std::begin(universe), std::end(universe) , 0 );
179 T duality_gap_2 =
static_cast<T
>( 0 );
181 unsigned int counter = 0;
185 Eigen::Matrix< T, Eigen::Dynamic, 1 > nu = DualPoint( X_A, Y, Beta_A, lambda_half );
186 duality_gap_2 = DualityGap2( X_A, Y, Beta_A, nu, lambda_half );
188 if( counter % 10 == 0 ) {
190 T radius = std::sqrt( 2.0 * duality_gap_2 /
square( lambda ) );
191 active_set = SafeActiveSet( X, nu, radius );
193 X_A = slice( X, active_set );
194 Beta_A = slice( Beta, active_set );
196 std::set_difference( universe.begin(),
200 std::inserter(inactive_set, inactive_set.begin()) );
203 for(
const auto& active_index : active_set ) {
205 Eigen::Matrix< T, Eigen::Dynamic, 1 > X_j = X.col( active_index );
207 if( Beta( active_index ) != static_cast<T>(0) ) {
208 Residual = Residual + X_j*Beta( active_index );
211 T inverse_norm_j = inverse_norms[ active_index ];
213 T threshold = lambda_half * inverse_norm_j;
214 T elem = inverse_norm_j*X_j.transpose()*Residual;
216 Beta( active_index ) = soft_threshold<T>( elem, threshold );
218 if( Beta( active_index ) !=
static_cast<T
>(0) ) {
219 Residual = Residual - X_j*Beta( active_index );
224 for(
const auto& inactive_index : inactive_set ) {
225 Beta( inactive_index ) = 0.0;
228 DEBUG_PRINT(
"Current Duality Gap: " << duality_gap_2 <<
" Current Target: " << dgt_half );
229 DEBUG_PRINT(
"Norm Squared of updated Beta: " << Beta.squaredNorm() );
233 }
while ( duality_gap_2 > dgt_half );
240 #endif // COORDINATEDESCENTWITHSCREEN_HPP
Eigen::Matrix< T, Eigen::Dynamic, 1 > operator()(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &X, const Eigen::Matrix< T, Eigen::Dynamic, 1 > &Y, const Eigen::Matrix< T, Eigen::Dynamic, 1 > &Beta_0, const T lambda, const T duality_gap_target)
Run the Sub-Gradient Descent algorithm until the duality gap is below the threshold specified by dual...
Abstract base class for solvers that do not make use of GAP SAFE screening rules. ...
#define DEBUG_PRINT(x,...)
T square(T &val)
Compute the square of a value.