Skip to content

Commit 709ca99

Browse files
committed
Update Emulator and tests
1 parent 51dadb7 commit 709ca99

14 files changed

Lines changed: 141 additions & 167 deletions

File tree

docs/src/API/GaussianProcess.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ GaussianProcess(
1515
::FT,
1616
::PredictionType,
1717
) where {GPPkg <: GaussianProcessesPackage, K <: GaussianProcesses.Kernel, KPy <: PyObject, AK <:AbstractGPs.Kernel, FT <: AbstractFloat}
18-
build_models!(::GaussianProcess{GPJL}, ::PairedDataContainer{FT}, input_structure_matrix, output_structure_matrix) where {FT <: AbstractFloat}
18+
build_models!(::GaussianProcess{GPJL}, ::PairedDataContainer{FT}, input_structure_mats, output_structure_mats) where {FT <: AbstractFloat}
1919
optimize_hyperparameters!(::GaussianProcess{GPJL})
2020
predict(::GaussianProcess{GPJL}, ::AbstractMatrix{FT}) where {FT <: AbstractFloat}
2121
```

docs/src/API/RandomFeatures.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ build_default_prior
2222
```@docs
2323
ScalarRandomFeatureInterface
2424
ScalarRandomFeatureInterface(::Int,::Int)
25-
build_models!(::ScalarRandomFeatureInterface, ::PairedDataContainer{FT}, input_structure_matrix, output_structure_matrix) where {FT <: AbstractFloat}
25+
build_models!(::ScalarRandomFeatureInterface, ::PairedDataContainer{FT}, input_structure_mats, output_structure_mats) where {FT <: AbstractFloat}
2626
predict(::ScalarRandomFeatureInterface, ::M) where {M <: AbstractMatrix}
2727
```
2828

@@ -31,7 +31,7 @@ predict(::ScalarRandomFeatureInterface, ::M) where {M <: AbstractMatrix}
3131
```@docs
3232
VectorRandomFeatureInterface
3333
VectorRandomFeatureInterface(::Int, ::Int, ::Int)
34-
build_models!(::VectorRandomFeatureInterface, ::PairedDataContainer{FT}, input_structure_matrix, output_structure_matrix) where {FT <: AbstractFloat}
34+
build_models!(::VectorRandomFeatureInterface, ::PairedDataContainer{FT}, input_structure_mats, output_structure_mats) where {FT <: AbstractFloat}
3535
predict(::VectorRandomFeatureInterface, ::M) where {M <: AbstractMatrix}
3636
```
3737

docs/src/emulate.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Developers may contribute new tools by performing the following
4444
2. Create a struct `MyMLTool <: MachineLearningTool`, containing any arguments or optimizer options
4545
3. Create the following three methods to build, train, and predict with your tool (use `GaussianProcess.jl` as a guide)
4646
```
47-
build_models!(mlt::MyMLTool, iopairs::PairedDataContainer) -> Nothing
47+
build_models!(mlt::MyMLTool, iopairs::PairedDataContainer, input_structure_mats::Dict{Symbol, <:StructureMatrix}, output_structure_mats::Dict{Symbol, <:StructureMatrix}) -> Nothing
4848
optimize_hyperparameters!(mlt::MyMLTool, args...; kwargs...) -> Nothing
4949
function predict(mlt::MyMLTool, new_inputs::Matrix; kwargs...) -> Matrix, Union{Matrix, Array{,3}
5050
```

examples/Sinusoid/emulate.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ gauss_proc = Emulators.GaussianProcess(gppackage, noise_learn = false)
7575
encoder_schedule = [(decorrelate_sample_cov(), "in"), (decorrelate_structure_mat(), "out")]
7676

7777
# Build emulator with data
78-
emulator_gp = Emulator(gauss_proc, input_output_pairs, output_structure_matrix = Γ, encoder_schedule = encoder_schedule)
78+
emulator_gp = Emulator(gauss_proc, input_output_pairs, (obs_cov_noise = Γ,); encoder_schedule)
7979
optimize_hyperparameters!(emulator_gp)
8080

8181
# We have built the Gaussian process emulator and we can now use it for prediction. We will validate the emulator
@@ -113,7 +113,7 @@ random_features = VectorRandomFeatureInterface(
113113
)
114114
encoder_schedule_rf = [(decorrelate_sample_cov(), "in"), (decorrelate_structure_mat(), "out")]
115115
emulator_random_features =
116-
Emulator(random_features, input_output_pairs, encoder_schedule = encoder_schedule_rf, output_structure_matrix = Γ)
116+
Emulator(random_features, input_output_pairs, (obs_cov_noise = Γ,); encoder_schedule = encoder_schedule_rf)
117117
optimize_hyperparameters!(emulator_random_features)
118118

119119

src/Emulator.jl

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ using Random
1717

1818
export Emulator
1919

20-
export calculate_normalization
2120
export build_models!
2221
export optimize_hyperparameters!
2322
export predict, encode_data, decode_data, encode_structure_matrix, decode_structure_matrix
@@ -41,7 +40,7 @@ include("RandomFeature.jl")
4140
function throw_define_mlt()
4241
throw(ErrorException("Unknown MachineLearningTool defined, please use a known implementation"))
4342
end
44-
function build_models!(mlt, iopairs, mlt_kwargs...)
43+
function build_models!(mlt, iopairs, input_structure_mats, output_structure_mats, mlt_kwargs...)
4544
throw_define_mlt()
4645
end
4746
function optimize_hyperparameters!(mlt)
@@ -109,71 +108,60 @@ Constructor of the Emulator object,
109108
Positional Arguments
110109
- `machine_learning_tool`: the selected machine learning tool object (e.g. Gaussian process / Random feature interface)
111110
- `input_output_pairs`: the paired input-output data points stored in a `PairedDataContainer`
111+
- `encoder_kwargs`[=`NamedTuple()`]: a Dict or NamedTuple with keyword arguments to be passed to `initialize_and_encode_with_schedule!`
112112
113113
Keyword Arguments
114-
- `encoder_schedule`[=`nothing`]: the schedule of data encoding/decoding. This will be passed into the method `create_encoder_schedule` internally. `nothing` sets sets a default schedule `(decorrelate_samples_cov(), "in_and_out")`. Pass `[]` for no encoding.
115-
- `input_structure_matrix`[=`nothing`]: Some encoders make use of an input structure (e.g., the prior covariance matrix). Particularly useful for few samples.
116-
- `output_structure_matrix` [=`nothing`] Some encoders make use of an input structure (e.g., the prior covariance matrix). Particularly useful for few samples.
114+
- `encoder_schedule`[=`nothing`]: the schedule of data encoding/decoding. This will be passed into the method `create_encoder_schedule` internally. `nothing` sets sets a default schedule `[(decorrelate_sample_cov(), "in_and_out")]`, or `[(decorrelate_sample_cov(), "in"), (decorrelate_structure_mat(), "out")]` if an `encoder_kwargs` has a key `:obs_noise_cov`. Pass `[]` for no encoding.
117115
Other keywords are passed to the machine learning tool initialization
118116
"""
119117
function Emulator(
120118
machine_learning_tool::MachineLearningTool,
121-
input_output_pairs::PairedDataContainer{FT};
119+
input_output_pairs::PairedDataContainer{FT},
120+
encoder_kwargs = NamedTuple();
122121
encoder_schedule = nothing,
123-
input_structure_matrix::Union{AbstractMatrix{FT}, UniformScaling{FT}, Nothing} = nothing,
124-
output_structure_matrix::Union{AbstractMatrix{FT}, UniformScaling{FT}, Nothing} = nothing,
125-
obs_noise_cov = nothing, # temporary
122+
obs_noise_cov = nothing, # temporary
126123
mlt_kwargs...,
127124
) where {FT <: AbstractFloat}
128125

129-
# For Consistency checks
130-
input_dim, output_dim = size(input_output_pairs, 1)
131-
132-
if !isnothing(obs_noise_cov) && isnothing(output_structure_matrix)
133-
@warn(
134-
"Keyword `obs_noise_cov=` is now deprecated, and replaced with `output_structure_matrix`. \n Continuing by setting `output_structure_matrix=obs_noise_cov`."
135-
)
136-
output_structure_matrix = obs_noise_cov
137-
elseif !isnothing(obs_noise_cov) && !isnothing(output_structure_matrix)
138-
@warn(
139-
"Keyword `obs_noise_cov=` is now deprecated and will be ignored. \n Continuing with value of `output_structure_matrix=`"
140-
)
126+
if !isnothing(obs_noise_cov)
127+
if haskey(encoder_kwargs, :obs_noise_cov)
128+
@warn "Keyword argument `obs_noise_cov=` is deprecated and will be ignored in favor of `encoder_kwargs[:obs_noise_cov]`."
129+
else
130+
@warn "Keyword argument `obs_noise_cov=` is deprecated. Please use `encoder_kwargs[:obs_noise_cov]` instead."
131+
end
141132
end
142133

143134
# [1.] Initializes and performs data encoding schedule
144135
# Default processing: decorrelate_sample_cov() where no structure matrix provided, and decorrelate_structure_mat() where provided.
145136
if isnothing(encoder_schedule)
146137
encoder_schedule = []
147-
if isnothing(input_structure_matrix)
148-
push!(encoder_schedule, (decorrelate_sample_cov(), "in"))
138+
139+
push!(encoder_schedule, (decorrelate_sample_cov(), "in"))
140+
if haskey(encoder_kwargs, :obs_noise_cov) || !isnothing(obs_noise_cov)
141+
push!(encoder_schedule, (decorrelate_structure_mat(), "out"))
149142
else
150-
push!(encoder_schedule, (decorrelate_structure_mat(), "in"))
151-
end
152-
if isnothing(output_structure_matrix)
153143
push!(encoder_schedule, (decorrelate_sample_cov(), "out"))
154-
else
155-
push!(encoder_schedule, (decorrelate_structure_mat(), "out"))
156144
end
157145
end
158146

159-
enc_schedule = create_encoder_schedule(encoder_schedule)
160-
(encoded_io_pairs, encoded_input_structure_matrix, encoded_output_structure_matrix) =
147+
encoder_schedule = create_encoder_schedule(encoder_schedule)
148+
(encoded_io_pairs, input_structure_mats, output_structure_mats, _, _) =
161149
initialize_and_encode_with_schedule!(
162-
enc_schedule,
163-
input_output_pairs,
164-
input_structure_matrix,
165-
output_structure_matrix,
150+
encoder_schedule,
151+
input_output_pairs;
152+
obs_noise_cov,
153+
encoder_kwargs...,
166154
)
167155

168156
# build the machine learning tool in the encoded space
169157
build_models!(
170158
machine_learning_tool,
171159
encoded_io_pairs,
172-
encoded_input_structure_matrix,
173-
encoded_output_structure_matrix;
160+
input_structure_mats,
161+
output_structure_mats;
174162
mlt_kwargs...,
175163
)
176-
return Emulator{FT, typeof(enc_schedule)}(machine_learning_tool, input_output_pairs, encoded_io_pairs, enc_schedule)
164+
return Emulator{FT, typeof(encoder_schedule)}(machine_learning_tool, input_output_pairs, encoded_io_pairs, encoder_schedule)
177165
end
178166

179167
"""
@@ -209,9 +197,9 @@ Encode a new structure matrix in the input space (`"in"`) or output space (`"out
209197
"""
210198
function encode_structure_matrix(
211199
emulator::Emulator,
212-
structure_mat::USorMorN,
200+
structure_mat::USorM,
213201
in_or_out::AS,
214-
) where {AS <: AbstractString, USorMorN <: Union{UniformScaling, AbstractMatrix, Nothing}}
202+
) where {AS <: AbstractString, USorM <: Union{UniformScaling, AbstractMatrix}}
215203
return encode_with_schedule(get_encoder_schedule(emulator), structure_mat, in_or_out)
216204
end
217205

@@ -240,9 +228,9 @@ Decode a new structure matrix in the input space (`"in"`) or output space (`"out
240228
"""
241229
function decode_structure_matrix(
242230
emulator::Emulator,
243-
structure_mat::USorMorN,
231+
structure_mat::USorM,
244232
in_or_out::AS,
245-
) where {AS <: AbstractString, USorMorN <: Union{UniformScaling, AbstractMatrix, Nothing}}
233+
) where {AS <: AbstractString, USorM <: Union{UniformScaling, AbstractMatrix}}
246234
return decode_with_schedule(get_encoder_schedule(emulator), structure_mat, in_or_out)
247235
end
248236

