54 const std::string& cd_type,
55 std::optional<int> random_seed = std::nullopt)
57 , update_clusters(update_clusters)
58 , cd_iterations(cd_iterations)
60 , rng(random_seed.has_value() ? std::mt19937(*random_seed)
61 : std::mt19937(std::random_device{}()))
66 void run(Eigen::VectorXd& beta0,
67 Eigen::VectorXd& beta,
69 const Eigen::ArrayXd& lambda,
70 const std::unique_ptr<Loss>& loss,
72 const Eigen::VectorXd& gradient,
73 const std::vector<int>& working_set,
74 const Eigen::MatrixXd& x,
75 const Eigen::VectorXd& x_centers,
76 const Eigen::VectorXd& x_scales,
77 const Eigen::MatrixXd& y)
override;
80 void run(Eigen::VectorXd& beta0,
81 Eigen::VectorXd& beta,
83 const Eigen::ArrayXd& lambda,
84 const std::unique_ptr<Loss>& loss,
86 const Eigen::VectorXd& gradient,
87 const std::vector<int>& working_set,
88 const Eigen::SparseMatrix<double>& x,
89 const Eigen::VectorXd& x_centers,
90 const Eigen::VectorXd& x_scales,
91 const Eigen::MatrixXd& y)
override;
94 void run(Eigen::VectorXd& beta0,
95 Eigen::VectorXd& beta,
97 const Eigen::ArrayXd& lambda,
98 const std::unique_ptr<Loss>& loss,
100 const Eigen::VectorXd& gradient,
101 const std::vector<int>& working_set,
102 const Eigen::Map<Eigen::MatrixXd>& x,
103 const Eigen::VectorXd& x_centers,
104 const Eigen::VectorXd& x_scales,
105 const Eigen::MatrixXd& y)
override;
108 void run(Eigen::VectorXd& beta0,
109 Eigen::VectorXd& beta,
110 Eigen::MatrixXd& eta,
111 const Eigen::ArrayXd& lambda,
112 const std::unique_ptr<Loss>& loss,
114 const Eigen::VectorXd& gradient,
115 const std::vector<int>& working_set,
116 const Eigen::Map<Eigen::SparseMatrix<double>>& x,
117 const Eigen::VectorXd& x_centers,
118 const Eigen::VectorXd& x_scales,
119 const Eigen::MatrixXd& y)
override;
136 template<
typename MatrixType>
137 void runImpl(Eigen::VectorXd& beta0,
138 Eigen::VectorXd& beta,
139 Eigen::MatrixXd& eta,
140 const Eigen::ArrayXd& lambda,
141 const std::unique_ptr<Loss>& loss,
143 const Eigen::VectorXd& gradient_in,
144 const std::vector<int>& working_set,
146 const Eigen::VectorXd& x_centers,
147 const Eigen::VectorXd& x_scales,
148 const Eigen::MatrixXd& y)
150 using Eigen::MatrixXd;
151 using Eigen::VectorXd;
153 const int n = x.rows();
154 const int m = eta.cols();
159 pgd_solver.run(beta0,
175 MatrixXd w = MatrixXd::Ones(n, m);
178 loss->updateWeightsAndWorkingResponse(w, z, eta, y);
180 MatrixXd residual = eta - z;
181 const VectorXd weight_sums = w.colwise().sum().transpose();
183 Eigen::ArrayXd lambda_cumsum(lambda.size() + 1);
184 lambda_cumsum(0) = 0.0;
185 std::partial_sum(lambda.begin(), lambda.end(), lambda_cumsum.begin() + 1);
187 for (
int it = 0; it < this->cd_iterations; ++it) {
189 computeObjective(penalty, beta, residual, w, lambda, working_set);
193 Eigen::MatrixXd old_residual = residual;
194 Eigen::VectorXd old_beta = beta;
195 Eigen::VectorXd old_beta0 = beta0;
209 this->update_clusters,
214 computeObjective(penalty, beta, residual, w, lambda, working_set);
216 if (!std::isfinite(new_obj) || new_obj > old_obj) {
218 clusters = old_clusters;
219 residual = old_residual;
233 double computeObjective(
const SortedL1Norm& penalty,
234 const Eigen::VectorXd& beta,
235 const Eigen::MatrixXd& residual,
236 const Eigen::MatrixXd& w,
237 const Eigen::ArrayXd& lambda,
238 const std::vector<int>& working_set)
241 0.5 * (residual.array().square() * w.array()).sum() / residual.rows() +
242 penalty.eval(beta(working_set), lambda.head(working_set.size()));
249 double pgd_learning_rate =
251 double pgd_learning_rate_decr =
254 bool update_clusters =
false;
255 int cd_iterations = 10;
256 std::string cd_type =
259 std::random_device{}()
void run(Eigen::VectorXd &beta0, Eigen::VectorXd &beta, Eigen::MatrixXd &eta, const Eigen::ArrayXd &lambda, const std::unique_ptr< Loss > &loss, const SortedL1Norm &penalty, const Eigen::VectorXd &gradient, const std::vector< int > &working_set, const Eigen::SparseMatrix< double > &x, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const Eigen::MatrixXd &y) override
Pure virtual function defining the solver's optimization routine.
void run(Eigen::VectorXd &beta0, Eigen::VectorXd &beta, Eigen::MatrixXd &eta, const Eigen::ArrayXd &lambda, const std::unique_ptr< Loss > &loss, const SortedL1Norm &penalty, const Eigen::VectorXd &gradient, const std::vector< int > &working_set, const Eigen::MatrixXd &x, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const Eigen::MatrixXd &y) override
Pure virtual function defining the solver's optimization routine.
void run(Eigen::VectorXd &beta0, Eigen::VectorXd &beta, Eigen::MatrixXd &eta, const Eigen::ArrayXd &lambda, const std::unique_ptr< Loss > &loss, const SortedL1Norm &penalty, const Eigen::VectorXd &gradient, const std::vector< int > &working_set, const Eigen::Map< Eigen::SparseMatrix< double > > &x, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const Eigen::MatrixXd &y) override
Pure virtual function defining the solver's optimization routine.
void run(Eigen::VectorXd &beta0, Eigen::VectorXd &beta, Eigen::MatrixXd &eta, const Eigen::ArrayXd &lambda, const std::unique_ptr< Loss > &loss, const SortedL1Norm &penalty, const Eigen::VectorXd &gradient, const std::vector< int > &working_set, const Eigen::Map< Eigen::MatrixXd > &x, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const Eigen::MatrixXd &y) override
Pure virtual function defining the solver's optimization routine.
double coordinateDescent(Eigen::VectorXd &beta0, Eigen::VectorXd &beta, Eigen::MatrixXd &residual, Clusters &clusters, const Eigen::ArrayXd &lambda_cumsum, const T &x, const Eigen::MatrixXd &w, const Eigen::VectorXd &weight_sums, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const bool intercept, const JitNormalization jit_normalization, const bool update_clusters, std::mt19937 &rng, const std::string &cd_type="cyclical")