Data¶
TorchSONN trains from PyTorch data loaders. This page covers the dataset wrapper, the splits a run needs, how to prepare features, and the options for unusual batch formats and imbalanced classes.
SONNDataset¶
SONNDataset(x, target) pairs a feature matrix with its targets; any
PyTorch DataLoader works on top of it.
from torch.utils.data import DataLoader
from torchsonn import SONNDataset
train_dl = DataLoader(SONNDataset(x_train, y_train), batch_size=16384, shuffle=True)
xis an array or tensor with one row per sample and one column per feature. Float32 and float64 both work.targetholds one value per row: a number for regression, the class index 0, 1, ... formulti-class(integers; float labels fail inside the loss), and 0 or 1 forbinary. A loader cannot batch missing targets; to predict rows that have none, callmodel.infer(x)on a tensor of features, or give the dataset placeholder targets.split=0orsplit=1keeps only the even or the odd rows. The trainer uses this for the minimum-bias criterion; you rarely need it.
The splits¶
A run reads three loaders, plus an optional fourth:
| Loader | Passed to | Used for |
|---|---|---|
| train | train(train_dl, ...) |
fitting every coefficient |
| dev | train(..., dev_dl, ...) |
scoring and selecting candidates, the depth, the early stops |
| test | train(..., test_dl) |
nothing during training; your final measurement with infer |
| validation | train(..., val_dl=...) |
reported per layer; optional (see Splits and stopping) |
The dev split decides a lot, so its rows must not appear in the test split. The quickstarts use 50% / 25% / 25%, and holding out around 20% for test and splitting the rest 3:1 into train and dev is a reasonable default. Shuffle the rows before cutting when the data is stored in a meaningful order, such as by location or by time.
Preparing features¶
- Standardize each feature with the mean and standard deviation of the training rows only, then apply the same transform to every split.
- Tame heavy tails. A few rows far outside the bulk get extreme
predictions from a polynomial network and can dominate the test error.
Clip standardized features (the quickstarts clip at ±5), or log-transform
skewed ones. Between layers,
model.output_clamp_value(1000 by default) bounds every layer's outputs. - The orthogonal families squash their inputs themselves (see Orthogonal polynomials), and the RBF family standardizes its own; the power-basis families use the inputs as they come.
Batch size¶
The trainer takes batches from the loaders as they come; train.batch_size
is read only by the tutorial scripts, which build their loaders from it.
For the LBFGS optimizer, use one batch per split: a batch size larger than
the number of training rows. LBFGS builds its curvature estimate from
successive gradients, which must come from the same rows. Shuffle the
training loader; the order of the dev and test loaders does not matter.
Deterministic splits¶
torchsonn.data.preprocessing has helpers for splitting data by row
position, as GMDH implementations traditionally do:
from torchsonn.data.preprocessing import SequenceTypeSet, split_dataset, train_preprocessing
x, y = train_preprocessing(x, y, feature_names) # arrays, shape checks
x_train, y_train, x_dev, y_dev = split_dataset(x, y, SequenceTypeSet.sqMode4_1)
train_preprocessing turns pandas objects into arrays, checks that x is
2-D with at least two features and two rows, transposes it if its rows and
columns are swapped, and checks feature_names against the number of
columns. split_dataset assigns each row to train or to dev (called
"validate" there):
SequenceTypeSet |
Rows sent to dev |
|---|---|
sqRandom |
each row at random, with probability 1/2 |
sqMode1, sqMode3_1, sqMode4_1 |
every 2nd, 3rd or 4th row |
sqMode2, sqMode3_2, sqMode4_2 |
all but every 2nd, 3rd or 4th row |
sqMode4_1, for example, gives a 3:1 train/dev split.
Custom batch formats¶
If your loader yields something other than (x, y) pairs, pass a function
that turns a batch into one:
The trainer applies it wherever it reads a batch during training. infer
does not: give it a loader that yields (x, y) pairs.
Class weights¶
For imbalanced classes, weight the loss per class:
For multi-class, the tensor has one weight per class. For binary, it
has one element, the weight of the positive class.
Loaders for the end-to-end pass¶
On a CUDA device the end-to-end pass copies each batch into a fixed buffer
(see Performance). With train.finetune_train.data_on_device:
false the batches stream from the loader; build that loader with
pin_memory=True, because pinning a batch inside each step costs more than
the step itself (about 35 ms per 12,000 rows, comment on
OutProjTrainConfig.data_on_device).
Checked against TorchSONN 0.1.5.