Skip to content

Commit 485d8d6

Browse files
authored
Tidy up for 0.8 (#228)
* Rename and move * Remove redundant comments * Shuffle and remove dead code * Update NEWS * Bump minor version * Update news * Bump docs deps * Import things * Tweak docs builder * Improve test coverage * Temporary performance bug fix * stabilise getting_started example * Finish off extended_mauna_loa upgrade
1 parent 9acc3ee commit 485d8d6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+458
-618
lines changed

NEWS.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,28 @@ between versions, and discuss new features.
66
If you find a breaking change this is not reported here, please either raise an issue or
77
make a PR to ammend this document.
88

9+
## 0.8.0
10+
11+
### Breaking Changes
12+
13+
This version contains some re-naming, specifically
14+
- `WrappedGP` -> `AtomicGP`,
15+
- `wrap` -> `atomic`, and
16+
- `CompositeGP` -> `DerivedGP`,
17+
which better reflect what these types / functions represent in the context of a `GPPP`.
18+
It's possible that you've never interacted with them, in which case there's nothing to
19+
worry about.
20+
21+
Lots of code has been moved around in order to better organise everything.
22+
23+
A method of `vcat` has been added to build `BlockData` from `GPPPInput`s. This can make
24+
your code look a bit nicer, so you might want to use it.
25+
26+
Additionally, this package no longer depends explicitly upon Zygote or ZygoteRules.
27+
Instead, all AD rules that are needed use ChainRulesCore directly.
28+
29+
Deprecations mentioned in the 0.7 release have also been dropped.
30+
931
## 0.7.16
1032
- Deprecate `approx_posterior` in favour of `posterior`. This is being removed because it has been removed in AbstractGPs in favour of `posterior`. It will be entirely removed in the next breaking release.
1133
- Remove some redundant testing infrastructure and tidy up the file structure slightly.

Project.toml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,22 @@
11
name = "Stheno"
22
uuid = "8188c328-b5d6-583d-959b-9690869a5511"
3-
version = "0.7.18"
3+
version = "0.8.0"
44

55
[deps]
66
AbstractGPs = "99985d1d-32ba-4be9-9821-2ec096f28918"
77
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
88
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
9-
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
109
KernelFunctions = "ec8451be-7e33-11e9-00cf-bbf324bd1392"
1110
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1211
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
1312
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1413
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
15-
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
16-
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
17-
ZygoteRules = "700de1a5-db45-46bc-99cf-38207098b444"
1814

1915
[compat]
2016
AbstractGPs = "0.4, 0.5"
2117
BlockArrays = "0.15, 0.16"
2218
ChainRulesCore = "1"
23-
FillArrays = "0.7, 0.8, 0.9, 0.10, 0.11, 0.12"
2419
KernelFunctions = "0.9.6, 0.10"
2520
MacroTools = "0.4, 0.5"
2621
Reexport = "0.2, 1"
27-
Zygote = "0.6"
28-
ZygoteRules = "0.2"
2922
julia = "1.3"

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ Stheno = "8188c328-b5d6-583d-959b-9690869a5511"
66
[compat]
77
Documenter = "0.27"
88
julia = "1.6"
9-
Stheno = "0.7"
9+
Stheno = "0.8"

docs/make.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
using Pkg
2+
Pkg.develop(path=joinpath(@__DIR__, ".."))
3+
4+
using Documenter
5+
using Stheno
6+
17
### Process examples
28

39
# Always rerun examples
@@ -35,8 +41,9 @@ else
3541
mkpath(EXAMPLES_OUT)
3642
end
3743

44+
dev_command = "Pkg.develop(PackageSpec(; path=relpath(\"$(pkgdir(Stheno))\", pwd())));"
3845

39-
let script = "using Pkg; Pkg.activate(ARGS[1]); Pkg.instantiate()"
46+
let script = "using Pkg; Pkg.activate(ARGS[1]); $dev_command Pkg.instantiate()"
4047
for example in example_locations
4148
if !success(`$(Base.julia_cmd()) -e $script $example`)
4249
error(
@@ -68,10 +75,6 @@ isempty(processes) || success(processes) || error("some examples were not run su
6875

6976

7077
### Build documentation
71-
using Pkg
72-
Pkg.develop(path=joinpath(@__DIR__, ".."))
73-
using Documenter, Stheno
74-
7578
DocMeta.setdocmeta!(
7679
Stheno,
7780
:DocTestSetup,

docs/src/input_types.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ For example, this means that when handling multi-dimensional inputs stored in a
3131
When constructing a GP whose domain is the real-line, for example when using a GP to solve some kind of time-series problem, it is sufficient to work with `Vector{<:Real}`s of inputs. As such, the following is completely valid:
3232
```julia
3333
using Stheno: GPC
34-
f = wrap(GP(SqExponentialKernel()), GPC())
34+
f = atomic(GP(SqExponentialKernel()), GPC())
3535
x = randn(10)
3636
f(x)
3737
```

docs/src/internals.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Interfaces
22

33
The primary objects in Stheno are some special subtypes of `AbstractGP`. There are three primary concrete subtypes of `AbstractGP`:
4-
- `WrappedGP`: an atomic Gaussian process given by wrapping an `AbstractGP`.
5-
- `CompositeGP`: a Gaussian process composed of other `WrappedGP`s and `CompositeGP`s, whose properties are determined recursively from the GPs of which it is composed.
6-
- `GaussianProcessProbabilisticProgramme` / `GPPP`: a Gaussian process comprising `WrappedGP`s and `CompositeGP`s. This is the primary piece of functionality that users should interact with.
4+
- `AtomicGP`: an atomic Gaussian process given by wrapping an `AbstractGP`.
5+
- `CompositeGP`: a Gaussian process composed of other `AtomicGP`s and `CompositeGP`s, whose properties are determined recursively from the GPs of which it is composed.
6+
- `GaussianProcessProbabilisticProgramme` / `GPPP`: a Gaussian process comprising `AtomicGP`s and `CompositeGP`s. This is the primary piece of functionality that users should interact with.
77

88
Each of these types implements the [Internal AbstractGPs API](https://github.com/JuliaGaussianProcesses/AbstractGPs.jl).
99

@@ -13,7 +13,7 @@ This documentation provides the information necessary to understand the internal
1313

1414
It is crucial for pseudo-point methods, and for the computation of marginal statistics at a reasonable scale, to be able to compute the diagonal of a given covariance matrix in linear time in the size of its inputs.
1515
This, in turn, necessitates that the diagonal of a given cross-covariance matrix can also be computed efficiently as the evaluation of covariance matrices often rely on the evaluation of cross-covariance matrices.
16-
As such, we have the following functions in addition to the AbstractGPs API implemented for `WrappedGP`s and `CompositeGP`s:
16+
As such, we have the following functions in addition to the AbstractGPs API implemented for `AtomicGP`s and `CompositeGP`s:
1717

1818
| Function | Brief description |
1919
|:--------------------- |:---------------------- |
@@ -24,18 +24,18 @@ As such, we have the following functions in addition to the AbstractGPs API impl
2424
The second and third rows of the table only make sense when `length(x) == length(x′)`, of course.
2525

2626

27-
## WrappedGP
27+
## AtomicGP
2828

29-
We can construct a `WrappedGP` in the following manner:
29+
We can construct a `AtomicGP` in the following manner:
3030

3131
```julia
32-
f = wrap(GP(m, k), gpc)
32+
f = atomic(GP(m, k), gpc)
3333

3434
```
3535
where `m` is its `MeanFunction`, `k` its `Kernel`. `gpc` is a `GPC` object that handles some book-keeping, and is discussed in more depth below.
3636

37-
The `AbstractGP` interface is implemented for `WrappedGP`s in terms of the `AbstractGP` that they wrap.
38-
So if you want a particular behaviour, just make sure that the `AbstractGP` that you wrap has the functionality you want.
37+
The `AbstractGP` interface is implemented for `AtomicGP`s in terms of the `AbstractGP` that they atomic.
38+
So if you want a particular behaviour, just make sure that the `AbstractGP` that you atomic has the functionality you want.
3939

4040
### Aside: Example Kernel implementation
4141

@@ -55,16 +55,16 @@ You should write
5555
```julia
5656
# THIS IS GOOD. PLEASE DO THIS
5757
gpc = GPC()
58-
f = wrap(GP(mf, kf), gpc)
59-
g = wrap(GP(mg, kg), gpc)
58+
f = atomic(GP(mf, kf), gpc)
59+
g = atomic(GP(mg, kg), gpc)
6060
h = f + g
6161
# THIS IS GOOD. PLEASE DO THIS
6262
```
6363
The rule is simple: when constructing GPs that you plan to make interact later in your program, construct them using the same `gpc` object. For example, DON'T do the following:
6464
```julia
6565
# THIS IS BAD. PLEASE DON'T DO THIS
66-
f = wrap(GP(mf, kf), GPC())
67-
g = wrap(GP(mg, kg), GPC())
66+
f = atomic(GP(mf, kf), GPC())
67+
g = atomic(GP(mg, kg), GPC())
6868
h = f + g
6969
# THIS IS BAD. PLEASE DON'T DO THIS
7070
```
@@ -75,7 +75,7 @@ The mistake here is to construct a separate `GPC` object for each `GP`. Hopefull
7575

7676
## CompositeGP
7777

78-
`CompositeGP`s are constructed as affine transformations of `CompositeGP`s and `WrappedGP`s.
78+
`CompositeGP`s are constructed as affine transformations of `CompositeGP`s and `AtomicGP`s.
7979
We describe the implemented transformations below.
8080
You can add additional transformations -- see [Custom Affine Transformations](@ref) for an a worked example.
8181

@@ -129,7 +129,7 @@ This particular function isn't part of the user-facing API because it isn't gene
129129
## GPPP
130130

131131
The `GaussianProcessProbabilisticProgramme` is another `AbstractGP` which enables provides a
132-
thin layer of convenience functionality on top of `WrappedGP`s and `CompositeGP`s, and is
132+
thin layer of convenience functionality on top of `AtomicGP`s and `CompositeGP`s, and is
133133
the primary way in which it is intended that users will interact with this package.
134134

135135
A `GPPP` like this
@@ -140,11 +140,11 @@ f = @gppp let
140140
f3 = f1 + f2
141141
end
142142
```
143-
is equivalent to manually constructing a `GPPP` using `WrappedGP`s and `CompositeGP`s:
143+
is equivalent to manually constructing a `GPPP` using `AtomicGP`s and `CompositeGP`s:
144144
```julia
145145
gpc = GPC()
146-
f1 = wrap(GP(SEKernel()), gpc)
147-
f2 = wrap(GP(SEKernel()), gpc)
146+
f1 = atomic(GP(SEKernel()), gpc)
147+
f2 = atomic(GP(SEKernel()), gpc)
148148
f3 = f1 + f2
149149
f = Stheno.GPPP((f1=f1, f2=f2, f3=f3), gpc)
150150
```

examples/custom_affine_transformations/script.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ using Stheno
1717
# Suppose that, for some reason, you wish to implement the affine transformation of a single
1818
# process `f` given by `(Af)(x) = f(x) + f(x + 3) - 2`.
1919
# In order to define this transformation, first create a function which accepts `f` and
20-
# returns a `CompositeGP`:
21-
using Stheno: AbstractGP, CompositeGP, SthenoAbstractGP
20+
# returns a `DerivedGP`:
21+
using Stheno: AbstractGP, DerivedGP, SthenoAbstractGP
2222

23-
A(f::SthenoAbstractGP) = CompositeGP((A, f), f.gpc)
23+
A(f::SthenoAbstractGP) = DerivedGP((A, f), f.gpc)
2424

25-
# The first argument to `CompositeGP` contains `A` itself and any data needed to fully
25+
# The first argument to `DerivedGP` contains `A` itself and any data needed to fully
2626
# specify the process results from this transformation. In this case the only piece of
2727
# information required is `f`, but really any data can be put in this argument.
2828
# For example, if we wished to replace the translation of `-3` by a parameter, we could do
@@ -48,7 +48,7 @@ const A_args = Tuple{typeof(A), SthenoAbstractGP};
4848
Stheno.mean((A, f)::A_args, x::AbstractVector) = mean(f, x) .+ mean(f, x .+ 3) .- 2
4949

5050
# The first argument here is _always_ going to be precisely the tuple of arguments passed
51-
# into the `CompositeGP` constructor above.
51+
# into the `DerivedGP` constructor above.
5252
# You can assume that you can compute any statistics of `f` that the AbstractGPs API
5353
# provides.
5454

examples/differentiation/script.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import AbstractGPs: mean, cov, var
2222

2323
using AbstractGPs: AbstractGP
2424
using AbstractGPs.TestUtils: test_internal_abstractgps_interface
25-
using Stheno: CompositeGP
25+
using Stheno: DerivedGP
2626

27-
derivative(f::AbstractGP) = CompositeGP((derivative, f), f.gpc)
27+
derivative(f::AbstractGP) = DerivedGP((derivative, f), f.gpc)
2828

2929

3030
const deriv_args = Tuple{typeof(derivative), AbstractGP}

examples/extended_mauna_loa/script.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ function optimize_loss(loss, θ_init; optimizer=default_optimizer, maxiter=1_000
209209
return unflatten(result.minimizer), result
210210
end
211211

212+
function KernelFunctions.kernelmatrix(k::ConstantKernel, x::AbstractVector)
213+
return fill(only(k.c), length(x), length(x))
214+
end
215+
216+
function KernelFunctions.kernelmatrix(k::ConstantKernel, x::AbstractVector, y::AbstractVector)
217+
return fill(only(k.c), length(x), length(y))
218+
end
219+
212220
θ_opt, result = optimize_loss(nlml, init_params)
213221

214222
# ## Plot the resulting model fit.

examples/getting_started/script.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,9 @@ using ParameterHandling
129129
l2 = positive(5.0),
130130
s2 = positive(1.0),
131131

132-
## Observation noise variance -- we'll be learning this as well.
133-
s_noise = positive(0.1),
132+
## Observation noise variance -- we'll be learning this as well. Constrained to be
133+
## at least 1e-3.
134+
s_noise = positive(0.1, exp, 1e-3),
134135
)
135136

136137
# We've used `ParameterHandling.jl`s `positive` constraint to ensure that all of the

src/Stheno.jl

Lines changed: 27 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,47 @@
11
module Stheno
22

3+
# Users generally need access to the functionality from both of these packages.
34
using Reexport
5+
@reexport using AbstractGPs
6+
@reexport using KernelFunctions
47

5-
using AbstractGPs
68
using BlockArrays
79
using ChainRulesCore
8-
using FillArrays
9-
@reexport using KernelFunctions
1010
using LinearAlgebra
1111
using Random
12-
using Zygote
13-
using ZygoteRules
1412

1513
import Base.Broadcast: broadcasted
1614

17-
using AbstractGPs: AbstractGP, FiniteGP, GP
18-
import AbstractGPs:
19-
mean,
20-
cov,
21-
var,
22-
mean_and_cov,
23-
mean_and_var,
24-
rand,
25-
logpdf,
26-
elbo,
27-
dtc,
28-
posterior,
29-
marginals
15+
using AbstractGPs: AbstractGP, FiniteGP
16+
import AbstractGPs: mean, cov, var
3017

3118
using MacroTools: @capture, combinedef, postwalk, splitdef
3219

3320
const AV{T} = AbstractVector{T}
3421

35-
# Various bits of utility that aren't inherently GP-related. Often very type-piratic.
36-
include(joinpath("util", "zygote_rules.jl"))
37-
include(joinpath("util", "covariance_matrices.jl"))
38-
include(joinpath("util", "block_arrays.jl"))
39-
include(joinpath("util", "abstract_data_set.jl"))
40-
include(joinpath("util", "proper_type_piracy.jl"))
41-
42-
# Supertype for GPs.
43-
include("abstract_gp.jl")
44-
45-
# Atomic GP objects.
46-
include(joinpath("gp", "gp.jl"))
47-
48-
# Composite GPs, constructed via affine transformation of CompositeGPs and GPs.
49-
include(joinpath("composite", "composite_gp.jl"))
50-
include(joinpath("composite", "cross.jl"))
51-
include(joinpath("composite", "product.jl"))
52-
include(joinpath("composite", "addition.jl"))
53-
include(joinpath("composite", "compose.jl"))
54-
# include(joinpath("composite", "gradient.jl"))
55-
# include(joinpath("composite", "integrate.jl"))
56-
57-
# Gaussian Process Probabilistic Programme object which implements the AbstractGPs API.
22+
# A couple of AbstractVector subtypes useful for expressing structure in inputs
23+
# regularly found in GPPPs.
24+
include("input_collection_types.jl")
25+
26+
# AbstractGP subtypes and associated utility.
27+
include(joinpath("gp", "util.jl"))
28+
include(joinpath("gp", "atomic_gp.jl"))
29+
include(joinpath("gp", "derived_gp.jl"))
30+
include(joinpath("gp", "sparse_finite_gp.jl"))
31+
32+
# Affine transformation library. Each file contains one / a couple of closely-related
33+
# affine transformations. Consequently, the code in each file can be understood
34+
# independently of the code in each other file.
35+
include(joinpath("affine_transformations", "cross.jl"))
36+
include(joinpath("affine_transformations", "addition.jl"))
37+
include(joinpath("affine_transformations", "compose.jl"))
38+
include(joinpath("affine_transformations", "product.jl"))
39+
40+
# AbstractGP subtype which groups together other AbstractGP subtypes.
5841
include("gaussian_process_probabilistic_programme.jl")
5942

60-
# Sparse GP hack to make pseudo-point approximations play nicely with Turing.jl.
61-
include("sparse_finite_gp.jl")
62-
63-
include("deprecate.jl")
64-
65-
export wrap, BlockData, GPC, GPPPInput, @gppp
43+
export atomic, BlockData, GPC, GPPPInput, @gppp
6644
export , select, stretch, periodic, shift
67-
export cov_diag, mean_and_cov_diag
45+
export SparseFiniteGP
46+
6847
end # module

src/composite/addition.jl renamed to src/affine_transformations/addition.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Produces an AbstractGP `f` satisfying `f(x) = fa(x) + fb(x)`.
77
"""
88
function +(fa::AbstractGP, fb::AbstractGP)
99
@assert fa.gpc === fb.gpc
10-
return CompositeGP((+, fa, fb), fa.gpc)
10+
return DerivedGP((+, fa, fb), fa.gpc)
1111
end
1212
-(fa::AbstractGP, fb::AbstractGP) = fa + (-fb)
1313

@@ -52,10 +52,10 @@ end
5252

5353

5454
#
55-
# Add a constant or known function to a GP -- just shifts the mean
55+
# Add a constant or known function to an AbstractGP -- just shifts the mean
5656
#
5757

58-
+(b, f::AbstractGP) = CompositeGP((+, b, f), f.gpc)
58+
+(b, f::AbstractGP) = DerivedGP((+, b, f), f.gpc)
5959
+(f::AbstractGP, b) = b + f
6060
-(b::Real, f::AbstractGP) = b + (-f)
6161
-(f::AbstractGP, b::Real) = f + (-b)

0 commit comments

Comments
 (0)