Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
5936e54
using AbstractGPs
felixmett Feb 6, 2024
f75b5a5
GaussianProcessRegressor struct
felixmett Feb 6, 2024
ac83936
Using GaussianProcesses
felixmett Feb 7, 2024
cf0be3d
TODO: Proper normalization scheme
felixmett Feb 7, 2024
edcb05c
Merge branch 'FriesischScott:master' into gaussian-processes
felixmett Feb 14, 2024
965a847
Imports necessary for gps
Feb 15, 2024
5a85023
Merge branch 'gaussian-processes' of https://github.com/Cr0gan/Uncert…
Feb 15, 2024
7207f4c
Testing file, delete later
Feb 15, 2024
c37df3e
Split gp fit and hyperparameter optimization
Feb 15, 2024
131cfa4
Additional packages for gaussian-processes
Feb 15, 2024
f21cdd5
StatsBase normalization and Optimizer struct
felixmett Feb 15, 2024
fdca54c
Optimizer in gp function, implement evaluate method
felixmett Feb 29, 2024
8db025f
Gaussianprocess from input, model and output
felixmett Mar 4, 2024
88777e5
Removed input normalization where UQInput is given
felixmett Mar 5, 2024
5eadb18
Ignoring sample method for now
felixmett Mar 5, 2024
ec975e4
Suggestion for naming of normalize
felixmett May 13, 2024
67b0731
Merge branch 'master' of https://github.com/FriesischScott/Uncertaint…
felixmett May 13, 2024
b5be7a4
Merge branch 'gaussian-processes' of https://github.com/Cr0gan/Uncert…
felixmett May 13, 2024
b62b021
Accepted incoming changes
felixmett May 13, 2024
43a5312
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett Sep 23, 2024
efcc4fa
Remove dependecies on GaussianProcesses.jl
felixmett Sep 24, 2024
d63cde9
First working version
felixmett Sep 25, 2024
bfd10d7
Moved gaussianprocesses in subdirectory
felixmett Sep 25, 2024
abac806
Demonstration of how to use current version of gps
felixmett Sep 25, 2024
a3df9f7
Preliminary demo files
felixmett Sep 27, 2024
1a5304d
Current state of gp implementation
felixmett Sep 27, 2024
11d1ddd
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett Sep 27, 2024
a34afa9
Added packages AbstractGPs, ParameterHandling and Zygote
felixmett Sep 27, 2024
cc4fd8f
added constructors for every input case
felixmett Sep 27, 2024
57625a8
added function _handle_gp_input for AbstractGPs interface
felixmett Sep 27, 2024
a24aa98
added evaluate! method for gaussianprocesses
felixmett Sep 27, 2024
9399cb9
added a demo file for gps
felixmett Sep 27, 2024
8abd2cb
added a convenience method to get the name of a single UQInput
felixmett Sep 27, 2024
dc014ea
current version that works for univariate in- and output
felixmett Sep 27, 2024
d6e52d2
added includes and exports for gps
felixmett Sep 27, 2024
0dd38ed
using only instead of X[1]
felixmett Sep 27, 2024
270a9ce
transform copy of DataFrame to handle 1D case
felixmett Sep 27, 2024
5f9a8cd
started adding unit tests
felixmett Sep 27, 2024
0d6cc64
Merge branch 'FriesischScott:master' into gaussian-processes
felixmett Dec 6, 2024
895949d
Automatically extract parameters from GP model
felixmett Feb 10, 2025
3ae037f
Normalization of in- and outputs
felixmett Feb 10, 2025
c0be0ff
Cleaned up hyperparameter optimization
felixmett Feb 10, 2025
33b1782
Started restructuring GaussianProcess constructors
felixmett Feb 10, 2025
fb9e15a
Moved normalization to other file
felixmett Feb 10, 2025
db0202d
Store in- and output standardization in single struct
felixmett Feb 11, 2025
95ee9c9
Simple demo of current state
felixmett Feb 11, 2025
19c8f42
Added gaussian process exports
felixmett Feb 11, 2025
0a9cdf9
Refactoring
felixmett Feb 11, 2025
8d59344
Simplified optimization routine for NoOptimization
felixmett Feb 11, 2025
96efb04
Added parameter routines for ARDTransform
felixmett Feb 11, 2025
ca876d8
Added constructors and evaluate
felixmett Feb 11, 2025
52fdee8
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett Feb 11, 2025
9e6f205
Merge branch 'master' into gaussian-processes
FriesischScott Feb 21, 2025
351ad0b
Merge branch 'master' into gaussian-processes
FriesischScott Feb 25, 2025
94a4a55
Merge branch 'master' into gaussian-processes
FriesischScott Feb 28, 2025
cfe0d65
Merge branch 'master' into gaussian-processes
FriesischScott Jul 4, 2025
dab9478
Merge branch 'master' of https://github.com/FriesischScott/Uncertaint…
felixmett Aug 14, 2025
867fdbc
Added compat entries for AbstractGPs and Zygote
felixmett Aug 14, 2025
faf254e
Redesigned data standardization
felixmett Aug 19, 2025
1b373d2
Added DifferentiationInterface and compat entries
felixmett Aug 19, 2025
39f2a53
Using ParameterHandling for gaussian processes
felixmett Aug 19, 2025
7406036
Refactoring of type II maximum likelihood estimation
felixmett Aug 19, 2025
a61da82
Added input and output transforms to gaussian process struct
felixmett Aug 19, 2025
3bfd29e
Preliminary file to test parameter extraction
felixmett Aug 20, 2025
a853620
Add more kernels and transforms for automatic parameter handling
felixmett Aug 20, 2025
b27131a
Minimize documentation overhead
felixmett Aug 20, 2025
5c78fc6
Add DataTransforms for in- and output transformation
felixmett Sep 2, 2025
bc77331
Change to single DataTransforms struct to handle transformations
felixmett Sep 2, 2025
f5c4033
Export all datatransformations for gaussian processes
felixmett Sep 2, 2025
337b326
Add types of inputs
felixmett Sep 2, 2025
3d7de71
Preliminary demo
felixmett Sep 2, 2025
548cd52
Refactor data standardization pipeline
felixmett Sep 3, 2025
027db46
Refactor data standardization pipeline
felixmett Sep 3, 2025
b3feed3
Preliminary test for refactored data standardization
felixmett Sep 3, 2025
48758d0
Preliminary unit test for data standardization
felixmett Sep 3, 2025
581f110
Add inverse output transform for gp posterior variance
felixmett Sep 3, 2025
a984293
Add var! and mean_and_var! methods for gps
felixmett Sep 3, 2025
0a7ec3c
Fix wrongly returned output transforms
felixmett Sep 3, 2025
8e9f339
Preliminary tests
felixmett Sep 3, 2025
55a0832
Add AbstractGPs to tests
felixmett Sep 3, 2025
6196775
Add unit tests for gp data standardization
felixmett Sep 4, 2025
f77e7b1
Add gaussian process regression reference
felixmett Sep 4, 2025
8137f0b
Add theoretical background documentation for gaussian process regression
felixmett Sep 4, 2025
109dc59
Add export NoHyperparameterOptimization
felixmett Sep 15, 2025
6fc01d1
Refactor NoHyperparameterOptimization
felixmett Sep 15, 2025
1c4bfb6
Add tests for GaussianProcess construction
felixmett Sep 15, 2025
531b25a
Preliminary test files
felixmett Sep 15, 2025
6bc6ead
Preliminary idea to test parameter extraction implementation
felixmett Sep 18, 2025
9f264ae
Preliminary commit
felixmett Oct 9, 2025
d0880a9
Add extract and apply method for unsupported kernels
felixmett Oct 9, 2025
0871a3c
Add test to check improvement after hyperparameter optimization
felixmett Oct 9, 2025
9bf53e5
Add test to check implementation for all kernels, transforms and mean…
felixmett Oct 9, 2025
42db9da
Refactor data standardization tests
felixmett Oct 9, 2025
1e71f29
Add complete test set for gaussian process regression constructors
felixmett Oct 9, 2025
21117c1
Refactor gaussian process hyperparameter optimization tests
felixmett Oct 9, 2025
e4ab211
Preliminary example
felixmett Oct 9, 2025
c892a43
Add documentation for exported structs
felixmett Oct 9, 2025
5c25292
Add documentation
felixmett Oct 10, 2025
6369de1
Add developer note
felixmett Oct 10, 2025
5feb38c
Add documentation and developer note
felixmett Oct 10, 2025
76bdc2c
Update DifferentiationInterface
felixmett Oct 10, 2025
a40bbd3
Refactor gaussian process evaluate!
felixmett Oct 13, 2025
ee0ab23
Fix only RandomVariables are used as gaussian process input
felixmett Oct 13, 2025
c92db59
Fix wrongful discarding of deterministic inputs
felixmett Oct 13, 2025
9118cf4
Preliminary examples
felixmett Oct 13, 2025
132145d
Current state of documentation
felixmett Oct 13, 2025
5e7a745
Current state of docs
felixmett Oct 13, 2025
3a1906b
Finish gaussian process documentation
felixmett Oct 14, 2025
7896712
Delete preliminary testing files
felixmett Oct 14, 2025
3679ee0
Fix gaussian process output name for mode :mean
felixmett Oct 14, 2025
ca8df9d
Add literate example for gaussian process regression
felixmett Oct 14, 2025
d0b3749
Delete unused exports
felixmett Oct 14, 2025
1fc82ee
Add execution of gaussian process tests
felixmett Oct 14, 2025
532ca08
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett Oct 14, 2025
b5369ff
Reexport AbstractGPs
felixmett Oct 14, 2025
a7f44ce
Fix docstrings
felixmett Oct 14, 2025
70ef0fc
Fix docstrings
felixmett Oct 14, 2025
61322a3
Fix documentation dependencies and loaded modules
felixmett Oct 14, 2025
a02af1d
Fix type of posterior gp in GaussianProcess
felixmett Oct 14, 2025
13179d1
Add literate demo file
felixmett Oct 14, 2025
11667f2
Fix bug where single UQInput is not filtered for random inputs
felixmett Oct 14, 2025
4e4c19d
Fix docstring does not require using AbstractGP
felixmett Oct 14, 2025
8fbc8a8
Add gaussian processes api
felixmett Oct 16, 2025
9982b84
Fix typo in gaussian process literate demo
felixmett Oct 16, 2025
697cb54
Fix jldoctest error
felixmett Oct 16, 2025
d4b796a
Change github username of Felix
felixmett Oct 17, 2025
aae5b9d
Add missing docs
felixmett Oct 17, 2025
1962e22
Refactor example code blocks
felixmett Oct 17, 2025
8450250
Fix unresolved reference in docstring
felixmett Oct 17, 2025
703425d
Refactor internal docs to comments
felixmett Oct 17, 2025
b9a8ddd
Fix faulty indent and linting errors
felixmett Oct 22, 2025
2a33fe9
Simplify gaussian process in- and output standardization
felixmett Feb 1, 2026
43177a4
Merge branch 'gaussian-processes' of https://github.com/Cr0gan/Uncert…
felixmett Feb 1, 2026
5af056e
Remove NoHyperparameterOptimization struct
felixmett Feb 1, 2026
f14e9bf
Add function to optimize hyperparameters of instantiated gaussian pro…
felixmett Feb 1, 2026
b4b314e
Add exports for transform choices
felixmett Mar 5, 2026
bdfa850
Refactor gaussian process transformation struct names
felixmett Mar 5, 2026
ef9c75c
Add tests for parameter extraction and application
felixmett Mar 5, 2026
5fcfa1d
Add tests for in- and output transformations
felixmett Mar 5, 2026
fbb1e0d
Update documentation of gaussian processes
felixmett Mar 6, 2026
8c2c281
Remove legacy exports
felixmett Mar 6, 2026
a963d78
Fix bug in optimize_hyperparameters and evaluate!
felixmett Mar 6, 2026
65d1d31
Fix bug in docstring
felixmett Mar 6, 2026
a059dfa
Add constructor tests
felixmett Mar 6, 2026
d0fc4a8
Add hyperparameter optimization tests
felixmett Mar 6, 2026
b75a9c9
Refactor testset name
felixmett Mar 6, 2026
38f0b05
Use newest version of DifferentiationInterface
felixmett Mar 6, 2026
264ce63
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett Mar 9, 2026
b846624
Merge branch 'master' into gaussian-processes
FriesischScott Apr 21, 2026
3ce7ef3
Update Demo
FriesischScott Apr 21, 2026
e4a49d1
Merge branch 'master' of https://github.com/FriesischScott/Uncertaint…
felixmett May 29, 2026
4cca66a
Fix formatting issue
felixmett May 29, 2026
fb71d43
Merge branch 'gaussian-processes' of https://github.com/Cr0gan/Uncert…
felixmett May 29, 2026
2476aa4
Remove merge conflict artifact
felixmett May 29, 2026
6bf7d0e
Fix Optim compat to match package version
felixmett May 29, 2026
5982277
Fix inconsistent ranges between training and test data
felixmett May 29, 2026
266a3f6
Remove parameterization Unions
FriesischScott Jul 31, 2026
2b28f90
Fix missing end
FriesischScott Jul 31, 2026
dab0fbb
Merge branch 'master' into gaussian-processes
FriesischScott Jul 31, 2026
095568b
Explicitly import sample function
FriesischScott Jul 31, 2026
1d8a6d0
Change internal implementation of GP construction
jgrashorn Jul 31, 2026
f73036e
Fix tests
FriesischScott Jul 31, 2026
5eef6c4
fixed tests, added safeguards
jgrashorn Aug 5, 2026
9541cd6
checked tests running
jgrashorn Aug 5, 2026
6ae984d
Merge branch 'master' into gaussian-processes
FriesischScott Aug 6, 2026
6d62703
changed gp test structure
jgrashorn Aug 6, 2026
ade139a
fix GP constructor
jgrashorn Aug 6, 2026
b9597a6
optional hyperparameter tuning
jgrashorn Aug 7, 2026
8aaf1b3
changed docs to new GPs
jgrashorn Aug 7, 2026
a292015
demo fix
jgrashorn Aug 7, 2026
c090e78
docstrings and doc fix
jgrashorn Aug 8, 2026
66c753a
Correctly initialize experimental design
FriesischScott Aug 10, 2026
362da0a
Correctly initialize experimental design
FriesischScott Aug 10, 2026
a8f0413
Fix typo
FriesischScott Aug 10, 2026
d187c8b
Fix error message
FriesischScott Aug 10, 2026
dbaf838
Add missing for
FriesischScott Aug 10, 2026
4d4dcc3
Fix typo
FriesischScott Aug 10, 2026
76f6ca6
observation noise fix
jgrashorn Aug 10, 2026
a55fd0a
Merge branch 'master' into gaussian-processes
FriesischScott Aug 12, 2026
b009630
Set default sigma^2 to 1e-10
lukasfritsch Aug 20, 2026
b2a3224
Merge branch 'master' into gaussian-processes
FriesischScott Aug 21, 2026
e1dbe90
Fix formatting
FriesischScott Aug 21, 2026
19080d8
Add adaptive GPs and random restart optimization
lukasfritsch Aug 24, 2026
1202254
Format docstrings with runic
lukasfritsch Aug 25, 2026
a64f202
Apply suggestions from code review
lukasfritsch Aug 25, 2026
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
5 changes: 5 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Jasper Behrensdorf <behrensdorf@irz.uni-hannover.de>", "Ander Gray <

