Variable Fidelity Surrogate Tutorial
With the variable fidelity surrogate, we can specify two different surrogates: one for high-fidelity data and one for low-fidelity data. By default, the first half of the samples are considered high-fidelity and the second half low-fidelity.
The model is a sum of two parts. The low-fidelity surrogate is fitted to the cheap samples, and a correction surrogate is then fitted to the residuals the low-fidelity surrogate leaves at the expensive samples:
\[\hat f(x) = \hat f_{\text{low}}(x) + \hat\varepsilon(x), \qquad \hat\varepsilon \text{ fitted to } y_{\text{high}} - \hat f_{\text{low}}(x_{\text{high}})\]
so the sum reproduces the high-fidelity data exactly, whatever the low-fidelity surrogate does with it. The split is positional: x must be ordered with the high-fidelity samples first, and num_high_fidel says how many there are. It must leave at least one sample on each side.
update! adds low-fidelity samples. It refits the correction surrogate as well, since changing the low-fidelity surrogate changes the residuals the correction was fitted to.
Any of the *Structure descriptors may be used for either level — RadialBasisStructure, KrigingStructure, LinearStructure, InverseDistanceStructure, LobachevskyStructure, NeuralStructure, XGBoostStructure, SecondOrderPolynomialStructure and WendlandStructure. GEKStructure is not supported: GEK needs gradient observations alongside its function values, and a variable-fidelity design carries only function values.
Surrogates.VariableFidelitySurrogate — Type
VariableFidelitySurrogate(x, y, lb, ub; num_high_fidel = floor(Int, length(x) / 2),
low_fid_structure = RadialBasisStructure(...),
high_fid_structure = RadialBasisStructure(...))Surrogate that combines low-fidelity observations with a correction surrogate fit to the high-fidelity residuals.
The first num_high_fidel samples are treated as high-fidelity data. The remaining samples are treated as low-fidelity data. Evaluation returns the sum of the fitted low-fidelity surrogate and the high-fidelity residual surrogate.
Fields
x: all training inputs.y: all training responses.lb: lower bound of the input domain.ub: upper bound of the input domain.num_high_fidel: number of leading samples treated as high fidelity.low_fid_surr: surrogate fitted to low-fidelity data.eps_surr: surrogate fitted to high-fidelity residuals.eps_structure: the configurationeps_surrwas built from, kept so thatupdate!can refit it against the corrected residuals.
Arguments
x: sample locations, ordered with high-fidelity samples first.y: observed values corresponding tox.lb: lower bound of the input domain.ub: upper bound of the input domain.
Keywords
num_high_fidel: number of leading samples treated as high fidelity. It must leave at least one sample on each side of the split.low_fid_structure: named-tuple surrogate configuration for low-fidelity data.high_fid_structure: named-tuple surrogate configuration for the residual model.
Returns
A VariableFidelitySurrogate satisfying the generic surrogate interface.
using Surrogates
using Plotsn = 100
lower_bound = 1.0
upper_bound = 6.0
x = sample(n, lower_bound, upper_bound, SobolSample())
f = x -> 1 / 3 * x
y = f.(x)
plot(x, y, seriestype = :scatter, label = "Sampled points",
xlims = (lower_bound, upper_bound), legend = :top)
plot!(f, label = "True function", xlims = (lower_bound, upper_bound), legend = :top)varfid = VariableFidelitySurrogate(x, y, lower_bound, upper_bound)(::VariableFidelitySurrogate{Vector{Float64}, Vector{Float64}, Float64, Float64, Int64, RadialBasis{Surrogates.var"#linearRadial##0#linearRadial##1", Int64, Vector{Float64}, Vector{Float64}, Float64, Float64, LinearAlgebra.Transpose{Float64, Vector{Float64}}, Float64, Bool, Float64}, RadialBasis{Surrogates.var"#cubicRadial##0#cubicRadial##1", Int64, Vector{Float64}, Vector{Float64}, Float64, Float64, LinearAlgebra.Transpose{Float64, Vector{Float64}}, Float64, Bool, Float64}, @NamedTuple{name::String, type::UnionAll, radial_function::Surrogates.RadialFunction{Int64, Surrogates.var"#cubicRadial##0#cubicRadial##1"}, scale_factor::Float64, sparse::Bool}}) (generic function with 1 method)plot(x, y, seriestype = :scatter, label = "Sampled points",
xlims = (lower_bound, upper_bound), legend = :top)
plot!(f, label = "True function", xlims = (lower_bound, upper_bound), legend = :top)
plot!(
varfid, label = "Surrogate function", xlims = (lower_bound, upper_bound), legend = :top)