quantlab.model.torch_model.TorchModel#
- class quantlab.model.torch_model.TorchModel(config)[source]#
Bases:
TrainingTargetMixin,BaseModelTorch variant: standard PyTorch datasets and loaders, every learning choice a hook.
The base class assembles the collected panel as a
TrainingPanelof torch tensors and computes the training target once per fit. The head’s_datasethook turns it into a PyTorchDatasetand_dataloaderbatches it. The default is one cross-section per step (ADR 0006): one bar’s present symbols, each with its lastwindow_barsbars, so the network sees[S_t, N, F]; S_t changes from bar to bar, so it must not depend on the order or the number of symbols, and a symbol the model never saw in training still gets a prediction. Every sample carries itswhere(timestamp and symbol index), through which the base puts predictions back into the panel for any sample shape.The base class owns every data contract: the warm-up, the training target and its mask, moving batches to the device, the epoch loop, evaluation under
no_gradin eval mode, the{split}_lossof each split,.pthcheckpoints and prediction; the other metrics come from the model’s evaluation after training (seeBaseModel._evaluate). A head writes three things:window_barsN, the bars in each symbol’s window.
_init_model(num_features, num_labels, hyperparameters)The
nn.Module; several networks go in annn.ModuleDict._loss(output, batch)The loss of one
Batchfrom the network’s raw output; count onlybatch.masksamples.
and may override any of these, each of which has a working default:
_dataset(panel, bars, training)The PyTorch
Datasetoverbars. Default:CrossSectionDataset, one item per bar;SymbolSequenceDatasetgives Qlib-style(bar, symbol)samples batched to[B, N, F]._dataloader(dataset, training)The
DataLoader. Default:batch_sizeandnum_workersfrom the hyperparameters (Noneand 0, one item per step), shuffled only in training with a generator seeded fromrandom_seed, the last batch never dropped._transform_feature(x)A batch’s raw
x, NaN where a value or a bar is missing, to the network’s input. Default: clip to ±3, NaN to 0._transform_target(y, training)One bar’s raw
[S_t, L]labels to(target, keep), computed once per fit;keep(or None) removes symbols from the loss only. Default:(y, None)._init_optim(model)Default: Adam at
hyperparameters["lr"](1e-3), kept onself.optim; a head may return anything its own_train_one_batchunderstands, such as a dict of optimizers._train_one_batch(epoch, batch)One optimisation step; returns the loss. Default: forward,
_loss, backward, gradient values clipped tograd_clip_value(3.0; None disables), step._val_one_batch(epoch, batch)The evaluation loss of one batch. Default:
_loss._test_one_batch(epoch, batch)Called on every test batch after each epoch. Default: nothing.
_forward(x)The prediction,
batch.mask.shape + (L,), from a transformedx, used for metrics andpredict_panel. Default:self.model(x); override it when the network returns more than the prediction._on_fit_start(),_should_stop(epoch, train_loss, val_loss),_on_fit_end()When to stop and which weights to keep. Default: run
epochsepochs, keep the last weights.
epochs, the epoch cap, is read from the hyperparameters (default 100) and must be a positive integer; seeRESERVED_HYPERPARAMETERSfor the other keys the base reads.The model’s warm-up is N - 1 bars: every feature request, in training and in a backtest, starts that many bars earlier, counted on each factor’s own calendar (the bars of its output panel,
Factor.bar_before: days for a daily factor computed from one-minute bars, not its dataset’s minutes), and every factor starts at the earliest of those bars, so the first requested bar has a full window.Examples
A minimal head: a linear map of each symbol’s latest bar:
>>> class LastBarHead(TorchModel): ... window_bars = 5 ... def _init_model(self, num_features, num_labels, hyperparameters): ... return LastBarLinear(num_features, num_labels) ... def _loss(self, output, batch): ... return masked_mse(output, batch.y, batch.mask) >>> head = LastBarHead(ModelConfig( ... factors=[factor], labels=[label], model_save_dir="checkpoints", ... factor_data_strategy="read", label_data_strategy="read", ... hyperparameters={"epochs": 2}, ... train_start="2024-01-01", train_end="2024-01-30", ... test_start="2024-01-31", test_end="2024-02-09", ... )) >>> head.collect().train().suffix '.pth'
where
LastBarLinearisnn.Linear(num_features, num_labels)applied tox[:, -1].- PANEL_DEVICES = ('auto', 'cuda', 'cpu')#
Accepted
hyperparameters["panel_device"]values.
- PANEL_DTYPES = {'float16': torch.float16, 'float32': torch.float32}#
Accepted
hyperparameters["panel_dtype"]values and the feature dtype each stores.
- PANEL_GPU_BUDGET = 0.5#
Largest share of free GPU memory
panel_device="auto"gives the panel.
- check_hyperparameters()[source]#
Refuse an invalid
epochs,prefetch,pin_memory,panel_deviceorpanel_dtype.- Raises:
- ValueError
If one of them is invalid.
Examples
>>> model.check_hyperparameters() # the defaults are valid
- property device#
"cuda"when a CUDA device is available, else"cpu".Examples
>>> head.device 'cpu'
- property epochs#
The epoch cap,
hyperparameters["epochs"], 100 when unset.- Raises:
- ValueError
If the value is not a positive integer (a bool is refused too).
Examples
>>> head.epochs 100
- grad_clip_value = 3.0#
Gradient value clip of the default
_train_one_batch; None disables.
- reserved_hyperparameters = frozenset({'batch_size', 'epochs', 'lr', 'num_workers', 'panel_device', 'panel_dtype', 'pin_memory', 'prefetch'})#
The
hyperparameterskeys this variant reads itself, whichhead_hyperparametersleaves out.
- property warmup_bars#
window_bars - 1: bars requested before the start of every feature panel.Examples
>>> head.warmup_bars 4
- abstract property window_bars#
N, the number of bars in each symbol’s input window.
Examples
>>> head.window_bars 5