-
Notifications
You must be signed in to change notification settings - Fork 13
Gaussian processes #245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
felixmett
wants to merge
131
commits into
JuliaUQ:master
Choose a base branch
from
felixmett:gaussian-processes
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Gaussian processes #245
Changes from all commits
Commits
Show all changes
131 commits
Select commit
Hold shift + click to select a range
5936e54
using AbstractGPs
felixmett f75b5a5
GaussianProcessRegressor struct
felixmett ac83936
Using GaussianProcesses
felixmett cf0be3d
TODO: Proper normalization scheme
felixmett edcb05c
Merge branch 'FriesischScott:master' into gaussian-processes
felixmett 965a847
Imports necessary for gps
5a85023
Merge branch 'gaussian-processes' of https://github.com/Cr0gan/Uncert…
7207f4c
Testing file, delete later
c37df3e
Split gp fit and hyperparameter optimization
131cfa4
Additional packages for gaussian-processes
f21cdd5
StatsBase normalization and Optimizer struct
felixmett fdca54c
Optimizer in gp function, implement evaluate method
felixmett 8db025f
Gaussianprocess from input, model and output
felixmett 88777e5
Removed input normalization where UQInput is given
felixmett 5eadb18
Ignoring sample method for now
felixmett ec975e4
Suggestion for naming of normalize
felixmett 67b0731
Merge branch 'master' of https://github.com/FriesischScott/Uncertaint…
felixmett b5be7a4
Merge branch 'gaussian-processes' of https://github.com/Cr0gan/Uncert…
felixmett b62b021
Accepted incoming changes
felixmett 43a5312
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett efcc4fa
Remove dependecies on GaussianProcesses.jl
felixmett d63cde9
First working version
felixmett bfd10d7
Moved gaussianprocesses in subdirectory
felixmett abac806
Demonstration of how to use current version of gps
felixmett a3df9f7
Preliminary demo files
felixmett 1a5304d
Current state of gp implementation
felixmett 11d1ddd
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett a34afa9
Added packages AbstractGPs, ParameterHandling and Zygote
felixmett cc4fd8f
added constructors for every input case
felixmett 57625a8
added function _handle_gp_input for AbstractGPs interface
felixmett a24aa98
added evaluate! method for gaussianprocesses
felixmett 9399cb9
added a demo file for gps
felixmett 8abd2cb
added a convenience method to get the name of a single UQInput
felixmett dc014ea
current version that works for univariate in- and output
felixmett d6e52d2
added includes and exports for gps
felixmett 0dd38ed
using only instead of X[1]
felixmett 270a9ce
transform copy of DataFrame to handle 1D case
felixmett 5f9a8cd
started adding unit tests
felixmett 0d6cc64
Merge branch 'FriesischScott:master' into gaussian-processes
felixmett 895949d
Automatically extract parameters from GP model
felixmett 3ae037f
Normalization of in- and outputs
felixmett c0be0ff
Cleaned up hyperparameter optimization
felixmett 33b1782
Started restructuring GaussianProcess constructors
felixmett fb9e15a
Moved normalization to other file
felixmett db0202d
Store in- and output standardization in single struct
felixmett 95ee9c9
Simple demo of current state
felixmett 19c8f42
Added gaussian process exports
felixmett 0a9cdf9
Refactoring
felixmett 8d59344
Simplified optimization routine for NoOptimization
felixmett 96efb04
Added parameter routines for ARDTransform
felixmett ca876d8
Added constructors and evaluate
felixmett 52fdee8
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett 9e6f205
Merge branch 'master' into gaussian-processes
FriesischScott 351ad0b
Merge branch 'master' into gaussian-processes
FriesischScott 94a4a55
Merge branch 'master' into gaussian-processes
FriesischScott cfe0d65
Merge branch 'master' into gaussian-processes
FriesischScott dab9478
Merge branch 'master' of https://github.com/FriesischScott/Uncertaint…
felixmett 867fdbc
Added compat entries for AbstractGPs and Zygote
felixmett faf254e
Redesigned data standardization
felixmett 1b373d2
Added DifferentiationInterface and compat entries
felixmett 39f2a53
Using ParameterHandling for gaussian processes
felixmett 7406036
Refactoring of type II maximum likelihood estimation
felixmett a61da82
Added input and output transforms to gaussian process struct
felixmett 3bfd29e
Preliminary file to test parameter extraction
felixmett a853620
Add more kernels and transforms for automatic parameter handling
felixmett b27131a
Minimize documentation overhead
felixmett 5c78fc6
Add DataTransforms for in- and output transformation
felixmett bc77331
Change to single DataTransforms struct to handle transformations
felixmett f5c4033
Export all datatransformations for gaussian processes
felixmett 337b326
Add types of inputs
felixmett 3d7de71
Preliminary demo
felixmett 548cd52
Refactor data standardization pipeline
felixmett 027db46
Refactor data standardization pipeline
felixmett b3feed3
Preliminary test for refactored data standardization
felixmett 48758d0
Preliminary unit test for data standardization
felixmett 581f110
Add inverse output transform for gp posterior variance
felixmett a984293
Add var! and mean_and_var! methods for gps
felixmett 0a7ec3c
Fix wrongly returned output transforms
felixmett 8e9f339
Preliminary tests
felixmett 55a0832
Add AbstractGPs to tests
felixmett 6196775
Add unit tests for gp data standardization
felixmett f77e7b1
Add gaussian process regression reference
felixmett 8137f0b
Add theoretical background documentation for gaussian process regression
felixmett 109dc59
Add export NoHyperparameterOptimization
felixmett 6fc01d1
Refactor NoHyperparameterOptimization
felixmett 1c4bfb6
Add tests for GaussianProcess construction
felixmett 531b25a
Preliminary test files
felixmett 6bc6ead
Preliminary idea to test parameter extraction implementation
felixmett 9f264ae
Preliminary commit
felixmett d0880a9
Add extract and apply method for unsupported kernels
felixmett 0871a3c
Add test to check improvement after hyperparameter optimization
felixmett 9bf53e5
Add test to check implementation for all kernels, transforms and mean…
felixmett 42db9da
Refactor data standardization tests
felixmett 1e71f29
Add complete test set for gaussian process regression constructors
felixmett 21117c1
Refactor gaussian process hyperparameter optimization tests
felixmett e4ab211
Preliminary example
felixmett c892a43
Add documentation for exported structs
felixmett 5c25292
Add documentation
felixmett 6369de1
Add developer note
felixmett 5feb38c
Add documentation and developer note
felixmett 76bdc2c
Update DifferentiationInterface
felixmett a40bbd3
Refactor gaussian process evaluate!
felixmett ee0ab23
Fix only RandomVariables are used as gaussian process input
felixmett c92db59
Fix wrongful discarding of deterministic inputs
felixmett 9118cf4
Preliminary examples
felixmett 132145d
Current state of documentation
felixmett 5e7a745
Current state of docs
felixmett 3a1906b
Finish gaussian process documentation
felixmett 7896712
Delete preliminary testing files
felixmett 3679ee0
Fix gaussian process output name for mode :mean
felixmett ca8df9d
Add literate example for gaussian process regression
felixmett d0b3749
Delete unused exports
felixmett 1fc82ee
Add execution of gaussian process tests
felixmett 532ca08
Merge remote-tracking branch 'upstream/master' into gaussian-processes
felixmett b5369ff
Reexport AbstractGPs
felixmett a7f44ce
Fix docstrings
felixmett 70ef0fc
Fix docstrings
felixmett 61322a3
Fix documentation dependencies and loaded modules
felixmett a02af1d
Fix type of posterior gp in GaussianProcess
felixmett 13179d1
Add literate demo file
felixmett 11667f2
Fix bug where single UQInput is not filtered for random inputs
felixmett 4e4c19d
Fix docstring does not require using AbstractGP
felixmett 8fbc8a8
Add gaussian processes api
felixmett 9982b84
Fix typo in gaussian process literate demo
felixmett 697cb54
Fix jldoctest error
felixmett d4b796a
Change github username of Felix
felixmett aae5b9d
Add missing docs
felixmett 1962e22
Refactor example code blocks
felixmett 8450250
Fix unresolved reference in docstring
felixmett 703425d
Refactor internal docs to comments
felixmett b9a8ddd
Fix faulty indent and linting errors
felixmett File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| 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() ∘ ARDTransform([1.0, 1.0]) | ||
| σ² = 1e-5 | ||
|
|
||
| gp_prior = with_gaussian_noise(GP(mean_f, kernel), σ²) | ||
|
|
||
| using Optim | ||
|
|
||
| optimizer = MaximumLikelihoodEstimation(Optim.Adam(alpha=0.005), Optim.Options(; iterations=10, show_trace=false)) | ||
|
|
||
| input_transform = ZScoreTransform() | ||
|
|
||
| gp_model = GaussianProcess( | ||
| gp_prior, | ||
| x, | ||
| himmelblau, | ||
| :y, | ||
| design; | ||
| input_transform=input_transform, | ||
| optimization=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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| #=== | ||
| # 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. | ||
| ``` | ||
| ===# | ||
| #  | ||
| #=== | ||
| Aanalogue 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 | ||
| ) | ||
|
|
||
| #=== | ||
| 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() ∘ ARDTransform([1.0, 1.0]) | ||
| σ² = 1e-5 | ||
|
|
||
| gp_prior = with_gaussian_noise(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)) | ||
|
|
||
| #=== | ||
| 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 = ZScoreTransform() | ||
|
|
||
| #=== | ||
| 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 transforms as well as the hyperparameter optimization method. | ||
| The construction then samples the experimental design, evaluates the model at the sampled points, standardizes the input and output data, optimizes the hyperparameters of the GP, and constructs the posterior GP. | ||
| ===# | ||
| #md using Random #hide | ||
| #md Random.seed!(42) #hide | ||
|
|
||
| gp_model = GaussianProcess( | ||
| gp_prior, | ||
| x, | ||
| himmelblau, | ||
| :y, | ||
| design; | ||
| input_transform=input_transform, | ||
| optimization=optimizer | ||
| ) | ||
|
|
||
| #=== | ||
| 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 | ||
|
|
||
| #  | ||
|
|
||
| #=== | ||
| 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. | ||
| ===# | ||
|
|
||
| #  | ||
|
|
||
| #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") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Gaussian Process Regression | ||
|
|
||
| Methods for Gaussian process regression. | ||
|
|
||
| ## Index | ||
|
|
||
| ```@index | ||
| Pages = ["gaussianprocesses.md"] | ||
| ``` | ||
|
|
||
| ## Types | ||
|
|
||
| ```@docs | ||
| GaussianProcess | ||
| NoHyperparameterOptimization | ||
| MaximumLikelihoodEstimation | ||
| IdentityTransform | ||
| ZScoreTransform | ||
| UnitRangeTransform | ||
| StandardNormalTransform | ||
| ``` | ||
|
|
||
| ## Functions | ||
|
|
||
| ```@docs | ||
| evaluate!(gp::GaussianProcess, data::DataFrame; mode::Symbol = :mean, n_samples::Int = 1) | ||
| with_gaussian_noise(gp::AbstractGPs.GP, σ²::Real) | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.