Choosing Summary Metrics
The choice of distance measure in the storm summary space is not always obvious. One way to choose is to pick some parametric distance (e.g. weighted Euclidean distance) and then choose the parameters by try to optimise for the performance of the simulated traces.
If we have a score for the similarity of two traces, we can try to minimise the expected score of the simulated traces against the true historical traces.
To do this, use
HistoricalStormTraceSimulation.find_best_distance — Functionfind_best_distance(D::Type{<:Metric},x₀,history; lowerbounds, upperbounds, optim_kwargs=(), kwargs...)Use optim to find the best distance based on score_method scoring.
Arguments:
Dthe type of distance (e.g. WeightedEuclidean). Note this is the constructor for the type, not an instance!x₀initial parameters for the distance to start optimisation.historythe storm history.lowerboundsthe lower bounds for the optimisation, defaults tofill(-Inf,length(x₀)).upperboundsthe upper bounds for the optimisation, defaults tofill(Inf,length(x₀)).optim_kwargs: Key word arguments to be passed to Optim.kwargsadditional key word arguments, similar toscore_method, but not includingsummarymetric, as this is specified by the optimisation.
Note:
To use WeightedPeriodicEuclidean, you first need to select the periods p, and then create a constructor to fix these, e.g.
julia> myperiods = [Inf,Inf,360.0]
3-element Vector{Float64}:
Inf
Inf
360.0
julia> myperiodicdistance(w) = WeightedPeriodicEuclidean(myperiods,w)
myperiodicdistance (generic function with 1 method)Then pass myperiodicdistance as the argument D to find_best_distance.
HistoricalStormTraceSimulation.expected_score — Functionexpected_score(history::StormHistory; samplemethod=1:50, rescalemethod, summarymetric::Metric=Euclidean(), interpolation_method=LinearInterpolation, tracescore::TraceScore)Compute the expected score.
Arguments:
history,samplemethod,rescalemethod,summarymetric,interpolation_method: seesampletraces.tracescore: Score for comparing traces.
HistoricalStormTraceSimulation.conditional_expected_score — Functionconditional_expected_score(summary,trace,history,sampler,rescalemethod,interpolation_method,tracescore)Compute the conditional expected score of a given historical trace. A different method will be used if the trace sampler uses a uniform over the closest m points method (i.e. if the sampler has a UnitRange for its samplemethod).
Arguments
summary: The summary of a historical trace.trace: The corresponding trace.sampler: ATraceSampler.history,rescalemethod,interpolation_method: seesampletracestracescore: Score for comparing traces.
Trace Scoring
Trace scores can be specified as a subtype of TraceScore. A functor should then be defined taking in two traces, which returns a measure of similarity between the two, with 0 being identical.
Provided is MarginalTraceScore which allows the user to define weighted sums of scores (usually metrics) applied to each variable.
HistoricalStormTraceSimulation.MarginalTraceScore — TypeMarginalTraceScore(metrics::NTuple{N,Metric},weights=ones(length(metrics)))Construct a scoring method for traces based on a weighted some of marginal metrics.
Arguments
metrics: Should be a tuple ofpmetrics, wherepis the number of variables in the trace of interest (not including time).weights: A vector of weights to be used (defaults to vector of ones).
Use
Given a MarginalTraceScore called mscore.
(mscore::MarginalTraceScore)(t1::StormTrace,t2::StormTrace)
will compute the marginal trace score between two traces t1 and t2.
Convenience functions for checking compatibility are also provided:
HistoricalStormTraceSimulation.checkcompatible — Functioncheckcompatible(m::MarginalTraceScore,t::StormTrace)Check trace is compatible with MarginalTraceScore.
checkcompatible(t1::StormTrace,t2::StormTrace)Check two traces are compatible.
Implementing new trace scores
New methods can be implemented by analogy to the implementation for MarginalTraceScore:
struct MarginalTraceScore{T,S} <: TraceScore
metrics::T
weights::S
function MarginalTraceScore(metrics::NTuple{N,Metric},weights=ones(length(metrics))) where {N}
length(metrics) == length(weights) || throw(DimensionMismatch("weights and metrics should be same length."))
new{typeof(metrics),typeof(weights)}(metrics,weights)
end
end
function (mscore::MarginalTraceScore)(t1::StormTrace,t2::StormTrace)
checkcompatible(t1,t2)
checkcompatible(mscore,t1)
score = 0.0
for i in eachindex(mscore.metrics)
@views score += mscore.weights[i]*mscore.metrics[i](t1.value[:,i],t2.value[:,i])
end
return score
endPeriodic trace scores
If one of the marginal traces should be periodic, use the following metric as opposed to PeriodicEuclidean, as that will only work for arrays of a fixed size.
HistoricalStormTraceSimulation.SinglePeriodicEuclidean — TypeSinglePeriodicEuclidean(p)Create a weighted Euclidean metric on a rectangular periodic domain where all dimensions have the same period.
Based on the PeriodicEuclidean from Distances.jl. The provided period p should be scalar.