DiSMEC++
reg_sq_hinge.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021, Aalto University, developed by Erik Schultheis
2 // All rights reserved.
3 //
4 // SPDX-License-Identifier: MIT
5 
6 #include "reg_sq_hinge.h"
7 
8 #include <utility>
9 #include "utils/hash_vector.h"
11 #include "reg_sq_hinge_detail.h"
12 #include "spdlog/spdlog.h"
13 #include "stats/collection.h"
14 
15 using namespace dismec::objective;
16 using namespace dismec::l2_reg_sq_hinge_detail;
17 
18 namespace {
20  constexpr const stat_id_t STAT_GRAD_SPARSITY{8};
21 }
22 
23 Regularized_SquaredHingeSVC::Regularized_SquaredHingeSVC(std::shared_ptr<const GenericFeatureMatrix> X,
24  std::unique_ptr<Objective> regularizer):
25  LinearClassifierImpBase(std::move(X), std::move(regularizer))
26 {
27 
28  if(!features().isCompressed()) {
29  throw std::logic_error("feature matrix is not compressed.");
30  }
31 
32  declare_stat(STAT_GRAD_SPARSITY, {"gradient_sparsity", "% non-zeros"});
33 }
34 
35 void Regularized_SquaredHingeSVC::gradient_imp(const HashVector& location, Eigen::Ref<DenseRealVector> target) {
36  gradient_and_pre_conditioner_tpl(location, target, nullptr);
37 }
38 
40  const HashVector& location, const DenseRealVector& direction, Eigen::Ref<DenseRealVector> output)
41 {
42  margin_error(location);
43  htd_sum(m_MVPos, output, features(), costs(), direction);
44 }
45 
46 void Regularized_SquaredHingeSVC::diag_preconditioner_imp(const HashVector& location, Eigen::Ref<DenseRealVector> target)
47 {
48  gradient_and_pre_conditioner_tpl(location, nullptr, target);
49 }
50 
52  const HashVector& location,
53  Eigen::Ref<DenseRealVector> gradient,
54  Eigen::Ref<DenseRealVector> pre)
55 {
57 }
58 
59 template<class T, class U>
60 void Regularized_SquaredHingeSVC::gradient_and_pre_conditioner_tpl(const HashVector& location, T&& gradient, U&& pre) {
61  // first, we determine whether we want to calculate gradient and/or preconditioning
62  constexpr bool calc_grad = !std::is_same_v<T, std::nullptr_t>;
63  constexpr bool calc_pre = !std::is_same_v<U, std::nullptr_t>;
64 
65  const auto& cost_vec = costs();
66  const auto& label_vec = labels();
67 
68  margin_error(location);
69  record(STAT_GRAD_SPARSITY, static_cast<real_t>(static_cast<double>(100*m_MVPos.size()) / label_vec.size()));
70 
71  const auto& ft = features();
72 
73  long shortlist_size = to_long(m_MVPos.size());
74  for (long i = 0; i < shortlist_size; ++i)
75  {
76  int pos = m_MVPos[i];
77  real_t cost = real_t{2.0} * cost_vec[pos];
78  real_t vi = - cost * static_cast<real_t>(label_vec.coeff(pos)) * m_MVVal[i];
79  for (FastSparseRowIter it(ft, pos); it; ++it)
80  {
81  if constexpr (calc_grad) {
82  gradient.coeffRef(it.col()) += it.value() * vi;
83  }
84  if constexpr (calc_pre) {
85  pre.coeffRef(it.col()) += it.value() * it.value() * cost;
86  }
87  }
88  }
89 }
90 
91 #include <iostream>
92 void Regularized_SquaredHingeSVC::gradient_at_zero_imp(Eigen::Ref<DenseRealVector> target) {
93  const auto& cost_vec = costs();
94  const auto& label_vec = labels();
95 
96  for (int i = 0; i < cost_vec.size(); ++i)
97  {
98  real_t cost = real_t{2} * cost_vec[i];
99  // margin_error = 1
100  real_t vi = -cost * label_vec.coeff(i) ;
101  for (FastSparseRowIter it(features(), i); it; ++it)
102  {
103  target.coeffRef(it.col()) += it.value() * vi;
104  }
105  }
106 }
107 
109  return sparse_features();
110 }
111 
113  // modifying the true labels invalidates margin caches
114  m_Last_MV = {};
115 }
116 
118  if(w.hash() == m_Last_MV) {
119  return;
120  }
121 
122  m_MVPos.clear();
123  m_MVVal.clear();
124  m_Last_MV = w.hash();
125  const auto& lbl = labels();
126  const auto& xTw = x_times_w(w);
127  for(Eigen::Index i = 0; i < lbl.size(); ++i) {
128  real_t label = lbl.coeff(i);
129  real_t d = real_t{1.0} - label * xTw.coeff(i);
130  if (d > 0) {
131  m_MVPos.push_back(i);
132  m_MVVal.push_back(d);
133  }
134  }
135 }
This is an almost verbatim copy of the SparseFeatures::InnerIterator provided by Eigen.
An Eigen vector with versioning information, to implement simple caching of results.
Definition: hash_vector.h:43
VectorHash hash() const
Gets the unique id of this vector.
Definition: hash_vector.cpp:45
const SparseFeatures & sparse_features() const
Definition: linear.cpp:43
const DenseRealVector & costs() const
Definition: linear.cpp:85
const BinaryLabelVector & labels() const
Definition: linear.cpp:89
const DenseRealVector & x_times_w(const HashVector &w)
Calculates the vector of feature matrix times weights w
Definition: linear.cpp:51
Implementation helper for linear classifier derived classes.
Definition: linear.h:124
void gradient(const HashVector &location, Eigen::Ref< DenseRealVector > target)
Evaluate the gradient at location.
Definition: objective.cpp:96
void gradient_imp(const HashVector &location, Eigen::Ref< DenseRealVector > target)
void hessian_times_direction_imp(const HashVector &location, const DenseRealVector &direction, Eigen::Ref< DenseRealVector > target)
void gradient_and_pre_conditioner_tpl(const HashVector &location, T &&gradient, U &&pre)
void diag_preconditioner_imp(const HashVector &location, Eigen::Ref< DenseRealVector > target)
void gradient_and_pre_conditioner_imp(const HashVector &location, Eigen::Ref< DenseRealVector > gradient, Eigen::Ref< DenseRealVector > pre)
Regularized_SquaredHingeSVC(std::shared_ptr< const GenericFeatureMatrix > X, std::unique_ptr< Objective > regularizer)
void gradient_at_zero_imp(Eigen::Ref< DenseRealVector > target)
void record(stat_id_t stat, T &&value)
Record statistics. This function just forwards all its arguments to the internal StatisticsCollection...
Definition: tracked.h:90
void declare_stat(stat_id_t index, StatisticMetaData meta)
Declares a new statistics. This function just forwards all its arguments to the internal StatisticsCo...
Definition: tracked.cpp:16
constexpr const stat_id_t STAT_GRAD_SPARSITY
void htd_sum(const std::vector< int > &indices, Eigen::Ref< DenseRealVector > output, const SparseFeatures &features, const DenseRealVector &costs, const DenseRealVector &direction)
opaque_int_type< detail::stat_id_tag > stat_id_t
An opaque int-like type that is used to identify a statistic in a StatisticsCollection.
Definition: stat_id.h:24
constexpr long to_long(T value)
Convert the given value to long, throwing an error if the conversion is not possible.
Definition: conversion.h:14
types::DenseVector< real_t > DenseRealVector
Any dense, real values vector.
Definition: matrix_types.h:40
float real_t
The default type for floating point values.
Definition: config.h:17