src/GaussianProcess.jl

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using EnsembleKalmanProcesses.DataContainers
33
using DocStringExtensions
44

5+
using ..Utilities: get_structure_mat
6+
57
# [1] For GaussianProcesses
68
import GaussianProcesses: predict, get_params, get_param_names
79
using GaussianProcesses
@@ -149,8 +151,8 @@ Method to build Gaussian process models based on the package.
149151
function build_models!(
150152
gp::GaussianProcess{GPJL},
151153
input_output_pairs::PairedDataContainer{FT},
152-
input_structure_matrix,
153-
output_structure_matrix;
154+
input_structure_mats,
155+
output_structure_mats;
154156
kwargs...,
155157
) where {FT <: AbstractFloat}
156158
# get inputs and outputs
@@ -191,12 +193,15 @@ function build_models!(
191193
println("Learning additive white noise")
192194
end
193195
# use the output_structure_matrix to scale regularization scale
194-
regularization = if isnothing(output_structure_matrix)
196+
regularization = if isempty(output_structure_mats)
195197
1.0 * ones(N_models)
196-
elseif isa(output_structure_matrix, UniformScaling)
197-
output_structure_matrix.λ * ones(N_models)
198198
else
199-
diag(output_structure_matrix)
199+
output_structure_mat = get_structure_mat(output_structure_mats)
200+
if isa(output_structure_mat, UniformScaling)
201+
output_structure_mat.λ * ones(N_models)
202+
else
203+
diag(output_structure_mat)
204+
end
200205
end
201206

202207
logstd_regularization_noise = log.(sqrt.(regularization .* gp.alg_reg_noise))
@@ -283,9 +288,8 @@ predict(gp::GaussianProcess{GPJL}, new_inputs::AbstractMatrix{FT}) where {FT <:
283288
function build_models!(
284289
gp::GaussianProcess{SKLJL},
285290
input_output_pairs::PairedDataContainer{FT},
286-
input_structure_matrix,
287-
output_structure_matrix;
288-
kwargs...,
291+
input_structure_mats,
292+
output_structure_mats,
289293
) where {FT <: AbstractFloat}
290294
# get inputs and outputs
291295
input_values = permutedims(get_inputs(input_output_pairs), (2, 1))
@@ -322,12 +326,15 @@ function build_models!(
322326
println("Learning additive white noise")
323327
end
324328
# use the output_structure_matrix to scale regularization scale
325-
regularization = if isnothing(output_structure_matrix)
329+
regularization = if isempty(output_structure_mats)
326330
1.0 * ones(N_models)
327-
elseif isa(output_structure_matrix, UniformScaling)
328-
output_structure_matrix.λ * ones(N_models)
329331
else
330-
diag(output_structure_matrix)
332+
output_structure_mat = get_structure_mat(output_structure_mats)
333+
if isa(output_structure_mat, UniformScaling)
334+
output_structure_mat.λ * ones(N_models)
335+
else
336+
diag(output_structure_mat)
337+
end
331338
end
332339
regularization_noise_vec = gp.alg_reg_noise .* regularization
333340
for i in 1:N_models
@@ -375,10 +382,9 @@ end
375382
function build_models!(
376383
gp::GaussianProcess{AGPJL},
377384
input_output_pairs::PairedDataContainer{FT},
378-
input_structure_matrix,
379-
output_structure_matrix;
385+
input_structure_mats,
386+
output_structure_mats;
380387
kernel_params = nothing,
381-
kwargs...,
382388
) where {FT <: AbstractFloat}
383389
# get inputs and outputs
384390
input_values = permutedims(get_inputs(input_output_pairs), (2, 1))
@@ -427,12 +433,15 @@ AbstractGP currently does not (yet) learn hyperparameters internally. The follow
427433

428434
N_models = size(output_values, 1) #size(transformed_data)[1]
429435
# use the output_structure_matrix to scale regularization scale
430-
regularization = if isnothing(output_structure_matrix)
436+
regularization = if isempty(output_structure_mats)
431437
1.0 * ones(N_models)
432-
elseif isa(output_structure_matrix, UniformScaling)
433-
output_structure_matrix.λ * ones(N_models)
434438
else
435-
diag(output_structure_matrix)
439+
output_structure_mat = get_structure_mat(output_structure_mats)
440+
if isa(output_structure_mat, UniformScaling)
441+
output_structure_mat.λ * ones(N_models)
442+
else
443+
diag(output_structure_mat)
444+
end
436445
end
437446
regularization_noise = gp.alg_reg_noise .* regularization
438447

src/ScalarRandomFeature.jl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,8 @@ Builds the random feature method from hyperparameters. We use cosine activation
319319
function build_models!(
320320
srfi::ScalarRandomFeatureInterface,
321321
input_output_pairs::PairedDataContainer{FT},
322-
input_structure_matrix,
323-
output_structure_matrix;
324-
kwargs...,
322+
input_structure_mats,
323+
output_structure_mats,
325324
) where {FT <: AbstractFloat}
326325

327326
# get inputs and outputs
@@ -385,12 +384,15 @@ function build_models!(
385384
end
386385
end
387386

388-
regularization = if isnothing(output_structure_matrix)
387+
regularization = if isempty(output_structure_mats)
389388
1.0 * I(n_rfms)
390-
elseif isa(output_structure_matrix, UniformScaling)
391-
output_structure_matrix
392389
else
393-
Diagonal(output_structure_matrix)
390+
output_structure_mat = get_structure_mat(output_structure_mats)
391+
if isa(output_structure_mat, UniformScaling)
392+
output_structure_mat
393+
else
394+
Diagonal(output_structure_mat)
395+
end
394396
end
395397

396398
@info (

0 commit comments

Comments
 (0)