Skip to content

Commit

Permalink
Add setup for documentation using sphinx and readthedocs
Browse files Browse the repository at this point in the history
  • Loading branch information
akleeman committed Jun 12, 2018
1 parent 93bf16f commit 6c7b5cd
Show file tree
Hide file tree
Showing 8 changed files with 450 additions and 90 deletions.
91 changes: 1 addition & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,93 +7,4 @@ A framework for statistical modelling in C++, with a focus on Gaussian processes
* Written using generics in an attempt to make these core routines applicable to a number of fields.
* Parameter handling which makes it easy to get and set parameters in a standardized way as well as compose and (de)serialize models to string.

## Install

`albatross` is a header only library so incorporating it in your C++ project should be as simple as adding `./albatross` as an include directory.

Make sure you've run `git submodule update --recursive --init` to be sure all the third party libraries required by albatross are up to date.

If you want to run the tests you can do so using `cmake`,

```
mkdir build;
cd build;
cmake ../
make run_albatross_unit_tests
```
Similarly you can make/run the examples,
```
make sinc_example
./examples/sinc_example -input ./examples/sinc_input.csv -output ./examples/sinc_predictions.csv
```
and plot the results (though this'll require a numerical python environment),
```
python ../examples/plot_example_predictions.py ./examples/sinc_input.csv ./examples/sinc_predictions.csv
./examples/sinc_example -input ../examples/sinc_input.csv -output ./examples/sinc_predictions.csv -n 10
```

## Examples

As an example we can build a model which estimates a function `f(x)`,
```
f(x) = a x + b + c sin(x) / x
```
by using noisy observations of the function `y = f(x) + N(0, s^2)`. To do so we can build up our model,
```
using Noise = IndependentNoise<double>;
using SqrExp = SquaredExponential<ScalarDistance>;
CovarianceFunction<Constant> mean = {Constant(100.)};
CovarianceFunction<SlopeTerm> slope = {SlopeTerm(100.)};
CovarianceFunction<Noise> noise = {Noise(meas_noise)};
CovarianceFunction<SqrExp> sqrexp = {SqrExp(2., 5.)};
auto linear_model = mean + slope + noise + sqrexp;
```
which incorporates prior knowledge that the function consists of a mean offset, a linear term, measurement noise and an unknown smooth compontent (which we captures using a squared exponential covariance function).

We can inspect the model and its parameters,
```
>> std::cout << linear_model.to_string() << std::endl;
model_name: (((constant+slope_term)+independent_noise)+squared_exponential[scalar_distance])
model_params:
length_scale: 2
sigma_constant: 100
sigma_independent_noise: 1
sigma_slope: 100
sigma_squared_exponential: 5
```
then condition the model on random observations, which we stored in `data`,
```
auto model = gp_from_covariance(linear_model);
model.fit(data);
```
and make some gridded predictions,
```
const int k = 161;
const auto grid_xs = uniform_points_on_line(k, low - 2., high + 2.);
const auto predictions = model.predict(grid_xs);
```
Here are the resulting predictions when we have only two noisy observations,

### 2 Observations
![2](https://github.com/swift-nav/albatross/blob/master/examples/sinc_function_2.png)

not great, but at least it knows it isn't great. As we start to add more observations
we can watch the model slowly get more confident,

### 5 Observations
![5](https://github.com/swift-nav/albatross/blob/master/examples/sinc_function_5.png)
### 10 Observations
![10](https://github.com/swift-nav/albatross/blob/master/examples/sinc_function_10.png)
### 30 Observations
![30](https://github.com/swift-nav/albatross/blob/master/examples/sinc_function_30.png)


## Credit
The `fit`, `predict`, `get_params` functionality was inspired by [scikit-learn](https://github.com/scikit-learn/scikit-learn) and the covariance function composition by [george](https://github.com/dfm/george).

Like this project? Want to get paid to help us apply it to our GNSS models? [Join us](https://www.swiftnav.com/join-us) at [Swift Navigation](https://www.swiftnav.com/)!

![albatross](https://static.fjcdn.com/gifs/Albatross_408ca5_5434150.gif)

For more details [See the full documentation](https://swiftnav-albatross.readthedocs.io/en/latest/)
143 changes: 143 additions & 0 deletions doc/1d-example.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
##########
1D Example
##########

.. _1d-example:

--------------
Introduction
--------------

Regression problems typically involve estimating some unknown function :math:`f` from a set of noisy data :math:`y`. As an example we can attempt to estimate a function :math:`f(x)`,

.. math::
f(x) = a x + b + \mbox{something_nonlinear}(x)
based off of noisy observations,

.. math::
y = f(x) + \mathcal{N}(0, \sigma^2).
For this example we'll use the ``sinc`` function for the non linear portion,

.. math::
f(x) = a x + b + c \frac{\mbox{sin}(x)}{x}
but for illustrative purposes we'll assume we know nothing about the non linear
component other than that we think it's smooth. To capture this with a Gaussian
process we may want to include a systematic offset and linear component and a component
which adds a soft constraint that the function value for neighboring points will be similar.

More specifically we can define our priors on the parameters,

.. math::
a \sim \mathcal{N}(0, \sigma_a^2)
b \sim \mathcal{N}(0, \sigma_b^2)
For the nonlinear portion we'll use a prior which states that two points
:math:`x` and :math:`x'` which are separated by a distance :math:`d = x - x'`
will have a covariance given by,

.. math::
\mbox{sqr_exp}(d) = \sigma_c^2 \mbox{e}^{-\left(\frac{d}{\ell}\right)^2}.
We can then define the covariance function which captures the constant, linear, nonlinear and measurement noise components,

.. math::
\mbox{cov}(x, x') = \sigma_a^2 x x' + \sigma_b^2 + \mbox{sqr_exp}(x - x') + \sigma^2 \mathbf{I}(x = x').
Where the first term captures the covariance between :math:`x` and :math:`x'` from the linear component. The second term captures the covariance from the common offset. The third term is provides the flexibility for non linear functions and the fourth term captures the measurement noise through the use of the indicator function, :math:`\mathbf{I}(\cdot)`, which takes on a value of :math:`1` if the argument is true.

-------------------------------
Implementation in ``albatross``
-------------------------------

Using ``albatross`` this would look like,

.. code-block:: c
using Noise = IndependentNoise<double>;
using SqrExp = SquaredExponential<ScalarDistance>;
CovarianceFunction<Constant> mean = {Constant(100.)};
CovarianceFunction<SlopeTerm> slope = {SlopeTerm(100.)};
CovarianceFunction<Noise> noise = {Noise(meas_noise)};
CovarianceFunction<SqrExp> sqrexp = {SqrExp(2., 5.)};
auto covariance = mean + slope + noise + sqrexp;
which incorporates prior knowledge that the function consists of a mean offset, a linear term, measurement noise and an unknown smooth compontent (which we captures using a squared exponential covariance function).

We can inspect the model and its parameters,

.. code-block:: c
std::cout << covariance.to_string() << std::endl;
Which shows us,

.. code-block:: bash
model_name: (((constant+slope_term)+independent_noise)+squared_exponential[scalar_distance])
model_params:
length_scale: 2
sigma_constant: 100
sigma_independent_noise: 1
sigma_slope: 100
sigma_squared_exponential: 5
then condition the model on random observations, which we stored in ``data``,
.. code-block:: c
auto model = gp_from_covariance(covariance);
model.fit(data);
and make some gridded predictions,
.. code-block:: c
const int k = 161;
const auto grid_xs = uniform_points_on_line(k, low - 2., high + 2.);
const auto predictions = model.predict(grid_xs);
Here are the resulting predictions when we have only two noisy observations,
---------------
2 Observations
---------------
.. image:: https://raw.githubusercontent.com/swift-nav/albatross/master/examples/sinc_function_2.png
:align: center
not great, but at least it knows it isn't great. As we start to add more observations
we can watch the model slowly get more confident,
---------------
5 Observations
---------------
.. image:: https://raw.githubusercontent.com/swift-nav/albatross/master/examples/sinc_function_5.png
:align: center
---------------
10 Observations
---------------
.. image:: https://raw.githubusercontent.com/swift-nav/albatross/master/examples/sinc_function_10.png
:align: center
---------------
30 Observations
---------------
.. image:: https://raw.githubusercontent.com/swift-nav/albatross/master/examples/sinc_function_30.png
:align: center
20 changes: 20 additions & 0 deletions doc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python -msphinx
SPHINXPROJ = albatross
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
Loading

0 comments on commit 6c7b5cd

Please sign in to comment.