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{}()))
67 Eigen::VectorXd& beta0,
68 Eigen::VectorXd& beta,
70 const Eigen::ArrayXd& lambda,
71 const std::unique_ptr<Loss>& loss,
73 const Eigen::VectorXd& gradient,
74 const std::vector<int>& working_set,
75 const Eigen::MatrixXd& x,
76 const Eigen::VectorXd& x_centers,
77 const Eigen::VectorXd& x_scales,
78 const Eigen::MatrixXd& y,
79 const Eigen::VectorXd& observation_weights = Eigen::VectorXd())
override;
83 Eigen::VectorXd& beta0,
84 Eigen::VectorXd& beta,
86 const Eigen::ArrayXd& lambda,
87 const std::unique_ptr<Loss>& loss,
89 const Eigen::VectorXd& gradient,
90 const std::vector<int>& working_set,
91 const Eigen::SparseMatrix<double>& x,
92 const Eigen::VectorXd& x_centers,
93 const Eigen::VectorXd& x_scales,
94 const Eigen::MatrixXd& y,
95 const Eigen::VectorXd& observation_weights = Eigen::VectorXd())
override;
99 Eigen::VectorXd& beta0,
100 Eigen::VectorXd& beta,
101 Eigen::MatrixXd& eta,
102 const Eigen::ArrayXd& lambda,
103 const std::unique_ptr<Loss>& loss,
105 const Eigen::VectorXd& gradient,
106 const std::vector<int>& working_set,
107 const Eigen::Map<Eigen::MatrixXd>& x,
108 const Eigen::VectorXd& x_centers,
109 const Eigen::VectorXd& x_scales,
110 const Eigen::MatrixXd& y,
111 const Eigen::VectorXd& observation_weights = Eigen::VectorXd())
override;
115 Eigen::VectorXd& beta0,
116 Eigen::VectorXd& beta,
117 Eigen::MatrixXd& eta,
118 const Eigen::ArrayXd& lambda,
119 const std::unique_ptr<Loss>& loss,
121 const Eigen::VectorXd& gradient,
122 const std::vector<int>& working_set,
123 const Eigen::Map<Eigen::SparseMatrix<double>>& x,
124 const Eigen::VectorXd& x_centers,
125 const Eigen::VectorXd& x_scales,
126 const Eigen::MatrixXd& y,
127 const Eigen::VectorXd& observation_weights = Eigen::VectorXd())
override;
144 template<
typename MatrixType>
145 void runImpl(Eigen::VectorXd& beta0,
146 Eigen::VectorXd& beta,
147 Eigen::MatrixXd& eta,
148 const Eigen::ArrayXd& lambda,
149 const std::unique_ptr<Loss>& loss,
151 const Eigen::VectorXd& gradient_in,
152 const std::vector<int>& working_set,
154 const Eigen::VectorXd& x_centers,
155 const Eigen::VectorXd& x_scales,
156 const Eigen::MatrixXd& y,
157 const Eigen::VectorXd& observation_weights)
159 using Eigen::MatrixXd;
160 using Eigen::VectorXd;
162 const int n = x.rows();
163 const int m = eta.cols();
164 const VectorXd weights =
165 detail::normalizeObservationWeights(observation_weights, n);
170 pgd_solver.run(beta0,
187 MatrixXd w = MatrixXd::Ones(n, m);
190 loss->updateWeightsAndWorkingResponse(w, z, eta, y, weights);
192 MatrixXd residual = eta - z;
193 detail::maskZeroWeightRows(residual, weights);
194 const VectorXd weight_sums = w.colwise().sum().transpose();
196 Eigen::ArrayXd lambda_cumsum(lambda.size() + 1);
197 lambda_cumsum(0) = 0.0;
198 std::partial_sum(lambda.begin(), lambda.end(), lambda_cumsum.begin() + 1);
200 for (
int it = 0; it < this->cd_iterations; ++it) {
202 computeObjective(penalty, beta, residual, w, lambda, working_set);
206 Eigen::MatrixXd old_residual = residual;
207 Eigen::VectorXd old_beta = beta;
208 Eigen::VectorXd old_beta0 = beta0;
222 this->update_clusters,
226 detail::maskZeroWeightRows(residual, weights);
229 computeObjective(penalty, beta, residual, w, lambda, working_set);
231 if (!std::isfinite(new_obj) || new_obj > old_obj) {
233 clusters = old_clusters;
234 residual = old_residual;
248 double computeObjective(
const SortedL1Norm& penalty,
249 const Eigen::VectorXd& beta,
250 const Eigen::MatrixXd& residual,
251 const Eigen::MatrixXd& w,
252 const Eigen::ArrayXd& lambda,
253 const std::vector<int>& working_set)
256 0.5 * (residual.array().square() * w.array()).sum() / residual.rows() +
257 penalty.eval(beta(working_set), lambda.head(working_set.size()));
264 double pgd_learning_rate =
266 double pgd_learning_rate_decr =
269 bool update_clusters =
false;
270 int cd_iterations = 10;
271 std::string cd_type =
274 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, const Eigen::VectorXd &observation_weights=Eigen::VectorXd()) 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, const Eigen::VectorXd &observation_weights=Eigen::VectorXd()) 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, const Eigen::VectorXd &observation_weights=Eigen::VectorXd()) 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, const Eigen::VectorXd &observation_weights=Eigen::VectorXd()) 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")