9#include "../clusters.h"
41std::pair<double, double>
44 const Eigen::VectorXd& w,
45 const Eigen::VectorXd& residual,
46 const Eigen::VectorXd& x_centers,
47 const Eigen::VectorXd& x_scales,
52 double gradient = 0.0;
55 switch (jit_normalization) {
58 (x.col(k).cwiseProduct(w).dot(residual) -
59 w.dot(residual) * x_centers(k)) /
62 (x.col(k).cwiseAbs2().dot(w) - 2 * x_centers(k) * x.col(k).dot(w) +
63 std::pow(x_centers(k), 2) * w.sum()) /
64 (std::pow(x_scales(k), 2) * n);
69 (x.col(k).cwiseProduct(w).dot(residual) -
70 w.dot(residual) * x_centers(k)) /
73 (x.col(k).cwiseAbs2().dot(w) - 2 * x_centers(k) * x.col(k).dot(w) +
74 std::pow(x_centers(k), 2) * w.sum()) /
80 s * (x.col(k).cwiseProduct(w).dot(residual)) / (n * x_scales(k));
81 hessian = x.col(k).cwiseAbs2().dot(w) / (std::pow(x_scales(k), 2) * n);
85 gradient = s * (x.col(k).cwiseProduct(w).dot(residual)) / n;
86 hessian = x.col(k).cwiseAbs2().dot(w) / n;
90 return { gradient, hessian };
116std::pair<double, double>
119 const std::vector<int>& s,
120 const Clusters& clusters,
121 const Eigen::VectorXd& w,
122 const Eigen::VectorXd& residual,
123 const Eigen::VectorXd& x_centers,
124 const Eigen::VectorXd& x_scales,
149std::pair<double, double>
152 const std::vector<int>& s,
153 const Clusters& clusters,
154 const Eigen::VectorXd& w,
155 const Eigen::VectorXd& residual,
156 const Eigen::VectorXd& x_centers,
157 const Eigen::VectorXd& x_scales,
189 Eigen::VectorXd& beta,
190 Eigen::VectorXd& residual,
192 const Eigen::ArrayXd& lambda,
194 const Eigen::VectorXd& w,
195 const Eigen::VectorXd& x_centers,
196 const Eigen::VectorXd& x_scales,
197 const bool intercept,
199 const bool update_clusters)
201 using namespace Eigen;
203 const int n = x.rows();
205 double max_abs_gradient = 0;
207 for (
int j = 0; j < clusters.
n_clusters(); ++j) {
208 double c_old = clusters.
coeff(j);
218 s.reserve(cluster_size);
220 for (
auto c_it = clusters.
cbegin(j); c_it != clusters.
cend(j); ++c_it) {
221 double s_k =
sign(beta(*c_it));
225 double hessian_j = 1;
226 double gradient_j = 0;
229 if (cluster_size == 1) {
230 int k = *clusters.
cbegin(j);
232 x, k, w, residual, x_centers, x_scales, s[0], jit_normalization, n);
235 x, j, s, clusters, w, residual, x_centers, x_scales, jit_normalization);
238 max_abs_gradient = std::max(max_abs_gradient, std::abs(gradient_j));
243 if (lambda(0) == 0) {
245 c_tilde = c_old - gradient_j / hessian_j;
249 c_old - gradient_j / hessian_j, j, lambda / hessian_j, clusters);
252 double c_diff = c_old - c_tilde;
255 auto s_it = s.cbegin();
256 auto c_it = clusters.
cbegin(j);
257 for (; c_it != clusters.
cend(j); ++c_it, ++s_it) {
262 beta(k) = c_tilde * s_k;
265 switch (jit_normalization) {
267 residual -= x.col(k) * (s_k * c_diff / x_scales(k));
268 residual.array() += x_centers(k) * s_k * c_diff / x_scales(k);
272 residual -= x.col(k) * (s_k * c_diff);
273 residual.array() += x_centers(k) * s_k * c_diff;
277 residual -= x.col(k) * (s_k * c_diff / x_scales(k));
281 residual -= x.col(k) * (s_k * c_diff);
287 if (update_clusters) {
288 clusters.
update(j, new_index, std::abs(c_tilde));
290 clusters.
setCoeff(j, std::abs(c_tilde));
295 double beta0_update = residual.dot(w) / n;
296 residual.array() -= beta0_update;
297 beta0(0) -= beta0_update;
300 return max_abs_gradient;
Representation of the clusters in SLOPE.
void update(const int old_index, const int new_index, const double c_new)
Updates the cluster structure when an index is changed.
double coeff(const int i) const
Returns the coefficient of the cluster with the given index.
int cluster_size(const int i) const
Returns the size of the cluster with the given index.
void setCoeff(const int i, const double x)
Sets the coefficient of the cluster with the given index.
int n_clusters() const
Returns the number of clusters.
std::vector< int >::const_iterator cend(const int i) const
Returns a constant iterator pointing to the end of the cluster with the given index.
std::vector< int >::const_iterator cbegin(const int i) const
Returns a constant iterator pointing to the beginning of the cluster with the given index.
Namespace containing SLOPE regression implementation.
double coordinateDescent(Eigen::VectorXd &beta0, Eigen::VectorXd &beta, Eigen::VectorXd &residual, Clusters &clusters, const Eigen::ArrayXd &lambda, const T &x, const Eigen::VectorXd &w, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const bool intercept, const JitNormalization jit_normalization, const bool update_clusters)
int sign(T val)
Returns the sign of a given value.
std::pair< double, double > computeClusterGradientAndHessian(const Eigen::MatrixXd &x, const int j, const std::vector< int > &s, const Clusters &clusters, const Eigen::VectorXd &w, const Eigen::VectorXd &residual, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const JitNormalization jit_normalization)
JitNormalization
Enums to control predictor standardization behavior.
@ None
No JIT normalization.
std::tuple< double, int > slopeThreshold(const double x, const int j, const Eigen::ArrayXd lambdas, const Clusters &clusters)
std::pair< double, double > computeGradientAndHessian(const T &x, const int k, const Eigen::VectorXd &w, const Eigen::VectorXd &residual, const Eigen::VectorXd &x_centers, const Eigen::VectorXd &x_scales, const double s, const JitNormalization jit_normalization, const int n)
The declaration of the slopeThreshold function.