17#ifndef __math_gradient_descent_h__
18#define __math_gradient_descent_h__
35 template <
typename ValueType>
36 inline bool operator() (Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& newx,
const Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& x,
37 const Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& g, ValueType step_size) {
39 for (ssize_t n = 0; n < x.size(); ++n) {
40 newx[n] = x[n] - step_size * g[n];
51 template <
class Function,
class UpdateFunctor=LinearUpdate>
72 const Eigen::Matrix<value_type, Eigen::Dynamic, 1>& state ()
const throw () {
return x; }
73 const Eigen::Matrix<value_type, Eigen::Dynamic, 1>& gradient ()
const throw () {
return g; }
76 int function_evaluations ()
const throw () {
return nfeval; }
78 void be_verbose(
bool v) {
verbose = v; }
79 void precondition (
const Eigen::Matrix<value_type, Eigen::Dynamic, 1>& weights) {
83 void run (
const size_t max_iterations = 1000,
85 std::streambuf* log_stream =
nullptr) {
86 std::ostream log_os(log_stream? log_stream :
nullptr);
88 log_os <<
"#iteration" <<
delim <<
"feval" <<
delim <<
"cost" <<
delim <<
"stepsize";
89 for ( ssize_t a = 0 ; a <
x.size() ; a++ )
91 for ( ssize_t a = 0 ; a <
x.size() ; a++ )
93 log_os <<
"\n" << std::flush;
99 DEBUG (
"Gradient descent iteration: init; cost: " +
str(
f));
101 while (
niter < max_iterations) {
102 bool retval = iterate (log_os);
109 if (
normg < gradient_tolerance) {
111 CONSOLE (
"normg (" +
str(
normg) +
") < gradient tolerance (" +
str(gradient_tolerance) +
")");
117 CONSOLE (
"unchanged parameters");
124 std::ostream dummy (
nullptr);
128 void init (std::ostream& log_os) {
134 assert(std::isfinite(
normg));
135 assert(!std::isnan(
normg));
143 assert (std::isfinite (
f));
144 assert (!std::isnan(
f));
145 assert (std::isfinite (
normg));
146 assert (!std::isnan(
normg));
149 for (ssize_t i=0; i<
x.size(); ++i){ log_os <<
delim <<
str(
x(i)); }
150 for (ssize_t i=0; i<
x.size(); ++i){ log_os <<
delim <<
str(
g(i)); }
156 std::ostream dummy (
nullptr);
157 return iterate (dummy);
160 bool iterate (std::ostream& log_os) {
162 assert (std::isfinite (
normg));
165 while (
normg != 0.0) {
181 dt *= quadratic_minimum;
187 for (ssize_t i=0; i<
x.size(); ++i){ log_os <<
delim <<
str(
x(i)); }
188 for (ssize_t i=0; i<
x.size(); ++i){ log_os <<
delim <<
str(
g(i)); }
195 if (quadratic_minimum >= 1.0)
196 quadratic_minimum = 0.5;
197 dt *= quadratic_minimum;
217 Eigen::Matrix<value_type, Eigen::Dynamic, 1>& newg,
221 if (!std::isfinite (cost))
222 throw Exception (
"cost function is NaN or Inf!");
231 assert(std::isfinite(
normg));
235 for (ssize_t n = 0; n <
g.size(); ++n) {
240 assert(std::isfinite(
normg));
Computes the minimum of a function using a gradient descent approach.
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > g
const value_type step_down
UpdateFunctor update_func
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > g2
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > preconditioner_weights
void compute_normg_and_step_unscaled()
value_type evaluate_func(const Eigen::Matrix< value_type, Eigen::Dynamic, 1 > &newx, Eigen::Matrix< value_type, Eigen::Dynamic, 1 > &newg, bool verbose=false)
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > x
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > x2
constexpr T pow2(const T &v)
MR::default_type value_type
std::string str(const T &value, int precision=0)