README
¶
dtgo
Decision tree in Go based on the @random-forests example.
Command line
Train a model from a labeled CSV file. By default, the final column is the target label and 20% of rows are reserved for evaluation:
go run . train -input testdata/Iris.csv -output iris-model.json
Use -target-name to select the target by its exact, case-sensitive header, or
-target-index to select it by its zero-based CSV column index:
go run . train -input testdata/Iris.csv -output iris-model.json -target-name Species
go run . train -input testdata/Iris.csv -output iris-model.json -target-index 4
The target flags are mutually exclusive. Remaining columns become model features in their original relative order.
Use -no-header when the training CSV contains data records only:
go run . train -input headerless-training.csv -output model.json -no-header
Headerless training names the model features feature_0, feature_1, and so
on, and names the target label. The final CSV column remains the default
target. Use -target-index to select another column; -target-name cannot be
used without a header. Generated feature numbers follow feature order after
the target column is removed.
The command prints the trained tree, any failed holdout predictions, and a
summary containing the training size, test size, correct and failed counts,
and accuracy. Change the holdout with -test-split; use -test-split 0 to
train on every row without evaluation.
Every successful training run also prints wall-clock time, percentage of total
time, and throughput for typed CSV loading, splitting, column finalization,
training, rendering, evaluation, and model saving. Loading reports source
bytes, records, values, and retained typed storage; finalization reports the
selected rows, immutable storage, and feature strategies. The performance
block also reports the process's current GOMAXPROCS. Use -perf-details to
include tree shape, split-scoring work, the five slowest features, allocations,
and garbage collection activity:
go run . train -input testdata/Iris.csv -output iris-model.json -perf-details
CLI training uses up to GOMAXPROCS workers for loading large regular CSV
files, merging typed source columns, global numeric presorting, feature scoring
at large nodes, and sufficiently large sibling subtrees. The phases reuse the
same bound and do not oversubscribe the process. Files smaller than 8 MiB and
inputs without regular-file size metadata retain the streaming serial loader.
Use -parallelism 1 for fully serial loading and training or -parallelism N
to set a smaller bound. Values above GOMAXPROCS are capped.
CLI training parses CSV records directly into typed immutable source columns;
it does not retain a [][]string or [][]any copy. Train/test selections are
indexed views over those columns, so holdout size, membership, and source order
remain unchanged. Constant source columns retain one value, binary source
columns retain two values plus a bitset, and integer source columns with 3–64
values retain byte ordinals. Selected views reuse this source inference
metadata and compatible masks or ordinals during finalization. Globally binary
integer, finite-float, and string features then use bitsets, including popcount
scoring at sufficiently dense nodes. Higher-cardinality integers and
non-binary numeric features are globally presorted once and retain their order
through child partitions. These representations are discarded after training
and do not change the saved model format.
For large files, the loader first finds quote-aware record boundaries and then
parses bounded ReaderAt sections concurrently. Typed shards are concatenated
in source order, including numeric promotion and dictionary reconciliation.
Quoted multiline fields, escaped quotes, TrimLeadingSpace, missing-value
locations, and deterministic error precedence remain identical to serial CSV
loading. Detailed performance output reports loader workers, chunks, boundary
scan time, and shard-merge time.
Use -cpuprofile FILE, -memprofile FILE, or -trace FILE to capture standard
Go diagnostic artifacts. Profile output paths must differ from the command's
input and output paths and from one another. Reported operational time excludes
the final profile flush.
Empty fields and the case-sensitive value NA are treated as missing. Training
rejects missing feature values by default and reports their CSV location. Use
-missing drop to discard rows with missing features before the train/test
split:
go run . train -input testdata/penguins.csv -output penguins-model.json -missing drop
The training summary always reports how many rows were dropped. Missing labels are rejected under both missing-value policies.
Run inference with a feature-only CSV whose header exactly matches the model's feature names and order:
go run . infer -input iris-features.csv -model iris-model.json > predictions.csv
The output CSV preserves the input columns and appends the label column from
the training data. Inference performance is reported on standard error so the
prediction CSV on standard output remains unchanged. Its phases are model
loading, CSV reading, record processing, and CSV writing; -perf-details and
the profiling flags are also available for inference.
For a feature-only CSV without a header, pass -no-header. Every input record
is processed, and the output remains headerless with the prediction appended:
go run . infer -input headerless-features.csv -model model.json -no-header > predictions.csv
Model API
decisiontree.TrainModel returns a model containing both the trained tree and
its input schema. Models can be persisted and restored with
decisiontree.SaveModel and decisiontree.LoadModel:
model, err := decisiontree.TrainModel(rows, header)
if err != nil {
return err
}
if err := decisiontree.SaveModel(writer, model); err != nil {
return err
}
loaded, err := decisiontree.LoadModel[any](reader)
if err != nil {
return err
}
label, err := loaded.Predict(features)
Use decisiontree.TrainModelWithMetrics when training diagnostics are needed.
It additionally returns ordered per-feature scoring calls, row visits,
candidate counts and elapsed time, along with columnar storage, global
presorting, histogram, binary/bitset, parallel-task, node, leaf, and depth
totals. TrainModel does not collect or time these details.
The existing Train, TrainModel, and TrainModelWithMetrics APIs remain
serial. Use the options-based APIs to enable bounded parallel training:
model, metrics, err := decisiontree.TrainModelWithOptionsAndMetrics(
rows,
header,
decisiontree.TrainingOptions{Parallelism: 0}, // use GOMAXPROCS
)
Streaming CSV integrations can build the same typed representation directly
with decisiontree.NewTrainingDataBuilder and AppendCSVRecord. Build
returns immutable TrainingData; Select makes checked indexed views without
copying column values, and RowInto reconstructs a row only when needed.
Prepare a non-empty selection once and train it repeatedly:
builder, err := decisiontree.NewTrainingDataBuilder(header, estimatedRows)
if err != nil {
return err
}
for readNextCSVRecord() {
if err := builder.AppendCSVRecord(record); err != nil {
return err
}
}
data, err := builder.Build()
if err != nil {
return err
}
prepared, preparation, err := decisiontree.PrepareTrainingData(data)
if err != nil {
return err
}
model, metrics, err := decisiontree.TrainPreparedModelWithOptionsAndMetrics(
prepared,
decisiontree.TrainingOptions{Parallelism: 0},
)
Parallel ingestion integrations can create category-compatible shard builders
with NewTrainingDataBuilderLike, then join immutable shards in source order
with ConcatTrainingData or ConcatTrainingDataWithOptions. Concatenation
reconciles numeric promotion, compact integer dictionaries, binary bitsets,
categorical string pools, and selected views without materializing Rows[any].
For batches, provide the destination slice so prediction does not allocate:
labels := make([]string, len(featureRows))
predicted, err := loaded.PredictInto(featureRows, labels)
if err != nil {
// labels[:predicted] contains the successful predictions.
return err
}
The JSON artifact is versioned and stores ordered feature names, explicit
int, float64, or string types, the label name, and the complete decision
tree. Load rejects unsupported versions and malformed trees before inference.
Models are immutable after training or loading; their prediction methods are
safe for concurrent callers using disjoint input and output slices.
Documentation
¶
There is no documentation for this package.