Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions for individual covariance functions. #29

Merged
merged 2 commits into from
Jul 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions albatross/covariance_functions/distance_metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

namespace albatross {

constexpr double EPSILON = 1e-16;

class DistanceMetric : public ParameterHandlingMixin {
public:
DistanceMetric(){};
Expand Down Expand Up @@ -45,17 +47,38 @@ class EuclideanDistance : public DistanceMetric {
}
};

template <typename _Scalar, int _Rows>
double radial_distance(const Eigen::Matrix<_Scalar, _Rows, 1> &x,
const Eigen::Matrix<_Scalar, _Rows, 1> &y) {
return fabs(x.norm() - y.norm());
}

class RadialDistance : public DistanceMetric {
public:
~RadialDistance(){};

std::string get_name() const override { return "radial_distance"; };

double operator()(const Eigen::VectorXd &x, const Eigen::VectorXd &y) const {
return fabs(x.norm() - y.norm());
return radial_distance(x, y);
}
};

template <typename _Scalar, int _Rows>
double angular_distance(const Eigen::Matrix<_Scalar, _Rows, 1> &x,
const Eigen::Matrix<_Scalar, _Rows, 1> &y) {
// The acos operator doesn't behave well near |1|. acos(1.), for example,
// returns NaN, so here we do some special casing,
double dot_product = x.dot(y) / (x.norm() * y.norm());
if (dot_product > 1. - EPSILON) {
return 0.;
} else if (dot_product < -1. + EPSILON) {
return M_PI;
} else {
return acos(dot_product);
}
}

class AngularDistance : public DistanceMetric {
public:
~AngularDistance(){};
Expand All @@ -65,16 +88,7 @@ class AngularDistance : public DistanceMetric {
template <typename _Scalar, int _Rows>
double operator()(const Eigen::Matrix<_Scalar, _Rows, 1> &x,
const Eigen::Matrix<_Scalar, _Rows, 1> &y) const {
// The acos operator doesn't behave well near |1|. acos(1.), for example,
// returns NaN, so here we do some special casing,
double dot_product = x.dot(y) / (x.norm() * y.norm());
if (dot_product > 1. - 1e-16) {
return 0.;
} else if (dot_product < -1. + 1e-16) {
return M_PI;
} else {
return acos(dot_product);
}
return angular_distance(x, y);
}
};

Expand Down
17 changes: 13 additions & 4 deletions albatross/covariance_functions/radial.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ class RadialCovariance : public CovarianceTerm {
DistanceMetricImpl distance_metric_;
};

inline double squared_exponential_covariance(double distance,
double length_scale,
double sigma = 1.) {
return sigma * sigma * exp(-pow(distance / length_scale, 2));
}

/*
* SquaredExponential distance
* - c(d) = -exp((d/length_scale)^2)
Expand Down Expand Up @@ -87,12 +93,16 @@ class SquaredExponential : public RadialCovariance<DistanceMetricImpl> {
double operator()(const X &x, const X &y) const {
double distance = this->distance_metric_(x, y);
double length_scale = this->params_.at("squared_exponential_length_scale");
distance /= length_scale;
double sigma = this->params_.at("sigma_squared_exponential");
return sigma * sigma * exp(-distance * distance);
return squared_exponential_covariance(distance, length_scale, sigma);
}
};

inline double exponential_covariance(double distance, double length_scale,
double sigma = 1.) {
return sigma * sigma * exp(-fabs(distance / length_scale));
}

/*
* Exponential distance
* - c(d) = -exp(|d|/length_scale)
Expand Down Expand Up @@ -121,9 +131,8 @@ class Exponential : public RadialCovariance<DistanceMetricImpl> {
double operator()(const X &x, const X &y) const {
double distance = this->distance_metric_(x, y);
double length_scale = this->params_.at("exponential_length_scale");
distance /= length_scale;
double sigma = this->params_.at("sigma_exponential");
return sigma * sigma * exp(-fabs(distance));
return exponential_covariance(distance, length_scale, sigma);
}
};

Expand Down
2 changes: 0 additions & 2 deletions albatross/models/gp.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ class GaussianProcessRegression
covariance_function_, features, this->model_fit_.train_features);
// Then we can use the information vector to determine the posterior
const Eigen::VectorXd pred = cross_cov * this->model_fit_.information;
// TODO: right now this is recomputing the LDLT, so is highly inefficient,
// Ideally this would get stored inside GaussianProcessFit.
Eigen::MatrixXd pred_cov =
symmetric_covariance(covariance_function_, features);
auto ldlt = this->model_fit_.train_ldlt;
Expand Down