{"record":{"id":"7b9f7a06e7f85d33","repo":"microsoft/qlib","slug":"model-is-not-fitted-yet-7b9f7a","errorCode":null,"errorMessage":"model is not fitted yet!","messagePattern":"model is not fitted yet!","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_localformer.py","lineNumber":218,"sourceCode":"                stop_steps = 0\r\n                best_epoch = step\r\n                best_param = copy.deepcopy(self.model.state_dict())\r\n            else:\r\n                stop_steps += 1\r\n                if stop_steps >= self.early_stop:\r\n                    self.logger.info(\"early stop\")\r\n                    break\r\n\r\n        self.logger.info(\"best score: %.6lf @ %d\" % (best_score, best_epoch))\r\n        self.model.load_state_dict(best_param)\r\n        torch.save(best_param, save_path)\r\n\r\n        if self.use_gpu:\r\n            torch.cuda.empty_cache()\r\n\r\n    def predict(self, dataset: DatasetH, segment: Union[Text, slice] = \"test\"):\r\n        if not self.fitted:\r\n            raise ValueError(\"model is not fitted yet!\")\r\n\r\n        x_test = dataset.prepare(segment, col_set=\"feature\", data_key=DataHandlerLP.DK_I)\r\n        index = x_test.index\r\n        self.model.eval()\r\n        x_values = x_test.values\r\n        sample_num = x_values.shape[0]\r\n        preds = []\r\n\r\n        for begin in range(sample_num)[:: self.batch_size]:\r\n            if sample_num - begin < self.batch_size:\r\n                end = sample_num\r\n            else:\r\n                end = begin + self.batch_size\r\n\r\n            x_batch = torch.from_numpy(x_values[begin:end]).float().to(self.device)\r\n\r\n            with torch.no_grad():\r\n                pred = self.model(x_batch).detach().cpu().numpy()\r","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_localformer.py#L200-L236","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call model.fit(dataset, evals_result) to completion before model.predict(dataset); only a finished fit sets self.fitted = True.","If fit() threw earlier, fix that root cause first (see its exception) and re-fit; predict will keep failing until fit succeeds.","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.","In multi-segment workflows, confirm your task config actually runs the train segment before the backtest/record step."],"exampleFix":"# before\nmodel = LOCALTransformerModel(d_feat=6)\npreds = model.predict(dataset)  # ValueError: model is not fitted yet!\n\n# after\nmodel = LOCALTransformerModel(d_feat=6)\nmodel.fit(dataset, evals_result)\npreds = model.predict(dataset)","handlingStrategy":"validation","validationCode":"# before predicting, confirm the model completed fit\nif not getattr(model, \"fitted\", False):\n    raise RuntimeError(\"LOCALTransformerModel is not fitted; call fit() before predict()\")\npreds = model.predict(dataset)","typeGuard":"def is_fitted_localformer(model) -> bool:\n    \"\"\"True only after a successful fit() on a LOCALTransformerModel.\"\"\"\n    return bool(getattr(model, \"fitted\", False)) and hasattr(model, \"model\")","tryCatchPattern":"try:\n    preds = model.predict(dataset)\nexcept ValueError as e:\n    if \"not fitted\" in str(e):\n        model.fit(dataset, evals_result)  # or load checkpoint + set fitted\n        preds = model.predict(dataset)\n    else:\n        raise","preventionTips":["Treat fit() and predict() as ordered steps; assert model.fitted before predict in pipeline code.","Check that fit() logged 'best score: ...' before continuing to backtest.","When restoring from checkpoints, set model.fitted = True explicitly after load_state_dict.","Make training failures fatal in workflow scripts so predict never runs on an unfitted model."],"tags":["pytorch","qlib","model-lifecycle","transformer","validation"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}