CliMA / CliMA/EnsembleKalmanProcesses.jl

Named tuples for parameters

Open
#42 9 comments 0 reactions 0 assignees View on GitHub
Dominant language
Julia
Stars
125
Forks
24
Avg merge
1d 18h
Merged PRs (30d)
5

Description

For applications with large numbers of parameters input into complex models, it's useful (even necessary) to use objects like `NamedTuple` that associate parameter names with values to hold / transport lists of parameters.

However, as far as I can tell, parameters are constrained to be vectors. Throughout the code in fact, many data structures seem constrained to `Array` or `Vector`. Eg, this code does not work:

```julia
using Distributions
using LinearAlgebra
using Random

using EnsembleKalmanProcesses.EnsembleKalmanProcessModule
using EnsembleKalmanProcesses.ParameterDistributionStorage
using EnsembleKalmanProcesses.EnsembleKalmanProcessModule: EnsembleKalmanProcess, construct_initial_ensemble

rng_seed = 41
Random.seed!(rng_seed)

# The system
θ★ = (a=1, b=-1)
G₁(θ) = [sqrt((θ.a - θ★.a)^2 + (θ.b - θ★.b)^2)]

# Hyperparameters
N_ensemble = 50
noise_level = 1e-3

unconstrained_prior_distributions = (a=Parameterized(Normal(0, 1)), b=Parameterized(Normal(0, 1)))
constraints = (a=no_constraint(), b=no_constraint())
parameter_names = ("a", "b")

prior = ParameterDistribution(unconstrained_prior_distributions, constraints, parameter_names)
```

and I get

```julia
julia> prior = ParameterDistribution(unconstrained_prior_distributions, constraints, ["a", "b"])
ERROR: MethodError: no method matching ParameterDistribution(::NamedTuple{(:a, :b), Tuple{Parameterized, Parameterized}}, ::NamedTuple{(:a, :b), Tuple{Constraint, Constraint}}, ::Vector{String})
```

Is it necessary to constrain parameters to type `Vector`? It seems like it should be possible to generically support any iterable object (or objects that support broadcasting?) In the case that we need to perform `LinearAlgebra` operations, we can constructor the appropriate matrices or vectors from iterable containers as needed:

```julia
julia> parameters = (a=1, b=2)
(a = 1, b = 2)

julia> parameter_vector =[θ for θ in parameters]
2-element Vector{Int64}:
1
2
```

Allocations could even be minimized, though I think this is usually unnecessary because typical applications of `EnsembleKalmanProcesses.jl` have computations _dominated_ by the cost of evaluating a loss function.

I'm happy to get to work on refactoring the internals to support more general parameter containers if someone can identify the minimal requirements for the parameters object. It's tough to figure out what methods would have to be defined without detailed knowledge of the code because the `struct` definitions are over-constrained, preventing experimentation.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start at the ParameterDistribution constructor and inspect the Array or Vector constraints in EnsembleKalmanProcessModule and ParameterDistributionStorage. Identify the minimal parameter-container requirements, then verify that the NamedTuple example can construct a prior without breaking existing parameter operations.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.