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

An unfitted estimator: inert data, no session, no server-side anything.

`Latu.ML.fit/2` is what turns one into a `Latu.ML.Model`, and the frame it is fitted on is
where the session comes from.

# `t`

```elixir
@type t() :: %Latu.ML.Estimator{
  class: String.t(),
  known: [Latu.ML.Param.t()],
  model_candidates: [String.t()],
  model_class: String.t() | nil,
  params: [Latu.ML.Plan.param()],
  uid: String.t()
}
```

# `new`

```elixir
@spec new(String.t(), keyword()) :: t()
```

An estimator the registry does not know, by its JVM class name.

The escape hatch for anything on the server's classpath that MLlib did not put there. Nothing
checks the param names — there is no table to check them against — so the server's error is
the only one you get, and `model_class` is yours to supply if you want the model's attributes
to resolve later.

## Options

  * `:params` — the params to send, already in wire form: `{name, type, value}` per param,
    where `name` is Spark's own spelling. Defaults to `[]`.
  * `:model_class` — the JVM class of the model a fit produces. Defaults to `nil`, which
    leaves `Latu.ML.Model`'s `:class` unset.
  * `:uid` — the uid to send. Defaults to a generated one in PySpark's shape.

## Example

    Latu.ML.Estimator.new("ml.dmlc.xgboost4j.scala.spark.XGBoostClassifier",
      params: [{"numRound", :int, 100}, {"max_depth", :int, 6}])

A param's name is whatever the library declared it, and that is not always one convention:
XGBoost4J spells its own params camelCase and the native booster's snake_case, and the server
resolves each exactly as written.

---

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