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 configuration eps_surr was built from, kept so that update! can refit it against the corrected residuals.

Arguments

  • x: sample locations, ordered with high-fidelity samples first.
  • y: observed values corresponding to x.
  • 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.

source
using Surrogates
using Plots
n = 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)
Example block output
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)
Example block output