{"record":{"id":"b1e26e5221e9f9dd","repo":"microsoft/qlib","slug":"model-is-not-fitted-yet-b1e26e","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_tabnet.py","lineNumber":219,"sourceCode":"                stop_steps = 0\n                best_epoch = epoch_idx\n                best_param = copy.deepcopy(self.tabnet_model.state_dict())\n            else:\n                stop_steps += 1\n                if stop_steps >= self.early_stop:\n                    self.logger.info(\"early stop\")\n                    break\n\n        self.logger.info(\"best score: %.6lf @ %d\" % (best_score, best_epoch))\n        self.tabnet_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(self, dataset: DatasetH, segment: Union[Text, slice] = \"test\"):\n        if not self.fitted:\n            raise ValueError(\"model is not fitted yet!\")\n\n        x_test = dataset.prepare(segment, col_set=\"feature\", data_key=DataHandlerLP.DK_I)\n        index = x_test.index\n        self.tabnet_model.eval()\n        x_values = torch.from_numpy(x_test.values)\n        x_values[torch.isnan(x_values)] = 0\n        sample_num = x_values.shape[0]\n        preds = []\n\n        for begin in range(sample_num)[:: self.batch_size]:\n            if sample_num - begin < self.batch_size:\n                end = sample_num\n            else:\n                end = begin + self.batch_size\n\n            x_batch = x_values[begin:end].float().to(self.device)\n            priors = torch.ones(end - begin, self.d_feat).to(self.device)\n","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_tabnet.py#L201-L237","documentation":"Raised by TabNet model predict() in qlib/contrib/model/pytorch_tabnet.py:219 when self.fitted is False. fitted is set only at the end of a successful fit() (after restoring best params and torch.save of the checkpoint); predict refuses inference otherwise.","triggerScenarios":"predict() before fit(); predict() after fit() failed mid-training (empty data, loss/metric ValueError, NaN loss, OOM); predict() on a fresh model object with a pretrain checkpoint but no finetune fit.","commonSituations":"Assuming pretrain_fn alone makes the model predict-ready (it does not — fit() must still run); scripted backtests that ignore fit failures.","solutions":["Complete model.fit(dataset) (with or without pretrain) before predict().","If fit fails, fix the earlier error; this ValueError is downstream noise.","Reuse trained checkpoints through the documented save/load path."],"exampleFix":"model.fit(dataset)                     # pretrain + finetune completes here\npreds = model.predict(dataset, segment=\"test\")","handlingStrategy":"validation","validationCode":"if not model.fitted:\n    raise RuntimeError(\"TabNet requires a completed fit() (pretrain alone is not enough)\")\npreds = model.predict(dataset, segment=\"test\")","typeGuard":"def is_fitted(model) -> bool:\n    return bool(getattr(model, \"fitted\", False))","tryCatchPattern":"try:\n    preds = model.predict(dataset, segment)\nexcept ValueError as e:\n    if \"not fitted\" in str(e):\n        raise RuntimeError(\"TabNet finetune fit() did not complete\") from e\n    raise","preventionTips":["Remember pretrain_fn does not set fitted; the finetune fit() must run.","Check fitted before predict in backtest scripts."],"tags":["qlib","pytorch","lifecycle","predict-before-fit","tabnet"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}