[deps]
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
AbstractGPs = "99985d1d-32ba-4be9-9821-2ec096f28918"
Bootstrap = "e28b5b4c-05e8-5b66-bc03-6f0c0a0a06e0"
Clarabel = "61c947e1-3e6d-4ee4-985a-eec8c727bd6e"
Copulas = "ae264745-0b69-425e-9d9d-cf662c5eec93"
Expand All @@ -25,7 +26,9 @@ MeshAdaptiveDirectSearch = "f4d74008-4565-11e9-04bd-4fe404e6a92a"
Monomials = "272bfe72-f66c-432f-a94d-600f29493792"
Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6"
Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
NLSolversBase = "d41bc354-129a-5804-8e4c-c37616107c6c"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
ParameterHandling = "2412ca09-6db7-441c-8e3a-88d5709968c5"
Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b"
Expand All @@ -39,6 +42,7 @@ TransportMaps = "6fd49bf0-03ac-4dd1-b9b3-42e511274d6e"

[compat]
ADTypes = "1.21.0"
AbstractGPs = "0.5.24"
Bootstrap = "2.2"
Clarabel = "0.11.1"
Copulas = "0.1.34"
Expand All @@ -56,6 +60,7 @@ MeshAdaptiveDirectSearch = "0.1.0"
Monomials = "1.0"
Mooncake = "0.4.196, 0.5"
Mustache = "1.0"
NLSolversBase = "8.0.1"
Optim = "2.0, 2.1"
Primes = "0.5"
QuadGK = "2.11.1"
Expand Down
42 changes: 42 additions & 0 deletions demo/metamodels/gaussianprocess.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using UncertaintyQuantification

