Skip to content

Commit b61ea13

Browse files
committed
Add an interpolation model which provides special methods for
computing first and second derivatives of the interpolated mean
1 parent 81b8704 commit b61ea13

File tree

9 files changed

+274
-51
lines changed

9 files changed

+274
-51
lines changed

include/albatross/CovarianceFunctions

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <albatross/src/covariance_functions/traits.hpp>
2525
#include <albatross/src/covariance_functions/callers.hpp>
26+
#include <albatross/src/covariance_functions/derivative.hpp>
2627
#include <albatross/src/covariance_functions/covariance_function.hpp>
2728
#include <albatross/src/covariance_functions/mean_function.hpp>
2829
#include <albatross/src/covariance_functions/call_trace.hpp>

include/albatross/Interpolate

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (C) 2020 Swift Navigation Inc.
3+
* Contact: Swift Navigation <[email protected]>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#ifndef ALBATROSS_INTERPOLATE_H
14+
#define ALBATROSS_INTERPOLATE_H
15+
16+
#include "GP"
17+
#include <albatross/src/models/interpolate.hpp>
18+
19+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (C) 2020 Swift Navigation Inc.
3+
* Contact: Swift Navigation <[email protected]>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#ifndef INCLUDE_ALBATROSS_SRC_COVARIANCE_FUNCTIONS_DERIVATIVE_HPP_
14+
#define INCLUDE_ALBATROSS_SRC_COVARIANCE_FUNCTIONS_DERIVATIVE_HPP_
15+
16+
namespace albatross {
17+
18+
template <typename T> struct Derivative {
19+
20+
Derivative() : value(){};
21+
22+
Derivative(const T &t) : value(t){};
23+
24+
T value;
25+
};
26+
27+
template <typename T> struct SecondDerivative {
28+
29+
SecondDerivative() : value(){};
30+
31+
SecondDerivative(const T &t) : value(t){};
32+
33+
T value;
34+
};
35+
36+
} // namespace albatross
37+
38+
#endif /* INCLUDE_ALBATROSS_SRC_COVARIANCE_FUNCTIONS_DERIVATIVE_HPP_ */

include/albatross/src/covariance_functions/distance_metrics.hpp

+11
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ class EuclideanDistance : public DistanceMetric {
3737
return fabs(x - y);
3838
}
3939

