microsoft/qlib · error · ValueError

model is not fitted yet!

Error message

model is not fitted yet!

What it means

Raised by TransformerTSModel.predict when self.fitted is False, i.e. predict() was called before a successful fit(). The TS model family in qlib guards prediction on a fitted flag that is only set after the training loop completes, so any predict-before-fit or failed-fit sequence hits this immediately.

Source

Thrown at qlib/contrib/model/pytorch_transformer_ts.py:203

                stop_steps = 0
                best_epoch = step
                best_param = copy.deepcopy(self.model.state_dict())
            else:
                stop_steps += 1
                if stop_steps >= self.early_stop:
                    self.logger.info("early stop")
                    break

        self.logger.info("best score: %.6lf @ %d" % (best_score, best_epoch))
        self.model.load_state_dict(best_param)
        torch.save(best_param, save_path)

        if self.use_gpu:
            torch.cuda.empty_cache()

    def predict(self, dataset):
        if not self.fitted:
            raise ValueError("model is not fitted yet!")

        dl_test = dataset.prepare("test", col_set=["feature", "label"], data_key=DataHandlerLP.DK_I)
        dl_test.config(fillna_type="ffill+bfill")
        test_loader = DataLoader(dl_test, batch_size=self.batch_size, num_workers=self.n_jobs)
        self.model.eval()
        preds = []

        for data in test_loader:
            feature = data[:, :, 0:-1].to(self.device)

            with torch.no_grad():
                pred = self.model(feature.float()).detach().cpu().numpy()

            preds.append(pred)

        return pd.Series(np.concatenate(preds), index=dl_test.get_index())


View on GitHub (pinned to 79633dd950)

Solutions

  1. Call model.fit(dataset) to completion before model.predict(dataset).
  2. If fit() previously failed, fix the underlying fit error first (check logs above this traceback).
  3. If you meant to use a previously trained model, restore it from its saved state (torch.load of the saved best_param / reload via qlib's ModelRecord or pickle the fitted object) instead of predicting from a fresh instance.
  4. Ensure only the trained model instance is passed to the backtest/report workflow (e.g. not re-instantiated by init_instance_by_config without retraining).

Example fix

# before
model = TransformerTSModel()
model.predict(dataset)  # ValueError: model is not fitted yet!

# after
model = TransformerTSModel()
model.fit(dataset)      # must complete successfully
model.predict(dataset)
Defensive patterns

Strategy: validation

Validate before calling

if not getattr(model, "fitted", False):
    raise RuntimeError("TransformerTSModel must be fit() before predict()")
preds = model.predict(dataset)

Type guard

def is_fitted_ts(model) -> bool:
    return bool(getattr(model, "fitted", False))

Try / catch

try:
    pred = model.predict(dataset)
except ValueError as e:
    if "not fitted" in str(e):
        model.fit(dataset)
        pred = model.predict(dataset)
    else:
        raise

Prevention

When it happens

Trigger: Calling model.predict(dataset) on a freshly constructed TransformerTSModel without calling fit(); calling predict after fit() raised an exception partway through training (fitted never set); reloading a workflow/pickle where the fitted attribute was lost; calling predict in a separate process that never trained.

Common situations: Notebook workflows where the fit cell errored (e.g. empty dataset, GPU OOM) but subsequent cells still run; serializing/deserializing model objects without the fitted state; orchestrating train and predict as separate scripts while sharing the model object instead of the saved checkpoint.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/a7d8eb543485fe27. Report an issue: GitHub.