x = RandomVariable.(Uniform(-5, 5), [:x1, :x2])

himmelblau = Model(
df -> (df.x1 .^ 2 .+ df.x2 .- 11) .^ 2 .+ (df.x1 .+ df.x2 .^ 2 .- 7) .^ 2, :y
)

design = LatinHypercubeSampling(80)

mean_f = ConstMean(0.0)
kernel = SqExponentialKernel()

gp_prior = GP(mean_f, kernel)

using Optim

optimizer = MaximumLikelihoodEstimation(Optim.Adam(alpha = 0.005), Optim.Options(; iterations = 10, show_trace = false))

input_transform = ZScoreTransformChoice()

gp_model = GaussianProcess(
gp_prior,
x,
himmelblau,
:y;
experimental_design = design,
input_transform = input_transform,
optimizer = optimizer
)

test_data = sample(x, 1000)
evaluate!(gp_model, test_data; mode = :mean_and_var)

test_data = sample(x, 1000)
evaluate!(gp_model, test_data)
evaluate!(himmelblau, test_data)

mse = mean((test_data.y .- test_data.y_mean) .^ 2)
println("MSE is: $mse")

# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl
55 changes: 55 additions & 0 deletions demo/metamodels/gaussianprocessadaptive.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using UncertaintyQuantification
using Plots
using DataFrames
using Optim # hide

