{"record":{"id":"8043e04533beb85b","repo":"microsoft/qlib","slug":"model-is-not-fitted-yet-8043e0","errorCode":null,"errorMessage":"model is not fitted yet!","messagePattern":"model is not fitted yet!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_general_nn.py","lineNumber":341,"sourceCode":"                if stop_steps >= self.early_stop:\n                    self.logger.info(\"early stop\")\n                    break\n\n        self.logger.info(\"best score: %.6lf @ %d epoch\" % (best_score, best_epoch))\n        self.dnn_model.load_state_dict(best_param)\n        torch.save(best_param, save_path)\n\n        if self.use_gpu:\n            torch.cuda.empty_cache()\n\n    def predict(\n        self,\n        dataset: Union[DatasetH, TSDatasetH],\n        batch_size=None,\n        n_jobs=None,\n    ):\n        if not self.fitted:\n            raise ValueError(\"model is not fitted yet!\")\n\n        dl_test = dataset.prepare(\"test\", col_set=[\"feature\", \"label\"], data_key=DataHandlerLP.DK_I)\n        self.logger.info(f\"Test samples: {len(dl_test)}\")\n\n        if isinstance(dataset, TSDatasetH):\n            dl_test.config(fillna_type=\"ffill+bfill\")  # process nan brought by dataloader\n            index = dl_test.get_index()\n        else:\n            # If it is a tabular, we convert the dataframe to numpy to be indexable by DataLoader\n            index = dl_test.index\n            dl_test = dl_test.values\n\n        test_loader = DataLoader(dl_test, batch_size=self.batch_size, num_workers=self.n_jobs)\n        self.dnn_model.eval()\n        preds = []\n\n        for data in test_loader:\n            feature, _ = self._get_fl(data)","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_general_nn.py#L323-L359","documentation":"Raised by DNNModelPytorch.predict when called before a successful fit(). The class tracks a boolean `fitted` flag that is set to True only after training completes (including restoring best parameters); predict refuses to run on an unfitted model because there are no learned weights to load.","triggerScenarios":"Instantiating DNNModelPytorch and calling predict(dataset) directly; or fit() raising earlier (e.g. empty data, unknown loss) so fitted was never set, then predict being called in a workflow's backtest stage; loading a fresh model object instead of restoring a persisted one.","commonSituations":"Workflow scripts that run predict in a separate process without re-fitting or loading the saved checkpoint; silent fit failures swallowed upstream; re-instantiating the model for inference after training in a different session.","solutions":["Call model.fit(dataset) successfully before predict (fitted becomes True at the end of fit).","If the model was trained previously, restore it rather than creating a new object; for nn models the recommended path is to rerun fit with the same save_path / or load the state dict and set model.fitted = True manually.","In R workflows, ensure the task model is fitted inside the same run before the backtest record triggers predict."],"exampleFix":"# before\nmodel = DNNModelPytorch(**params)\npreds = model.predict(dataset)  # ValueError: not fitted\n\n# after\nmodel = DNNModelPytorch(**params)\nmodel.fit(dataset)\npreds = model.predict(dataset)","handlingStrategy":"validation","validationCode":"assert model.fitted, \"call model.fit(dataset) (or restore a trained checkpoint) before predict()\"","typeGuard":"def is_fitted(model) -> bool:\n    return bool(getattr(model, \"fitted\", False))","tryCatchPattern":"try:\n    preds = model.predict(dataset)\nexcept ValueError as e:\n    if \"not fitted\" in str(e):\n        model.fit(dataset)\n        preds = model.predict(dataset)\n    else:\n        raise","preventionTips":["Check the `fitted` attribute before predict in inference scripts.","Abort the pipeline on any fit() failure so backtest/predict stages never run against an unfitted model."],"tags":["qlib","pytorch","lifecycle","state-error"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}