Turi Create  4.0
utils.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_OPTIMIZATION_UTILS_H_
7 #define TURI_OPTIMIZATION_UTILS_H_
8 
9 
10 
11 #include <ml/optimization/optimization_interface.hpp>
12 #include <core/data/flexible_type/flexible_type.hpp>
13 #include <Eigen/Core>
14 
15 namespace turi {
16 
17 namespace optimization {
18 
19 
20 
21 /**
22  * \ingroup group_optimization
23  * \addtogroup utils Utility Functions
24  * \{
25  */
26 
27 
28 /**
29  *
30  * Basic solver error checking and default option hanlding.
31  *
32  * This function takes in a dictionary of solver options as input. Keys in opts
33  * that are required by the solver and NOT in opts are set to a default value.
34  *
35  * \param[in] model Any model with a first order optimization interface.
36  * \param[in] init_point Starting point for the solver.
37  * \param[in,out] opts Solver options.
38  * \param[in] solver Name of solver
39  *
40 */
41 void set_default_solver_options(const first_order_opt_interface& model, const
42  DenseVector& point, const std::string solver, std::map<std::string,
43  flexible_type>& opts);
44 
45 /**
46  *
47  * Compute residual gradient.
48  *
49  * \param[in] gradient Dense Gradient
50  * \returns Residual to check for termination.
51  *
52  *
53 */
54 double compute_residual(const DenseVector& gradient);
55 
56 /**
57  *
58  * Compute residual gradient.
59  *
60  * \param[in] gradient Dense Gradient
61  * \returns Residual to check for termination.
62  *
63  *
64 */
65 double compute_residual(const SparseVector& gradient);
66 
67 /**
68  *
69  * Check hessian of second_order_optimization_iterface models at a point.
70  *
71  * The function lets you check that model.compute_hessian is accurately
72  * implemented.
73  *
74  * Check uses central difference to hessian. The must be with 1e-3
75  * relative tolerance. The notion of relative tolerance is tricky especially
76  * when gradients are really large or really small.
77  *
78  * \param[in] model Any model with a first order optimization interface.
79  * \param[in] point Point at which to check the gradient.
80  * \param[in] hessian Dense hessian matrix.
81  * \param[in] mbStart Minibatch start index
82  * \param[in] mbSize Minibatch size
83  * \returns bool True if hessian is correct to 1e-3 tolerance.
84  *
85  * \note I can't make the model a const because model.compute_function_value()
86  * need not be const.
87  *
88 */
89 bool check_hessian(second_order_opt_interface& model, const DenseVector& point,
90  const DenseMatrix& hessian);
91 
92 /**
93  *
94  * Check dense gradient of first_order_optimization_iterface models at a point.
95  *
96  * The function lets you check that model.compute_gradient is accurately
97  * implemented.
98  *
99  * Check uses central difference to compute gradient. The must be with 1e-3
100  * relative tolerance. The notion of relative tolerance is tricky especially
101  * when gradients are really large or really small.
102  *
103  * \param[in] model Any model with a first order optimization interface.
104  * \param[in] point Point at which to check the gradient.
105  * \param[in] grad Sparse Gradient computed analytically at "point"
106  * \param[in] mbStart Minibatch start index
107  * \param[in] mbSize Minibatch size
108  * \returns bool True if gradient is correct to 1e-3 tolerance.
109  *
110  * \note I can't make the model a const because model.gradient() need not be
111  * const.
112  *
113 */
114 bool check_gradient(first_order_opt_interface& model, const DenseVector& point,
115  SparseVector& gradient, const size_t mbStart = 0, const size_t mbSize
116  = (size_t)(-1));
117 
118 /**
119  *
120  * Check sparse gradient of first_order_optimization_iterface models at
121  * a point.
122  *
123  * The function lets you check that model.compute_gradient is accurately
124  * implemented.
125  *
126  * Check uses central difference to compute gradient. The must be with 1e-3
127  * relative tolerance. The notion of relative tolerance is tricky especially
128  * when gradients are really large or really small.
129  *
130  * \param[in] model Any model with a first order optimization interface.
131  * \param[in] point Point at which to check the gradient.
132  * \param[in] grad Dense gradient computed analytically at "point"
133  * \param[in] mbStart Minibatch start index
134  * \param[in] mbSize Minibatch size
135  * \returns bool True if hessian is correct to 1e-3 tolerance.
136  *
137  *
138 */
139 bool check_gradient(first_order_opt_interface& model, const DenseVector& point,
140  const DenseVector& gradient, const size_t mbStart = 0, const size_t mbSize
141  = (size_t)(-1));
142 
143 
144 /**
145  * Translate solver status to a string that a user can understand.
146  *
147  * \param[in] status Status of the solver
148  * \returns String with a meaningful interpretation of the solver status.
149 */
150 std::string translate_solver_status(const OPTIMIZATION_STATUS& status);
151 
152 /**
153  * Log solver summary stats (useful for benchmarking
154  *
155  * \param[in] status Status of the solver
156  * \returns Clean output of the optimization summary.
157 */
158 void log_solver_summary_stats(const solver_return& stats, bool simple_mode = false);
159 
160 /**
161  * Performs left = left + right across sparse and dense vectors.
162  *
163  * \note Although Eigen is an amazing library. This operation is horribly
164  * inefficient when Left is a dense vector and Right is a sparse vector.
165  *
166  * \param[in,out] left Vector
167  * \param[in] right Rector
168 */
169 template <typename L, typename R>
170 void vector_add(L & left, const R & right);
171 
172 
173 /// \}
174 //
175 } // Optimization
176 
177 } // turicreate
178 
179 #endif
void vector_add(L &left, const R &right)
OPTIMIZATION_STATUS
Optimization status.
double compute_residual(const SparseVector &gradient)
void set_default_solver_options(const first_order_opt_interface &model, const DenseVector &point, const std::string solver, std::map< std::string, flexible_type > &opts)
bool check_hessian(second_order_opt_interface &model, const DenseVector &point, const DenseMatrix &hessian)
bool check_gradient(first_order_opt_interface &model, const DenseVector &point, const DenseVector &gradient, const size_t mbStart=0, const size_t mbSize=(size_t)(-1))
void log_solver_summary_stats(const solver_return &stats, bool simple_mode=false)
std::string translate_solver_status(const OPTIMIZATION_STATUS &status)