40+
double derivative(const double &x, const double &y) const {
41+
if (x - y == 0.) {
42+
return 1.;
43+
}
44+
return (x - y) / fabs(x - y);
45+
}
46+
47+
double second_derivative(const double &x, const double &y) const {
48+
return 0.;
49+
}
50+
4051
template <typename _Scalar, int _Rows>
4152
double operator()(const Eigen::Matrix<_Scalar, _Rows, 1> &x,
4253
const Eigen::Matrix<_Scalar, _Rows, 1> &y) const {

include/albatross/src/covariance_functions/radial.hpp

+52
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ inline double squared_exponential_covariance(double distance,
2828
return sigma * sigma * exp(-pow(distance / length_scale, 2));
2929
}
3030

31+
inline double squared_exponential_covariance_derivative(double distance,
32+
double length_scale,
33+
double sigma = 1.) {
34+
if (length_scale <= 0.) {
35+
return 0.;
36+
}
37+
return -2 * distance / (length_scale * length_scale) *
38+
squared_exponential_covariance(distance, length_scale, sigma);
39+
}
40+
41+
inline double squared_exponential_covariance_second_derivative(
42+
double distance, double length_scale, double sigma = 1.) {
43+
if (length_scale <= 0.) {
44+
return 0.;
45+
}
46+
const auto ratio = distance / length_scale;
47+
return (4. * ratio * ratio - 2.) / (length_scale * length_scale) *
48+
squared_exponential_covariance(distance, length_scale, sigma);
49+
}
50+
3151
/*
3252
* SquaredExponential distance
3353
* covariance(d) = sigma^2 exp(-(d/length_scale)^2)
@@ -83,6 +103,38 @@ class SquaredExponential
83103
sigma_squared_exponential.value);
84104
}
85105

106+
// This operator is only defined when the distance metric is also defined.
107+
template <typename X,
108+
typename std::enable_if<
109+
has_call_operator<DistanceMetricType, X &, X &>::value,
110+
int>::type = 0>
111+
double _call_impl(const Derivative<X> &x, const X &y) const {
112+
double distance = this->distance_metric_(x.value, y);
113+
double distance_derivative = this->distance_metric_.derivative(x.value, y);
114+
return distance_derivative * squared_exponential_covariance_derivative(
115+
distance,
116+
squared_exponential_length_scale.value,
117+
sigma_squared_exponential.value);
118+
}
119+
120+
// This operator is only defined when the distance metric is also defined.
121+
template <typename X,
122+
typename std::enable_if<
123+
has_call_operator<DistanceMetricType, X &, X &>::value,
124+
int>::type = 0>
125+
double _call_impl(const SecondDerivative<X> &x, const X &y) const {
126+
double d = this->distance_metric_(x.value, y);
127+
double d_1 = this->distance_metric_.derivative(x.value, y);
128+
double d_2 = this->distance_metric_.second_derivative(x.value, y);
129+
double f_1 = squared_exponential_covariance_derivative(
130+
d, squared_exponential_length_scale.value,
131+
sigma_squared_exponential.value);
132+
double f_2 = squared_exponential_covariance_second_derivative(
133+
d, squared_exponential_length_scale.value,
134+
sigma_squared_exponential.value);
135+
return d_2 * f_1 + d_1 * d_1 * f_2;
136+
}
137+
86138
DistanceMetricType distance_metric_;
87139
};
88140

include/albatross/src/models/gp.hpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,11 @@ class GaussianProcessBase : public ModelBase<ImplType> {
350350
return pred;
351351
}
352352

353-
template <
354-
typename FeatureType, typename FitFeaturetype,
355-
typename CovarianceRepresentation,
356-
typename std::enable_if<
357-
has_call_operator<CovFunc, FeatureType, FeatureType>::value &&
358-
has_call_operator<CovFunc, FeatureType, FitFeaturetype>::value,
359-
int>::type = 0>
353+
template <typename FeatureType, typename FitFeaturetype,
354+
typename CovarianceRepresentation,
355+
typename std::enable_if<
356+
has_call_operator<CovFunc, FeatureType, FitFeaturetype>::value,
357+
int>::type = 0>
360358
Eigen::VectorXd _predict_impl(
361359
const std::vector<FeatureType> &features,
362360
const GPFitType<CovarianceRepresentation, FitFeaturetype> &gp_fit,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (C) 2020 Swift Navigation Inc.
3+
* Contact: Swift Navigation <[email protected]>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#ifndef INCLUDE_ALBATROSS_SRC_MODELS_INTERPOLATE_HPP_
14+
#define INCLUDE_ALBATROSS_SRC_MODELS_INTERPOLATE_HPP_
15+
16+
namespace albatross {
17+
18+
auto interpolation_cov_func() {
19+
SquaredExponential<EuclideanDistance> sqr_exp;
20+
IndependentNoise<double> noise;
21+
return sqr_exp + measurement_only(noise);
22+
}
23+
24+
using InterpolationFunction = decltype(interpolation_cov_func());
25+
26+
/*
27+
* Generic Gaussian Process Implementation.
28+
*/
29+
class GaussianProcessInterpolator
30+
: public GaussianProcessBase<InterpolationFunction, ZeroMean,
31+
GaussianProcessInterpolator> {
32+
public:
33+
using Base = GaussianProcessBase<InterpolationFunction, ZeroMean,
34+
GaussianProcessInterpolator>;
35+
};
36+
37+
using GPInterpolatorFitType =
38+
typename fit_type<GaussianProcessInterpolator, double>::type;
39+
40+
template <>
41+
class Prediction<GaussianProcessInterpolator, double, GPInterpolatorFitType> {
42+
43+
public:
44+
Prediction(const GaussianProcessInterpolator &model,
45+
const GPInterpolatorFitType &fit,
46+
const std::vector<double> &features)
47+
: model_(model), fit_(fit), features_(features) {}
48+
49+
Prediction(GaussianProcessInterpolator &&model, GPInterpolatorFitType &&fit,
50+
const std::vector<double> &features)
51+
: model_(std::move(model)), fit_(std::move(fit)), features_(features) {}
52+
53+
// Mean
54+
Eigen::VectorXd mean() const {
55+
return MeanPredictor()._mean(model_, fit_, features_);
56+
}
57+
58+
Eigen::VectorXd derivative() const {
59+
60+
std::vector<Derivative<double>> derivative_features;
61+
for (const auto &f : features_) {
62+
derivative_features.emplace_back(f);
63+
}
64+
65+
return MeanPredictor()._mean(model_, fit_, derivative_features);
66+
}
67+
68+
Eigen::VectorXd second_derivative() const {
69+
70+
std::vector<SecondDerivative<double>> derivative_features;
71+
for (const auto &f : features_) {
72+
derivative_features.emplace_back(f);
73+
}
74+
return MeanPredictor()._mean(model_, fit_, derivative_features);
75+
}
76+
77+
const GaussianProcessInterpolator model_;
78+
const GPInterpolatorFitType fit_;
79+
const std::vector<double> features_;
80+
};
81+
82+
} // namespace albatross
83+
#endif /* INCLUDE_ALBATROSS_SRC_MODELS_INTERPOLATE_HPP_ */

