# `Latu.ML.CrossValidator`
[🔗](https://github.com/zero-one-group/latu_ml/blob/v0.4.2/lib/latu/ml/cross_validator.ex#L1)

K-fold cross-validation: fit every param map on every fold, and keep the best.

**Not a server operator.** Spark has no `Fit` for a validator — `MlCommand.Fit` takes an
`MlOperator` and the Connect server exposes none for `CrossValidator` — so the search is a
fold this package runs, as it is a loop PySpark runs. What reaches the server is one `Fit`,
one `Transform` and one `Evaluate` per fold per param map, and one last `Fit` for the winner.

    grid = ML.param_grid(lr, reg_param: [0.1, 0.01], max_iter: [10, 100])

    cv =
      ML.cross_validator(
        estimator: lr,
        param_maps: grid,
        evaluator: Evaluation.binary_classification_evaluator(),
        num_folds: 3
      )

    {:ok, model} = ML.fit(cv, training)

## What it costs

`num_folds * length(param_maps)` fits, plus one. Each is a cache entry on the server while it
is being scored, and `Latu.ML.fit/2` deletes it as soon as its metric is read — so a 3-by-4
search holds one model at a time rather than twelve. `collect_sub_models: true` keeps them
all instead, and they become yours to `Latu.ML.delete/1`.

## The folds

A fold is cut by ranking rows on `rand(seed)` and taking a range of it, which is Spark's own
way and **not** a `random_split`. Pass `seed:` for a cut that is the same twice. `fold_col:`
names a column that already holds a fold number instead, in which case `seed` and `num_folds`
only have to agree with it.

# `searchable`

```elixir
@type searchable() :: Latu.ML.Estimator.t() | Latu.ML.Pipeline.t()
```

What is being searched: one estimator, or a pipeline with one inside it.

# `t`

```elixir
@type t() :: %Latu.ML.CrossValidator{
  collect_sub_models: boolean(),
  estimator: searchable(),
  evaluator: Latu.ML.Evaluator.t(),
  fold_col: String.t() | nil,
  num_folds: pos_integer(),
  param_maps: [Latu.ML.param_map()],
  seed: integer() | nil,
  uid: String.t()
}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
