> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Regularization

> Stabilise parameter fits with Gaussian priors using iws.priors and iws.stats distributions.

Regularization in `iws.DataFit` is expressed as **priors** on the fit parameters. Each prior pairs a parameter name with a distribution from `iws.stats`. For why regularization is needed and how to choose prior strengths, see the [Regularization Guide](/guide/data-fitting/regularization).

## Distributions

| Schema                                   | Use for                                                                                   |
| ---------------------------------------- | ----------------------------------------------------------------------------------------- |
| `iws.stats.Normal(mean=..., std=...)`    | Gaussian prior, additive scale                                                            |
| `iws.stats.LogNormal(mean=..., std=...)` | Strictly-positive parameter spanning orders of magnitude (e.g. solid-phase diffusivities) |
| `iws.stats.Uniform(lb=..., ub=...)`      | Hard support; equivalent to bounds with constant density                                  |
| `iws.stats.MultivariateNormal(...)`      | Correlated priors across multiple parameters                                              |

## A regularized fit

```python theme={null}
import pybamm
import ionworks_schema as iws
from ionworks import Ionworks

parameters = {
    "Positive particle diffusivity [m2.s-1]": iws.Parameter(
        "Positive particle diffusivity [m2.s-1]",
        initial_value=1e-14,
        bounds=(1e-16, 1e-12),
    ),
    "Negative particle diffusivity [m2.s-1]": iws.Parameter(
        "Negative particle diffusivity [m2.s-1]",
        initial_value=3e-14,
        bounds=(1e-16, 1e-12),
    ),
}

priors = {
    "Positive particle diffusivity [m2.s-1]": iws.priors.Prior(
        "Positive particle diffusivity [m2.s-1]",
        iws.stats.LogNormal(mean=-32.2, std=1.0),  # log-mean, log-std
    ),
    "Negative particle diffusivity [m2.s-1]": iws.priors.Prior(
        "Negative particle diffusivity [m2.s-1]",
        iws.stats.LogNormal(mean=-31.1, std=1.0),
    ),
}

fit = iws.DataFit(
    objectives={
        "1C": iws.objectives.CurrentDriven(
            data_input="file:.../1C.csv",
            options={"model": pybamm.lithium_ion.SPMe()},
        ),
    },
    parameters=parameters,
    priors=priors,
    optimizer=iws.optimizers.ScipyLeastSquares(),
)

pipeline = iws.Pipeline({"fit": fit})

client = Ionworks()
submission = client.pipeline.create(pipeline)
```

The `priors` dict adds a regularization term to the cost function so deviations from the prior mean are penalised in proportion to the prior's inverse variance.

## Attaching priors via `Parameter`

Priors can also be attached directly to a `Parameter` rather than passed as a separate dict — useful when the prior is intrinsic to that parameter:

```python theme={null}
diffusivity = iws.Parameter(
    "Positive particle diffusivity [m2.s-1]",
    initial_value=1e-14,
    bounds=(1e-16, 1e-12),
    prior=iws.stats.LogNormal(mean=-32.2, std=1.0),
)
```

## Dict-form priors

Schema configs can also be written as plain dicts — useful when a config is loaded from JSON or YAML. Two equivalent forms are accepted in the `priors` mapping:

```python theme={null}
# Flat form: distribution name as a string, params inline
priors = {
    "Positive particle diffusivity [m2.s-1]": {
        "distribution": "LogNormal",
        "mean": -32.2,
        "std": 1.0,
    },
}

# Nested form: distribution as its own dict
priors = {
    "Positive particle diffusivity [m2.s-1]": {
        "distribution": {"distribution": "LogNormal", "mean": -32.2, "std": 1.0},
        "regularizer_weight": 2.0,
    },
}
```

The mapping key is the authoritative parameter name. Any `name` embedded inside the prior dict is ignored — including when the parameter itself is literally named `"distribution"`.

## Strict validation

Priors, distributions, and samplers are validated against discriminated unions at submission time. This catches typos and stale configs before a run starts, rather than letting them surface as opaque runtime crashes.

Mistakes that are now rejected with a `ValidationError`:

* An unknown distribution name (e.g. `{"distribution": "Guassian", ...}`).
* A stray or misspelled key in a distribution, prior, or sampler config.
* A `type` discriminator that doesn't match the field (e.g. `{"type": "Penalty", ...}` placed under `priors`).
* A bare scalar or list passed where a prior, distribution, or sampler is expected.

The legacy `type` alias is still accepted in place of the `distribution` discriminator **inside a distribution config** — e.g. the nested form's inner dict `{"type": "Normal", "mean": 3.0, "std": 0.2}` resolves to a `Normal` — so existing serialized configs round-trip unchanged. Note that `type` only aliases `distribution` at the distribution level: at the top level of a prior mapping, `type` is the prior discriminator (it must be `"Prior"`), so a flat-form prior must name its distribution with `distribution`, not `type`.

## Why `LogNormal` for diffusivities

Solid-phase diffusivities span many orders of magnitude (often $10^{-16}$ to $10^{-10}$ m²/s). A `Normal` prior on the raw value is hard to specify — mean ± std doesn't reflect order-of-magnitude uncertainty. A `LogNormal` prior treats the parameter on a log scale, so "mean ± 1 std" corresponds to a factor of $e$ — much more natural. The `mean=-32.2` in the example above is the natural log of $\sim 10^{-14}$, so the prior is centred on a typical particle diffusivity.

<CardGroup cols={2}>
  <Card title="Regularization (theory)" icon="scale-balanced" href="/guide/data-fitting/regularization">
    Ridge regression, MAP estimation, bias–variance tradeoff.
  </Card>

  <Card title="Data Fitting overview" icon="chart-line" href="/pipelines/data-fitting/overview">
    Putting priors together with objectives and optimisers.
  </Card>
</CardGroup>
