{"record":{"id":"a7d8eb543485fe27","repo":"microsoft/qlib","slug":"model-is-not-fitted-yet-a7d8eb","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_transformer_ts.py","lineNumber":203,"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):\r\n        if not self.fitted:\r\n            raise ValueError(\"model is not fitted yet!\")\r\n\r\n        dl_test = dataset.prepare(\"test\", col_set=[\"feature\", \"label\"], data_key=DataHandlerLP.DK_I)\r\n        dl_test.config(fillna_type=\"ffill+bfill\")\r\n        test_loader = DataLoader(dl_test, batch_size=self.batch_size, num_workers=self.n_jobs)\r\n        self.model.eval()\r\n        preds = []\r\n\r\n        for data in test_loader:\r\n            feature = data[:, :, 0:-1].to(self.device)\r\n\r\n            with torch.no_grad():\r\n                pred = self.model(feature.float()).detach().cpu().numpy()\r\n\r\n            preds.append(pred)\r\n\r\n        return pd.Series(np.concatenate(preds), index=dl_test.get_index())\r\n\r\n\r","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_transformer_ts.py#L185-L221","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call model.fit(dataset) to completion before model.predict(dataset).","If fit() previously failed, fix the underlying fit error first (check logs above this traceback).","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.","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)."],"exampleFix":"# before\nmodel = TransformerTSModel()\nmodel.predict(dataset)  # ValueError: model is not fitted yet!\n\n# after\nmodel = TransformerTSModel()\nmodel.fit(dataset)      # must complete successfully\nmodel.predict(dataset)","handlingStrategy":"validation","validationCode":"if not getattr(model, \"fitted\", False):\n    raise RuntimeError(\"TransformerTSModel must be fit() before predict()\")\npreds = model.predict(dataset)","typeGuard":"def is_fitted_ts(model) -> bool:\n    return bool(getattr(model, \"fitted\", False))","tryCatchPattern":"try:\n    pred = model.predict(dataset)\nexcept ValueError as e:\n    if \"not fitted\" in str(e):\n        model.fit(dataset)\n        pred = model.predict(dataset)\n    else:\n        raise","preventionTips":["Treat fit and predict as one pipeline step; never ship a predict path that can run before fit.","Check model.fitted before predict in orchestration code.","Persist and restore fitted model objects rather than re-instantiating from config for inference."],"tags":["qlib","pytorch","lifecycle","state","predict"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}