tests/CMakeLists.txt

+1-44
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,5 @@
11
add_executable(albatross_unit_tests
2-
test_apply.cc
3-
test_async_utils.cc
4-
test_block_utils.cc
5-
test_call_trace.cc
6-
test_callers.cc
7-
test_concatenate.cc
8-
test_core_dataset.cc
9-
test_core_distribution.cc
10-
test_core_model.cc
11-
test_covariance_function.cc
12-
test_covariance_functions.cc
13-
test_cross_validation.cc
14-
test_csv_utils.cc
15-
test_distance_metrics.cc
16-
test_eigen_utils.cc
17-
test_evaluate.cc
18-
test_gp.cc
19-
test_group_by.cc
20-
test_indexing.cc
21-
test_linalg_utils.cc
22-
test_map_utils.cc
23-
test_model_adapter.cc
24-
test_model_metrics.cc
25-
test_models.cc
26-
test_parameter_handling_mixin.cc
27-
test_patchwork_gp.cc
28-
test_prediction.cc
29-
test_radial.cc
30-
test_random_utils.cc
31-
test_ransac.cc
32-
test_samplers.cc
33-
test_scaling_function.cc
34-
test_serializable_ldlt.cc
35-
test_serialize.cc
36-
test_sparse_gp.cc
37-
test_stats.cc
38-
test_traits_cereal.cc
39-
test_traits_core.cc
40-
test_traits_details.cc
41-
test_traits_covariance_functions.cc
42-
test_traits_evaluation.cc
43-
test_traits_indexing.cc
44-
test_tune.cc
45-
test_variant_utils.cc
2+
test_interpolate.cc
463
)
474
target_include_directories(albatross_unit_tests SYSTEM PRIVATE
485
"${gtest_SOURCE_DIR}"

tests/test_interpolate.cc

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (C) 2020 Swift Navigation Inc.
3+
* Contact: Swift Navigation <[email protected]>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#include <albatross/Interpolate>
14+
15+
#include <gtest/gtest.h>
16+
17+
namespace albatross {
18+
19+
std::vector<double> uniform_points_on_line(const std::size_t n,
20+
const double low,
21+
const double high) {
22+
std::vector<double> xs;
23+
for (std::size_t i = 0; i < n; i++) {
24+
double ratio = (double)i / (double)(n - 1);
25+
xs.push_back(low + ratio * (high - low));
26+
}
27+
return xs;
28+
};
29+
30+
TEST(test_interpolator, test_interpolate) {
31+
32+
const auto xs = uniform_points_on_line(21, 0., 2 * 3.14159);
33+
34+
Eigen::VectorXd targets(xs.size());
35+
for (std::size_t i = 0; i < xs.size(); ++i) {
36+
targets[i] = std::sin(xs[i]);
37+
}
38+
39+
const auto interp_xs = uniform_points_on_line(101, 0., 2 * 3.14159);
40+
41+
Eigen::VectorXd mean_truth(interp_xs.size());
42+
Eigen::VectorXd derivative_truth(interp_xs.size());
43+
Eigen::VectorXd second_derivative_truth(interp_xs.size());
44+
45+
for (std::size_t i = 0; i < interp_xs.size(); ++i) {
46+
mean_truth[i] = std::sin(interp_xs[i]);
47+
derivative_truth[i] = std::cos(interp_xs[i]);
48+
second_derivative_truth[i] = -std::sin(interp_xs[i]);
49+
}
50+
51+
GaussianProcessInterpolator interpolator;
52+
interpolator.set_param("squared_exponential_length_scale", 10.);
53+
interpolator.set_param("sigma_squared_exponential", 10.);
54+
interpolator.set_param("sigma_independent_noise", 1e-6);
55+
56+
const auto predictor = interpolator.fit(xs, targets).predict(interp_xs);
57+
58+
EXPECT_LT((predictor.mean() - mean_truth).norm(), 1e-3);
59+
EXPECT_LT((predictor.derivative() - derivative_truth).norm(), 1e-2);
60+
EXPECT_LT((predictor.second_derivative() - second_derivative_truth).norm(),
61+
1e-1);
62+
}
63+
64+
} // namespace albatross

0 commit comments

Comments
 (0)