x = RandomVariable.(Uniform(-5, 5), [:x1, :x2])
himmelblau = Model(
df -> (df.x1 .^ 2 .+ df.x2 .- 11) .^ 2 .+ (df.x1 .+ df.x2 .^ 2 .- 7) .^ 2, :y
)

design = LatinHypercubeSampling(80)
mean_f = ConstMean(0.0)
kernel = SqExponentialKernel()

gp_prior = GP(mean_f, kernel)
input_transform = ZScoreTransformChoice()
optimizer = MaximumLikelihoodEstimation(Optim.Adam(alpha = 0.005), Optim.Options(; iterations = 10, show_trace = false))

initial_gp = GaussianProcess(
gp_prior,
x,
himmelblau,
:y;
experimental_design = design,
input_transform = input_transform,
optimizer = optimizer
)

learning_function = MaximinDistance()
n_added_points = 20

adaptive_gp = AdaptiveGaussianProcess(
deepcopy(initial_gp),
x,
himmelblau,
learning_function,
n_added_points;
optimizer = optimizer
)

test_data = sample(x, LatinHypercubeSampling(1000))
test_data_adaptive = deepcopy(test_data)
evaluate!(initial_gp, test_data; mode = :mean)
evaluate!(himmelblau, test_data)

mse = mean((test_data.y .- test_data.y_mean) .^ 2)
println("MSE (initial GP): $mse")

