Skip to content

Commit

Permalink
Merge branch 'master' into st/gamma_swap
Browse files Browse the repository at this point in the history
  • Loading branch information
theogf authored Jan 31, 2022
2 parents c675c62 + 05abf88 commit 7a48b74
Show file tree
Hide file tree
Showing 27 changed files with 247 additions and 255 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.DS_Store
/Manifest.toml
test/Manifest.toml
docs/Manifest.toml
/dev/
/docs/build/
/docs/site/
Expand Down
5 changes: 4 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ version = "0.3.0"
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[compat]
Distributions = "0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25"
Functors = "0.1, 0.2"
StatsFuns = "0.9"
InverseFunctions = "0.1.2"
StatsFuns = "0.9.13"
julia = "1.3"
99 changes: 0 additions & 99 deletions docs/Manifest.toml

This file was deleted.

2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using Documenter, GPLikelihoods
makedocs(;
modules=[GPLikelihoods],
format=Documenter.HTML(),
pages=["Home" => "index.md"],
pages=["Home" => "index.md", "API" => "api.md"],
repo="https://github.com/JuliaGaussianProcesses/GPLikelihoods.jl/blob/{commit}{path}#L{line}",
sitename="GPLikelihoods.jl",
authors="JuliaGaussianProcesses organization",
Expand Down
45 changes: 45 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# API

```@index
```

## Likelihoods

```@docs
BernoulliLikelihood
CategoricalLikelihood
ExponentialLikelihood
GammaLikelihood
GaussianLikelihood
HeteroscedasticGaussianLikelihood
PoissonLikelihood
```

## Links

```@docs
Link
ChainLink
```

The rest of the links [`ExpLink`](@ref), [`LogisticLink`](@ref), etc.,
are aliases for the corresponding wrapped functions in a `Link`.
For example `ExpLink == Link{typeof(exp)}`.

When passing a [`Link`](@ref) to an `AbstractLikelihood`, this link
corresponds to the transformation `p=link(f)` while, as mentioned in the
[`Constrained parameters`](@ref) section, the statistics literature usually use
the denomination [**inverse link or mean function**](https://en.wikipedia.org/wiki/Generalized_linear_model#Link_function) for it.

```@docs
LogLink
ExpLink
InvLink
SqrtLink
SquareLink
LogitLink
LogisticLink
ProbitLink
NormalCDFLink
SoftMaxLink
```
55 changes: 51 additions & 4 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,55 @@
# GPLikelihoods.jl
```@meta
CurrentModule = GPLikelihoods
```
# GPLikelihoods

[`GPLikelihoods.jl`](https://github.com/JuliaGaussianProcesses/GPLikelihoods.jl) provides a practical interface to connect Gaussian and non-conjugate likelihoods
to Gaussian Processes.
The API is very basic: Every `AbstractLikelihood` object is a [functor](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects-1)
taking a `Real` or an `AbstractVector` as an input and returns a
`Distribution` from [`Distributions.jl`](https://github.com/JuliaStats/Distributions.jl).

### Single-latent vs multi-latent likelihoods

Most likelihoods, like the [`GaussianLikelihood`](@ref), only require one latent Gaussian process.
Passing a `Real` will therefore return a [`UnivariateDistribution`](https://juliastats.org/Distributions.jl/latest/univariate/),
and passing an `AbstractVector{<:Real}` will return a [multivariate product of distributions](https://juliastats.org/Distributions.jl/latest/multivariate/#Product-distributions).
```@repl
f = 2.0;
GaussianLikelihood()(f) == Normal(2.0)
fs = [2.0, 3.0, 1.5]
GaussianLikelihood()(fs) == Product([Normal(2.0), Normal(3.0), Normal(1.5)])
```

```@index
Some likelihoods, like the [`CategoricalLikelihood`](@ref), requires multiple latent Gaussian processes,
and an `AbstractVector{<:Real}` needs to be passed.
To obtain a product of distributions an `AbstractVector{<:AbstractVector{<:Real}}` has to be passed (we recommend
using [`ColVecs` and `RowVecs` from KernelFunctions.jl](https://juliagaussianprocesses.github.io/KernelFunctions.jl/stable/api/#Vector-Valued-Inputs)
if you need to transform an `AbstractMatrix`).
```@repl
fs = [2.0, 3.0, 4.5];
CategoricalLikelihood()(fs) isa Categorical
Fs = [rand(3) for _ in 1:4]
CategoricalLikelihood()(Fs) isa Product{<:Any,<:Categorical}
```

```@autodocs
Modules = [GPLikelihoods]
### Constrained parameters

The domain of some distributions parameters can be different from
``\mathbb{R}``, the real domain.
To solve this problem, we also provide the [`Link`](@ref) type, which can be
passed to the [`Likelihood`](@ref) constructors.
Alternatively, `function`s can also directly be passed and will be wrapped in a `Link`).
For more details about which likelihoods require a [`Link`](@ref) check out their docs.
We typically named this passed link as the `invlink`.
This comes from the statistic literature, where the "link" is defined as `f = link(y)`.

A classical example is the [`BernoulliLikelihood`](@ref) for classification, with the probability parameter ``p \in \[0, 1\]``.
The default it to use a [`logistic`](https://en.wikipedia.org/wiki/Logistic_function) transformation, but one could also use the inverse of the [`probit`](https://en.wikipedia.org/wiki/Probit) link:

```@repl
f = 2.0;
BernoulliLikelihood()(f) == Bernoulli(logistic(f))
BernoulliLikelihood(NormalCDFLink()) == Bernoulli(normalcdf(f))
```
Note that we passed the `inverse` of the `probit` function which is the `normalcdf` function.
8 changes: 5 additions & 3 deletions src/GPLikelihoods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module GPLikelihoods

using Distributions
using Functors
using InverseFunctions: InverseFunctions
using LinearAlgebra
using Random
using StatsFuns
Expand All @@ -15,6 +16,7 @@ export BernoulliLikelihood,
GammaLikelihood
export Link,
ChainLink,
BijectiveSimplexLink,
ExpLink,
LogLink,
InvLink,
Expand All @@ -26,9 +28,6 @@ export Link,
NormalCDFLink,
SoftMaxLink

# Inverses
include("inverse.jl")

# Links
include("links.jl")

Expand All @@ -41,4 +40,7 @@ include("likelihoods/poisson.jl")
include("likelihoods/gamma.jl")
include("likelihoods/exponential.jl")

# TestInterface module
include("TestInterface.jl")

end # module
60 changes: 60 additions & 0 deletions src/TestInterface.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module TestInterface

using Functors
using Random
using Test

function test_interface(rng::AbstractRNG, lik, out_dist, D_in=1; functor_args=())
N = 10
T = Float64 # TODO test Float32 as well
f, fs = if D_in == 1
f = randn(rng, T)
fs = randn(rng, T, 10)
f, fs
else
f = randn(rng, T, D_in)
fs = [randn(rng, T, D_in) for _ in 1:N]
f, fs
end
# Check if likelihood produces the correct distribution
# and is sampleable
@test lik(f) isa out_dist
@test_nowarn rand(rng, lik(f))

# Check if the likelihood samples are of correct length
@test length(rand(rng, lik(fs))) == N

# Check if functor works properly
xs, re = Functors.functor(lik)
@test lik == re(xs)
if isempty(functor_args)
@test xs === ()
else
@test keys(xs) == functor_args
end

return nothing
end

@doc raw"""
test_interface([rng::AbstractRNG,] lik, out_dist; functor_args=())
This function provides unified method to check the interface of the various likelihoods
defined. It checks if the likelihood produces the correct distribution, length of likelihood
samples is correct and if the functor works as intended.
...
## Arguments
- `lik`: the likelihood to test the interface of
- `out_dist::Type{<:Distribution}`: the type of distribution the likelihood should return
- `D_in::Int=1` : The input dimension of the likelihood
## Keyword arguments
- `functor_args=()`: a collection of symbols of arguments to match functor parameters with.
...
"""
function test_interface(lik, out_dist, D_in=1; kwargs...)
return test_interface(Random.GLOBAL_RNG, lik, out_dist, D_in; kwargs...)
end

end
27 changes: 0 additions & 27 deletions src/inverse.jl

This file was deleted.

2 changes: 1 addition & 1 deletion src/likelihoods/bernoulli.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct BernoulliLikelihood{Tl<:AbstractLink} <: AbstractLikelihood
invlink::Tl
end

BernoulliLikelihood(l=logistic) = BernoulliLikelihood(Link(l))
BernoulliLikelihood(l=logistic) = BernoulliLikelihood(link(l))

(l::BernoulliLikelihood)(f::Real) = Bernoulli(l.invlink(f))

Expand Down
Loading

0 comments on commit 7a48b74

Please sign in to comment.