ML.NET learner - xkqg/DeepSharp GitHub Wiki
The ML.NET learner
In short
A table is often learned better by a tree than by a network, and a table that a tree learns better does not have to become a network. DeepSharp's learner seam takes any learner, so a trainer from ML.NET stands exactly where a network stands: the pipeline prepares the rows, the tree learns from them, and the pipeline's own report measures what comes back. The rule to remember: a tree and a network measured by one report on the same rows is the only comparison between them that means anything β so the declaration stays the same, and only the learner's line changes.
| You want to⦠| Write |
|---|---|
| Declare boosted trees | .WithML(trainer => trainer.FastTree(trees: 50)) |
| Declare a forest | .WithML(trainer => trainer.FastForest()) |
| Give the trainer a seed of your own | .WithML(trainer => trainer.FastTree(), seed: 7) |
Train it (needs DeepSharp.Learners.MLNet) |
pipeline.TrainWithML() |
| See what it predicts for every row of a part | trained.Predict(Part.Test) |
| Write the model file | File.WriteAllText("titanic.mlmodel.json", trained.ToJson()) |
| Read a model file back, without ML.NET | MLModelFile.FromJson(text) |
The rest of this page explains the two packages, the declaration, and why the list of trainers is short.
Two packages, and which one you need
| what it is | brings | |
|---|---|---|
DeepSharp.Learners.ML |
The verb: it says which trainer a pipeline's rows are prepared for, and it reads and writes the model file. | nothing of ML.NET |
DeepSharp.Learners.MLNet |
The training: it hands the rows to Microsoft.ML, fits the tree and writes the model. | Microsoft.ML and Microsoft.ML.FastTree |
The split is the dependency, not the design. A notebook, a server or an application that only reads a model is forced to carry whichever package brings a verb. So the verb's package carries no ML.NET at all, and the library travels only to whoever asks to train.
A check of the packages measures exactly that on every build: one application trains and writes a model file, another reads that file back while carrying nothing of ML.NET.
Declaring it
using DeepSharp.Learners.ML;
using DeepSharp.Pipelines;
var pipeline = Pdd.Create()
.ReadCsv("titanic.csv")
.Declare(schema => schema.Integer("survived", "sibsp").Category("sex").Optional("age", ColumnKind.Number).Number("fare"))
.SplitStratified("survived", train: 0.70, validation: 0.15)
.Target("survived")
.FillMissing(fill => fill.Median("age"))
.EncodeCategories()
.Normalise("age", "fare") // declared, and left out of the run a tree is made for
.Report(report => report.Measure(Metric.Accuracy, Metric.Precision).On(Part.Validation, Part.Test).As(Shown.Numbers))
.WithML(trainer => trainer.FastTree(trees: 50)) // or .FastForest(β¦)
.Build();
That is the declaration, and it needs only DeepSharp.Learners.ML.
Training it
Training needs the other package, and reads as one line more:
// using DeepSharp.Learners.MLNet;
// var trained = pipeline.TrainWithML();
// File.WriteAllText("titanic.mlmodel.json", trained.ToJson());
It is TrainWithML rather than Train, because the networks package already offers Train on a pipeline, and two
packages offering one name on one type either refuse to compile or quietly take each other's calls.
What a tree does without, and why it still compares
A tree takes numbers of any size, so the run made for it leaves the scalings out β Needs.NoScale β and writes down
which steps it left out, in the file.
Everything else is the same run over the same rows in the same parts. That is why the report can measure a tree and a network against each other at all.
Declare the scalings anyway: the same declaration is then the one a network is trained from, and the two differ in a single line.
Which trainers, and why so few
Boosted trees and a forest. No linear trainer, no LightGBM.
| trainer | what it is | settings, with their defaults |
|---|---|---|
FastTree |
Gradient-boosted trees: each tree corrects what the ones before it got wrong. | leaves: 20, trees: 100, leastRows: 10, rate: 0.2 |
FastForest |
A forest of trees grown apart and averaged, which holds up better on few rows than boosting does. | leaves: 20, trees: 100, leastRows: 10 |
leaves is how many leaves one tree may grow to, trees how many trees are grown, leastRows the fewest training rows
a leaf may stand for, and rate how much of each tree's correction is taken.
Why no linear trainer
A declaration is a promise that running it again gives the same model, and that promise is what decides the list.
Measured on this library's own rows:
- at its defaults, ML.NET's stochastic dual coordinate ascent trainer gave five different models in five runs, even under one seeded context;
- pinning it to a single thread makes it repeat on one machine, and the last bits still move when the processor takes another instruction path;
- boosted trees do not move.
So a tree repeats from the seed the declaration carries, and a trainer that cannot be replayed is refused by name rather than offered with a warning nobody reads.
Why no LightGBM
LightGBM is left out for a plainer reason: its native side is built for x64 only and wants an OpenMP runtime the package does not bring.
The seed, and what it actually changes
The declaration carries a seed, and the trainers read it from there β ML.NET's own context seed never reaches them.
Measured:
- A forest bags its rows, so another seed gives another model.
- Boosted trees at these settings draw nothing at random, so the seed changes nothing about them.
Both are replayable, which is what the seed is there to promise.
The model file
One file, as a network's is:
- the pipeline's text, exactly as it was written;
- the model, bound to that text;
- a model read beside another fit of those steps is refused, rather than quietly answering from numbers learned somewhere else.
It says two things a network's file does not have to.
- Which ML.NET, on which processor. The model inside it is ML.NET's own archive, which only ML.NET opens. So the file names the version of ML.NET that wrote it and the processor it was written on, and a reader that cannot open it can say which package and which version would.
- Not tied by the archive's bytes. The archive's own bytes are never what ties the file to anything: ML.NET stamps it with the clock it was saved at, so two saves of one model differ while the model does not.
Next: every verb in the order you write them: Pipeline Β· the other learner: Networks Β· why the course is shaped this way: PDD