/
VGP.jl
93 lines (79 loc) · 3.38 KB
/
VGP.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
VGP(args...; kwargs...)
Variational Gaussian Process
## Arguments
- `X::AbstractArray` : Input features, if `X` is a matrix the choice of colwise/rowwise is given by the `obsdim` keyword
- `y::AbstractVector` : Output labels
- `kernel::Kernel` : Covariance function, can be any kernel from KernelFunctions.jl
- `likelihood` : Likelihood of the model. For compatibilities, see [`Likelihood Types`](@ref likelihood_user)
- `inference` : Inference for the model, see the [`Compatibility Table`](@ref compat_table))
## Keyword arguments
- `verbose` : How much does the model print (0:nothing, 1:very basic, 2:medium, 3:everything)
- `optimiser` : Optimiser used for the kernel parameters. Should be an Optimiser object from the [Flux.jl](https://github.com/FluxML/Flux.jl) library, see list here [Optimisers](https://fluxml.ai/Flux.jl/stable/training/optimisers/) and on [this list](https://github.com/theogf/AugmentedGaussianProcesses.jl/tree/master/src/inference/optimisers.jl). Default is `ADAM(0.001)`
- `atfrequency::Int=1` : Choose how many variational parameters iterations are between hyperparameters optimization
- `mean=ZeroMean()` : PriorMean object, check the documentation on it [`MeanPrior`](@ref meanprior)
- `obsdim::Int=1` : Dimension of the data. 1 : X ∈ DxN, 2: X ∈ NxD
"""
mutable struct VGP{
T<:Real,
TLikelihood<:AbstractLikelihood,
TInference<:AbstractInference,
TData<:AbstractDataContainer,
N,
} <: AbstractGPModel{T,TLikelihood,TInference,N}
data::TData # Data container
f::NTuple{N,VarLatent{T}} # Vector of latent GPs
likelihood::TLikelihood
inference::TInference
verbose::Int #Level of printing information
atfrequency::Int
trained::Bool
end
function VGP(
X::AbstractArray,
y::AbstractVector,
kernel::Kernel,
likelihood::AbstractLikelihood,
inference::AbstractInference;
verbose::Int=0,
optimiser=ADAM(0.01),
atfrequency::Integer=1,
mean::Union{<:Real,AbstractVector{<:Real},PriorMean}=ZeroMean(),
obsdim::Int=1,
)
X, T = wrap_X(X, obsdim)
y = check_data!(y, likelihood)
inference isa VariationalInference || error(
"The inference object should be of type `VariationalInference` : either `AnalyticVI` or `NumericalVI`",
)
!isa(likelihood, GaussianLikelihood) || error(
"For a Gaussian Likelihood you should directly use the `GP` model or the `SVGP` model for large datasets",
)
implemented(likelihood, inference) ||
error("The $likelihood is not compatible or implemented with the $inference")
data = wrap_data(X, y)
if isa(optimiser, Bool)
optimiser = optimiser ? ADAM(0.01) : nothing
end
n_feature = n_sample(data)
if typeof(mean) <: Real
mean = ConstantMean(mean)
elseif typeof(mean) <: AbstractVector{<:Real}
mean = EmpiricalMean(mean)
end
latentf = ntuple(n_latent(likelihood)) do _
VarLatent(T, n_feature, kernel, mean, optimiser)
end
return VGP{T,typeof(likelihood),typeof(inference),typeof(data),n_latent(likelihood)}(
data, latentf, likelihood, inference, verbose, atfrequency, false
)
end
function Base.show(io::IO, model::VGP)
return print(
io,
"Variational Gaussian Process with a $(likelihood(model)) infered by $(inference(model)) ",
)
end
Zviews(m::VGP) = (input(m.data),)
objective(m::VGP, state, y) = ELBO(m, state, y)
@traitimpl IsFull{VGP}