microsoft/qlib · error · ValueError

model is not fitted yet!

Error message

model is not fitted yet!

What it means

LOCALTransformerModel.predict() refuses to run when the instance flag self.fitted is False. The flag is only set to True after a successful fit() completes (including early stop, where the best checkpoint is reloaded). Calling predict() on a fresh or failed-to-fit model raises ValueError('model is not fitted yet!') immediately, before any data is prepared.

Source

Thrown at qlib/contrib/model/pytorch_localformer.py:218

                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: DatasetH, segment: Union[Text, slice] = "test"):
        if not self.fitted:
            raise ValueError("model is not fitted yet!")

        x_test = dataset.prepare(segment, col_set="feature", data_key=DataHandlerLP.DK_I)
        index = x_test.index
        self.model.eval()
        x_values = x_test.values
        sample_num = x_values.shape[0]
        preds = []

        for begin in range(sample_num)[:: self.batch_size]:
            if sample_num - begin < self.batch_size:
                end = sample_num
            else:
                end = begin + self.batch_size

            x_batch = torch.from_numpy(x_values[begin:end]).float().to(self.device)

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

View on GitHub (pinned to 79633dd950)

Solutions

  1. Call model.fit(dataset, evals_result) to completion before model.predict(dataset); only a finished fit sets self.fitted = True.
  2. If fit() threw earlier, fix that root cause first (see its exception) and re-fit; predict will keep failing until fit succeeds.
  3. To reuse a previously trained model, load the saved state dict (torch.load(save_path); model.model.load_state_dict(state)) AND set model.fitted = True explicitly before predict.
  4. In multi-segment workflows, confirm your task config actually runs the train segment before the backtest/record step.

Example fix

# before
model = LOCALTransformerModel(d_feat=6)
preds = model.predict(dataset)  # ValueError: model is not fitted yet!

# after
model = LOCALTransformerModel(d_feat=6)
model.fit(dataset, evals_result)
preds = model.predict(dataset)
Defensive patterns

Strategy: validation

Validate before calling

# before predicting, confirm the model completed fit
if not getattr(model, "fitted", False):
    raise RuntimeError("LOCALTransformerModel is not fitted; call fit() before predict()")
preds = model.predict(dataset)

Type guard

def is_fitted_localformer(model) -> bool:
    """True only after a successful fit() on a LOCALTransformerModel."""
    return bool(getattr(model, "fitted", False)) and hasattr(model, "model")

Try / catch

try:
    preds = model.predict(dataset)
except ValueError as e:
    if "not fitted" in str(e):
        model.fit(dataset, evals_result)  # or load checkpoint + set fitted
        preds = model.predict(dataset)
    else:
        raise

Prevention

When it happens

Trigger: Calling model.predict(dataset) on a LOCALTransformerModel whose fit() was never called, whose fit() raised before setting self.fitted = True, or on a newly constructed model after a failed/interrupted training run.

Common situations: Running a workflow (e.g. qrun) with a pickle-loaded model whose training step was skipped; fit() crashed on empty data or CUDA OOM and the script continued to backtest; instantiating the model directly in a notebook and jumping straight to predict.

Related errors


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