Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/ceres/include/ceres/gradient_checker.h')
-rw-r--r--extern/ceres/include/ceres/gradient_checker.h239
1 files changed, 83 insertions, 156 deletions
diff --git a/extern/ceres/include/ceres/gradient_checker.h b/extern/ceres/include/ceres/gradient_checker.h
index 28304159b44..6d285daf1d9 100644
--- a/extern/ceres/include/ceres/gradient_checker.h
+++ b/extern/ceres/include/ceres/gradient_checker.h
@@ -27,194 +27,121 @@
// POSSIBILITY OF SUCH DAMAGE.
// Copyright 2007 Google Inc. All Rights Reserved.
//
-// Author: wjr@google.com (William Rucklidge)
-//
-// This file contains a class that exercises a cost function, to make sure
-// that it is computing reasonable derivatives. It compares the Jacobians
-// computed by the cost function with those obtained by finite
-// differences.
+// Authors: wjr@google.com (William Rucklidge),
+// keir@google.com (Keir Mierle),
+// dgossow@google.com (David Gossow)
#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
#define CERES_PUBLIC_GRADIENT_CHECKER_H_
-#include <cstddef>
-#include <algorithm>
#include <vector>
+#include <string>
+#include "ceres/cost_function.h"
+#include "ceres/dynamic_numeric_diff_cost_function.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/fixed_array.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
-#include "ceres/numeric_diff_cost_function.h"
+#include "ceres/local_parameterization.h"
#include "glog/logging.h"
namespace ceres {
-// An object that exercises a cost function, to compare the answers that it
-// gives with derivatives estimated using finite differencing.
+// GradientChecker compares the Jacobians returned by a cost function against
+// derivatives estimated using finite differencing.
//
-// The only likely usage of this is for testing.
+// The condition enforced is that
//
-// How to use: Fill in an array of pointers to parameter blocks for your
-// CostFunction, and then call Probe(). Check that the return value is
-// 'true'. See prober_test.cc for an example.
+// (J_actual(i, j) - J_numeric(i, j))
+// ------------------------------------ < relative_precision
+// max(J_actual(i, j), J_numeric(i, j))
+//
+// where J_actual(i, j) is the jacobian as computed by the supplied cost
+// function (by the user) multiplied by the local parameterization Jacobian
+// and J_numeric is the jacobian as computed by finite differences, multiplied
+// by the local parameterization Jacobian as well.
//
-// This is templated similarly to NumericDiffCostFunction, as it internally
-// uses that.
-template <typename CostFunctionToProbe,
- int M = 0, int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0>
+// How to use: Fill in an array of pointers to parameter blocks for your
+// CostFunction, and then call Probe(). Check that the return value is 'true'.
class GradientChecker {
public:
- // Here we stash some results from the probe, for later
- // inspection.
- struct GradientCheckResults {
- // Computed cost.
- Vector cost;
-
- // The sizes of these matrices are dictated by the cost function's
- // parameter and residual block sizes. Each vector's length will
- // term->parameter_block_sizes().size(), and each matrix is the
- // Jacobian of the residual with respect to the corresponding parameter
- // block.
+ // This will not take ownership of the cost function or local
+ // parameterizations.
+ //
+ // function: The cost function to probe.
+ // local_parameterization: A vector of local parameterizations for each
+ // parameter. May be NULL or contain NULL pointers to indicate that the
+ // respective parameter does not have a local parameterization.
+ // options: Options to use for numerical differentiation.
+ GradientChecker(
+ const CostFunction* function,
+ const std::vector<const LocalParameterization*>* local_parameterizations,
+ const NumericDiffOptions& options);
+
+ // Contains results from a call to Probe for later inspection.
+ struct ProbeResults {
+ // The return value of the cost function.
+ bool return_value;
+
+ // Computed residual vector.
+ Vector residuals;
+
+ // The sizes of the Jacobians below are dictated by the cost function's
+ // parameter block size and residual block sizes. If a parameter block
+ // has a local parameterization associated with it, the size of the "local"
+ // Jacobian will be determined by the local parameterization dimension and
+ // residual block size, otherwise it will be identical to the regular
+ // Jacobian.
// Derivatives as computed by the cost function.
- std::vector<Matrix> term_jacobians;
+ std::vector<Matrix> jacobians;
+
+ // Derivatives as computed by the cost function in local space.
+ std::vector<Matrix> local_jacobians;
- // Derivatives as computed by finite differencing.
- std::vector<Matrix> finite_difference_jacobians;
+ // Derivatives as computed by nuerical differentiation in local space.
+ std::vector<Matrix> numeric_jacobians;
- // Infinity-norm of term_jacobians - finite_difference_jacobians.
- double error_jacobians;
+ // Derivatives as computed by nuerical differentiation in local space.
+ std::vector<Matrix> local_numeric_jacobians;
+
+ // Contains the maximum relative error found in the local Jacobians.
+ double maximum_relative_error;
+
+ // If an error was detected, this will contain a detailed description of
+ // that error.
+ std::string error_log;
};
- // Checks the Jacobian computed by a cost function.
- //
- // probe_point: The parameter values at which to probe.
- // error_tolerance: A threshold for the infinity-norm difference
- // between the Jacobians. If the Jacobians differ by more than
- // this amount, then the probe fails.
+ // Call the cost function, compute alternative Jacobians using finite
+ // differencing and compare results. If local parameterizations are given,
+ // the Jacobians will be multiplied by the local parameterization Jacobians
+ // before performing the check, which effectively means that all errors along
+ // the null space of the local parameterization will be ignored.
+ // Returns false if the Jacobians don't match, the cost function return false,
+ // or if the cost function returns different residual when called with a
+ // Jacobian output argument vs. calling it without. Otherwise returns true.
//
- // term: The cost function to test. Not retained after this call returns.
- //
- // results: On return, the two Jacobians (and other information)
- // will be stored here. May be NULL.
+ // parameters: The parameter values at which to probe.
+ // relative_precision: A threshold for the relative difference between the
+ // Jacobians. If the Jacobians differ by more than this amount, then the
+ // probe fails.
+ // results: On return, the Jacobians (and other information) will be stored
+ // here. May be NULL.
//
// Returns true if no problems are detected and the difference between the
// Jacobians is less than error_tolerance.
- static bool Probe(double const* const* probe_point,
- double error_tolerance,
- CostFunctionToProbe *term,
- GradientCheckResults* results) {
- CHECK_NOTNULL(probe_point);
- CHECK_NOTNULL(term);
- LOG(INFO) << "-------------------- Starting Probe() --------------------";
-
- // We need a GradientCheckeresults, whether or not they supplied one.
- internal::scoped_ptr<GradientCheckResults> owned_results;
- if (results == NULL) {
- owned_results.reset(new GradientCheckResults);
- results = owned_results.get();
- }
-
- // Do a consistency check between the term and the template parameters.
- CHECK_EQ(M, term->num_residuals());
- const int num_residuals = M;
- const std::vector<int32>& block_sizes = term->parameter_block_sizes();
- const int num_blocks = block_sizes.size();
-
- CHECK_LE(num_blocks, 5) << "Unable to test functions that take more "
- << "than 5 parameter blocks";
- if (N0) {
- CHECK_EQ(N0, block_sizes[0]);
- CHECK_GE(num_blocks, 1);
- } else {
- CHECK_LT(num_blocks, 1);
- }
- if (N1) {
- CHECK_EQ(N1, block_sizes[1]);
- CHECK_GE(num_blocks, 2);
- } else {
- CHECK_LT(num_blocks, 2);
- }
- if (N2) {
- CHECK_EQ(N2, block_sizes[2]);
- CHECK_GE(num_blocks, 3);
- } else {
- CHECK_LT(num_blocks, 3);
- }
- if (N3) {
- CHECK_EQ(N3, block_sizes[3]);
- CHECK_GE(num_blocks, 4);
- } else {
- CHECK_LT(num_blocks, 4);
- }
- if (N4) {
- CHECK_EQ(N4, block_sizes[4]);
- CHECK_GE(num_blocks, 5);
- } else {
- CHECK_LT(num_blocks, 5);
- }
-
- results->term_jacobians.clear();
- results->term_jacobians.resize(num_blocks);
- results->finite_difference_jacobians.clear();
- results->finite_difference_jacobians.resize(num_blocks);
-
- internal::FixedArray<double*> term_jacobian_pointers(num_blocks);
- internal::FixedArray<double*>
- finite_difference_jacobian_pointers(num_blocks);
- for (int i = 0; i < num_blocks; i++) {
- results->term_jacobians[i].resize(num_residuals, block_sizes[i]);
- term_jacobian_pointers[i] = results->term_jacobians[i].data();
- results->finite_difference_jacobians[i].resize(
- num_residuals, block_sizes[i]);
- finite_difference_jacobian_pointers[i] =
- results->finite_difference_jacobians[i].data();
- }
- results->cost.resize(num_residuals, 1);
-
- CHECK(term->Evaluate(probe_point, results->cost.data(),
- term_jacobian_pointers.get()));
- NumericDiffCostFunction<CostFunctionToProbe, CENTRAL, M, N0, N1, N2, N3, N4>
- numeric_term(term, DO_NOT_TAKE_OWNERSHIP);
- CHECK(numeric_term.Evaluate(probe_point, results->cost.data(),
- finite_difference_jacobian_pointers.get()));
-
- results->error_jacobians = 0;
- for (int i = 0; i < num_blocks; i++) {
- Matrix jacobian_difference = results->term_jacobians[i] -
- results->finite_difference_jacobians[i];
- results->error_jacobians =
- std::max(results->error_jacobians,
- jacobian_difference.lpNorm<Eigen::Infinity>());
- }
-
- LOG(INFO) << "========== term-computed derivatives ==========";
- for (int i = 0; i < num_blocks; i++) {
- LOG(INFO) << "term_computed block " << i;
- LOG(INFO) << "\n" << results->term_jacobians[i];
- }
-
- LOG(INFO) << "========== finite-difference derivatives ==========";
- for (int i = 0; i < num_blocks; i++) {
- LOG(INFO) << "finite_difference block " << i;
- LOG(INFO) << "\n" << results->finite_difference_jacobians[i];
- }
-
- LOG(INFO) << "========== difference ==========";
- for (int i = 0; i < num_blocks; i++) {
- LOG(INFO) << "difference block " << i;
- LOG(INFO) << (results->term_jacobians[i] -
- results->finite_difference_jacobians[i]);
- }
-
- LOG(INFO) << "||difference|| = " << results->error_jacobians;
-
- return results->error_jacobians < error_tolerance;
- }
+ bool Probe(double const* const* parameters,
+ double relative_precision,
+ ProbeResults* results) const;
private:
CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(GradientChecker);
+
+ std::vector<const LocalParameterization*> local_parameterizations_;
+ const CostFunction* function_;
+ internal::scoped_ptr<CostFunction> finite_diff_cost_function_;
};
} // namespace ceres