123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- #include "ceres/loss_function.h"
- #include <cstddef>
- #include "glog/logging.h"
- #include "gtest/gtest.h"
- namespace ceres {
- namespace internal {
- namespace {
- void AssertLossFunctionIsValid(const LossFunction& loss, double s) {
- CHECK_GT(s, 0);
-
- double rho[3];
- loss.Evaluate(s, rho);
-
-
- const double kH = 1e-4;
-
- double fwd[3];
-
- double bwd[3];
- loss.Evaluate(s + kH, fwd);
- loss.Evaluate(s - kH, bwd);
-
- const double fd_1 = (fwd[0] - bwd[0]) / (2 * kH);
- ASSERT_NEAR(fd_1, rho[1], 1e-6);
-
- const double fd_2 = (fwd[0] - 2 * rho[0] + bwd[0]) / (kH * kH);
- ASSERT_NEAR(fd_2, rho[2], 1e-6);
- }
- }
- TEST(LossFunction, TrivialLoss) {
- AssertLossFunctionIsValid(TrivialLoss(), 0.357);
- AssertLossFunctionIsValid(TrivialLoss(), 1.792);
-
- double rho[3];
- TrivialLoss().Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
- ASSERT_NEAR(rho[1], 1.0, 1e-6);
- ASSERT_NEAR(rho[2], 0.0, 1e-6);
- }
- TEST(LossFunction, HuberLoss) {
- AssertLossFunctionIsValid(HuberLoss(0.7), 0.357);
- AssertLossFunctionIsValid(HuberLoss(0.7), 1.792);
- AssertLossFunctionIsValid(HuberLoss(1.3), 0.357);
- AssertLossFunctionIsValid(HuberLoss(1.3), 1.792);
-
- double rho[3];
- HuberLoss(0.7).Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
- ASSERT_NEAR(rho[1], 1.0, 1e-6);
- ASSERT_NEAR(rho[2], 0.0, 1e-6);
- }
- TEST(LossFunction, SoftLOneLoss) {
- AssertLossFunctionIsValid(SoftLOneLoss(0.7), 0.357);
- AssertLossFunctionIsValid(SoftLOneLoss(0.7), 1.792);
- AssertLossFunctionIsValid(SoftLOneLoss(1.3), 0.357);
- AssertLossFunctionIsValid(SoftLOneLoss(1.3), 1.792);
-
- double rho[3];
- SoftLOneLoss(0.7).Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
- ASSERT_NEAR(rho[1], 1.0, 1e-6);
- ASSERT_NEAR(rho[2], -0.5 / (0.7 * 0.7), 1e-6);
- }
- TEST(LossFunction, CauchyLoss) {
- AssertLossFunctionIsValid(CauchyLoss(0.7), 0.357);
- AssertLossFunctionIsValid(CauchyLoss(0.7), 1.792);
- AssertLossFunctionIsValid(CauchyLoss(1.3), 0.357);
- AssertLossFunctionIsValid(CauchyLoss(1.3), 1.792);
-
- double rho[3];
- CauchyLoss(0.7).Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
- ASSERT_NEAR(rho[1], 1.0, 1e-6);
- ASSERT_NEAR(rho[2], -1.0 / (0.7 * 0.7), 1e-6);
- }
- TEST(LossFunction, ArctanLoss) {
- AssertLossFunctionIsValid(ArctanLoss(0.7), 0.357);
- AssertLossFunctionIsValid(ArctanLoss(0.7), 1.792);
- AssertLossFunctionIsValid(ArctanLoss(1.3), 0.357);
- AssertLossFunctionIsValid(ArctanLoss(1.3), 1.792);
-
- double rho[3];
- ArctanLoss(0.7).Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
- ASSERT_NEAR(rho[1], 1.0, 1e-6);
- ASSERT_NEAR(rho[2], 0.0, 1e-6);
- }
- TEST(LossFunction, TolerantLoss) {
- AssertLossFunctionIsValid(TolerantLoss(0.7, 0.4), 0.357);
- AssertLossFunctionIsValid(TolerantLoss(0.7, 0.4), 1.792);
- AssertLossFunctionIsValid(TolerantLoss(0.7, 0.4), 55.5);
- AssertLossFunctionIsValid(TolerantLoss(1.3, 0.1), 0.357);
- AssertLossFunctionIsValid(TolerantLoss(1.3, 0.1), 1.792);
- AssertLossFunctionIsValid(TolerantLoss(1.3, 0.1), 55.5);
-
- double rho[3];
- TolerantLoss(0.7, 0.4).Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
-
-
- AssertLossFunctionIsValid(TolerantLoss(20.0, 1.0), 20.0 + 36.6);
- AssertLossFunctionIsValid(TolerantLoss(20.0, 1.0), 20.0 + 36.7);
- AssertLossFunctionIsValid(TolerantLoss(20.0, 1.0), 20.0 + 36.8);
- AssertLossFunctionIsValid(TolerantLoss(20.0, 1.0), 20.0 + 1000.0);
- }
- TEST(LossFunction, TukeyLoss) {
- AssertLossFunctionIsValid(TukeyLoss(0.7), 0.357);
- AssertLossFunctionIsValid(TukeyLoss(0.7), 1.792);
- AssertLossFunctionIsValid(TukeyLoss(1.3), 0.357);
- AssertLossFunctionIsValid(TukeyLoss(1.3), 1.792);
-
- double rho[3];
- TukeyLoss(0.7).Evaluate(0.0, rho);
- ASSERT_NEAR(rho[0], 0.0, 1e-6);
- ASSERT_NEAR(rho[1], 1.0, 1e-6);
- ASSERT_NEAR(rho[2], -2.0 / (0.7 * 0.7), 1e-6);
- }
- TEST(LossFunction, ComposedLoss) {
- {
- HuberLoss f(0.7);
- CauchyLoss g(1.3);
- ComposedLoss c(&f, DO_NOT_TAKE_OWNERSHIP, &g, DO_NOT_TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(c, 0.357);
- AssertLossFunctionIsValid(c, 1.792);
- }
- {
- CauchyLoss f(0.7);
- HuberLoss g(1.3);
- ComposedLoss c(&f, DO_NOT_TAKE_OWNERSHIP, &g, DO_NOT_TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(c, 0.357);
- AssertLossFunctionIsValid(c, 1.792);
- }
- }
- TEST(LossFunction, ScaledLoss) {
-
-
-
- {
- ScaledLoss scaled_loss(nullptr, 6, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 0.323);
- }
- {
- ScaledLoss scaled_loss(new TrivialLoss(), 10, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 0.357);
- }
- {
- ScaledLoss scaled_loss(new HuberLoss(0.7), 0.1, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 1.792);
- }
- {
- ScaledLoss scaled_loss(new SoftLOneLoss(1.3), 0.1, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 1.792);
- }
- {
- ScaledLoss scaled_loss(new CauchyLoss(1.3), 10, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 1.792);
- }
- {
- ScaledLoss scaled_loss(new ArctanLoss(1.3), 10, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 1.792);
- }
- {
- ScaledLoss scaled_loss(new TolerantLoss(1.3, 0.1), 10, TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 1.792);
- }
- {
- ScaledLoss scaled_loss(new ComposedLoss(new HuberLoss(0.8),
- TAKE_OWNERSHIP,
- new TolerantLoss(1.3, 0.5),
- TAKE_OWNERSHIP),
- 10,
- TAKE_OWNERSHIP);
- AssertLossFunctionIsValid(scaled_loss, 1.792);
- }
- }
- TEST(LossFunction, LossFunctionWrapper) {
-
- HuberLoss loss_function1(1.0);
- LossFunctionWrapper loss_function_wrapper(new HuberLoss(1.0), TAKE_OWNERSHIP);
- double s = 0.862;
- double rho_gold[3];
- double rho[3];
- loss_function1.Evaluate(s, rho_gold);
- loss_function_wrapper.Evaluate(s, rho);
- for (int i = 0; i < 3; ++i) {
- EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
- }
-
- HuberLoss loss_function2(0.5);
- loss_function_wrapper.Reset(new HuberLoss(0.5), TAKE_OWNERSHIP);
- loss_function_wrapper.Evaluate(s, rho);
- loss_function2.Evaluate(s, rho_gold);
- for (int i = 0; i < 3; ++i) {
- EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
- }
-
- HuberLoss loss_function3(0.3);
- loss_function_wrapper.Reset(&loss_function3, DO_NOT_TAKE_OWNERSHIP);
- loss_function_wrapper.Evaluate(s, rho);
- loss_function3.Evaluate(s, rho_gold);
- for (int i = 0; i < 3; ++i) {
- EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
- }
-
- TrivialLoss loss_function4;
- loss_function_wrapper.Reset(nullptr, TAKE_OWNERSHIP);
- loss_function_wrapper.Evaluate(s, rho);
- loss_function4.Evaluate(s, rho_gold);
- for (int i = 0; i < 3; ++i) {
- EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
- }
-
- loss_function_wrapper.Reset(nullptr, DO_NOT_TAKE_OWNERSHIP);
- loss_function_wrapper.Evaluate(s, rho);
- loss_function4.Evaluate(s, rho_gold);
- for (int i = 0; i < 3; ++i) {
- EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
- }
- }
- }
- }
|