evaluate!(adaptive_gp, test_data_adaptive; mode = :mean)
evaluate!(himmelblau, test_data_adaptive)

mse_adap = mean((test_data_adaptive.y .- test_data_adaptive.y_mean) .^ 2)
println("MSE (adaptive GP): $mse_adap")

# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl
2 changes: 2 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
UncertaintyQuantification = "7183a548-a887-11e9-15ce-a56ab60bad7a"
Expand All @@ -14,3 +15,4 @@ UncertaintyQuantification = "7183a548-a887-11e9-15ce-a56ab60bad7a"
Documenter = "1.14.1"
DocumenterCitations = "1.4.1"
DocumenterVitepress = "0.2.6"
Optim = "1.9.4, 2.0"
136 changes: 136 additions & 0 deletions docs/literate/metamodels/gaussianprocess.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#===
# Gaussian Process Regression

## Himmelblau's Function

In this example, we will model the following test function (known as Himmelblau's function) in the range ``x1, x2 ∈ [-5, 5]`` with a Gaussian process (GP) regression model.

It is defined as:

```math
f(x1, x2) = (x1^2 + x2 - 11)^2 + (x1 + x2^2 - 7)^2.
```
===#
# ![](himmelblau.svg)
#===
Analogue to the response surface example, we create an array of random variables, that will be used when evaluating the points that our experimental design produces.
===#

using UncertaintyQuantification

x = RandomVariable.(Uniform(-5, 5), [:x1, :x2])

himmelblau = Model(
df -> (df.x1 .^ 2 .+ df.x2 .- 11) .^ 2 .+ (df.x1 .+ df.x2 .^ 2 .- 7) .^ 2, :y
)
#md nothing # hide

#===
Next, we chose a experimental design. In this example, we are using a `LatinHyperCube` design from which we draw 80 samples to train our model:
===#

design = LatinHypercubeSampling(80)

#===
After that, we construct a prior GP model. Here we assume a constant mean of 0.0 and a squared exponential kernel with automatic relevance determination (ARD).
We also assume a small Gaussian noise term in the observations for numerical stability:
===#

mean_f = ConstMean(0.0)
kernel = SqExponentialKernel()

gp_prior = GP(mean_f, kernel)

#===
Next, we set up an optimizer used in the log marginal likelihood maximization to find the optimal hyperparameters of our GP model. Here we use the Adam optimizer from the `Optim.jl` package with a learning rate of 0.005 and run it for 10 iterations.:
===#
using Optim

optimizer = MaximumLikelihoodEstimation(Optim.Adam(alpha = 0.005), Optim.Options(; iterations = 10, show_trace = false))
#md nothing # hide

#===
Finally, we define an input standardization (here a z-score transform). While not strictly necessary for this example, standardization can help finding good hyperparameters.
Note that we can also define an output transform to scale the output for training the GP. When evaluating the GP model, the input will be automatically transformed with the fitted standardization.
The output will be transformed back to the original scale automatically as well.
===#

input_transform = ZScoreTransformChoice()
#md nothing # hide

#===
The GP regression model is now constructed by calling the `GaussianProcess` constructor with the prior GP, the input random variables, the model, the output symbol, the experimental design, and the optional input and output transform choices.
The construction then samples the experimental design, evaluates the model at the sampled points, standardizes the input and output data, and constructs the posterior GP.
===#
#md using Random #hide
#md Random.seed!(42) #hide

gp_model = GaussianProcess(
gp_prior,
x,
himmelblau,
:y;
experimental_design = design,
input_transform = input_transform,
optimizer = optimizer
)
#md nothing # hide

#===
The GP regression model uses finite projections of the fitted posterior GP to make predictions. As of now, the hyperparameters of the GP might not be optimal.
We can find optimal hyperparameters through maximizing the log marginal likelihood of observing the training data under the posterior GP.
===#

#===
To evaluate the `GaussianProcess`, use `evaluate!(gp::GaussianProcess, data::DataFrame)` with the `DataFrame` containing the points you want to evaluate.
The evaluation of a GP is not unique, and we can choose to evaluate the mean prediction, the prediction variance, a combination of both, or draw samples from the posterior distribution.
The default is to evaluate the mean prediction.
We can specify the evaluation mode via the `mode` keyword argument. Supported options are:
- `:mean` - predictive mean (default)
- `:var` - predictive variance
- `:mean_and_var` - both mean and variance
- `:sample` - random samples from the predictive distribution
===#

test_data = sample(x, 1000)
evaluate!(gp_model, test_data; mode = :mean_and_var)

#===
The mean prediction of our model in this case has an mse of about 65 and looks like this in comparison to the original:
===#

#md using Plots #hide
#md using DataFrames #hide
#md a = range(-5, 5; length=200) #hide
#md b = range(-5, 5; length=200) #hide
#md A = repeat(collect(a)', length(b), 1) #hide
#md B = repeat(collect(b), 1, length(a)) #hide
#md df = DataFrame(x1 = vec(A), x2 = vec(B)) #hide
#md evaluate!(gp_model, df; mode=:mean_and_var) #hide
#md evaluate!(himmelblau, df) #hide
#md gp_mean = reshape(df[:, :y_mean], length(b), length(a)) #hide
#md gp_var = reshape(df[:, :y_var], length(b), length(a)) #hide
#md himmelblau_values = reshape(df[:, :y], length(b), length(a)) #hide
#md s1 = surface(a, b, himmelblau_values; plot_title="Himmelblau's function")
#md s2 = surface(a, b, gp_mean; plot_title="GP posterior mean")
#md plot(s1, s2, layout = (1, 2), legend = false)
#md savefig("gp-mean-comparison.svg") # hide
#md s3 = surface(a, b, gp_var; plot_title="GP posterior variance") # hide
#md plot(s3, legend = false) #hide
#md savefig("gp-variance.svg"); nothing # hide

# ![](gp-mean-comparison.svg)

#===
Note that the mse in comparison to the response surface model (with an mse of about 1e-26) is significantly higher.
However, the GP model also provides a measure of uncertainty in its predictions via the predictive variance.
===#

# ![](gp-variance.svg)

#jl test_data = sample(x, 1000)
#jl evaluate!(gp_model, test_data)
#jl evaluate!(himmelblau, test_data)

#jl mse = mean((test_data.y .- test_data.y_mean) .^ 2)
#jl println("MSE is: $mse")
105 changes: 105 additions & 0 deletions docs/literate/metamodels/gaussianprocessadaptive.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#===
# Adaptive Gaussian Process Regression

Adaptive Gaussian process regression enriches an initial surrogate model with
new evaluations selected by a learning function. At every iteration, the
algorithm samples candidate points, selects the most informative one according
to the learning function, evaluates the expensive model there, and refits the
Gaussian process.

## Himmelblau's Function

As in the (non-adaptive) GP example, we consider the Himmelblau function in ``x1, x2 ∈ [-5, 5]``
as a test function.
===#

#md using UncertaintyQuantification # hide
#md using Plots # hide
#md using DataFrames # hide
#md using Optim # hide

#jl using UncertaintyQuantification
#jl using Plots
#jl using DataFrames
#jl using Optim # hide

#===
First, define the probabilistic input and the expensive model to approximate.
===#

x = RandomVariable.(Uniform(-5, 5), [:x1, :x2])
himmelblau = Model(
df -> (df.x1 .^ 2 .+ df.x2 .- 11) .^ 2 .+ (df.x1 .+ df.x2 .^ 2 .- 7) .^ 2, :y
)
#md nothing # hide

#===
We start with the same initial Gaussian process surrogate as in the *regular* GP regression
example. Hence, we use the same initial design and same optimizer.
===#

design = LatinHypercubeSampling(80)
mean_f = ConstMean(0.0)
kernel = SqExponentialKernel()

gp_prior = GP(mean_f, kernel)
input_transform = ZScoreTransformChoice()
optimizer = MaximumLikelihoodEstimation(Optim.Adam(alpha = 0.005), Optim.Options(; iterations = 10, show_trace = false))

initial_gp = GaussianProcess(
gp_prior,
x,
himmelblau,
:y;
experimental_design = design,
input_transform = input_transform,
optimizer = optimizer
)
#md nothing # hide

#===
Next, we update the initial GP using a selected learning function and a set number of
additional points used to refine the initial GP. We use the [`MaximinDistance`](@ref)
acquisition function and select `20` additional points.
===#

learning_function = MaximinDistance()
n_added_points = 20
#md nothing # hide

#===
We refine the GP using [`AdaptiveGaussianProcess`](@ref) which we pass our initial GP, the
`learning_function` and `n_added_points`.
===#

adaptive_gp = AdaptiveGaussianProcess(
deepcopy(initial_gp),
x,
himmelblau,
learning_function,
n_added_points;
optimizer = optimizer
)
#md nothing # hide

#===
To assess the fitted surrogate, we compute the MSE between GP mean and the reference model.
We compare the MSE of the initial GP and the refined GP.

We start with the initial GP:
===#

test_data = sample(x, LatinHypercubeSampling(1000))
test_data_adaptive = deepcopy(test_data)
evaluate!(initial_gp, test_data; mode = :mean)
evaluate!(himmelblau, test_data)

mse = mean((test_data.y .- test_data.y_mean) .^ 2)
println("MSE (initial GP): $mse")

# Then, we also evaluate the adaptively refined GP at the same test set:
evaluate!(adaptive_gp, test_data_adaptive; mode = :mean)
evaluate!(himmelblau, test_data_adaptive)

mse_adap = mean((test_data_adaptive.y .- test_data_adaptive.y_mean) .^ 2)
println("MSE (adaptive GP): $mse_adap")
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ makedocs(;
"Basis Functions" => "api/basisfunctions.md",
"ResponseSurface" => "api/responsesurface.md",
"PolyharmonicSpline" => "api/polyharmonicspline.md",
"Gaussian Processes" => "api/gaussianprocesses.md",
"Simulations" => "api/simulations.md",
"Bayesian Updating" => "api/bayesianupdating.md",
"Transport Maps" => "api/transportmaps.md",
Expand Down
Loading
Loading