{"record":{"id":"9d52fc95fd56a2f0","repo":"microsoft/qlib","slug":"model-is-not-fitted-yet","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/catboost_model.py","lineNumber":82,"sourceCode":"        valid_pool = Pool(data=x_valid, label=y_valid_1d, weight=w_valid)\n\n        # Initialize the catboost model\n        self._params[\"iterations\"] = num_boost_round\n        self._params[\"early_stopping_rounds\"] = early_stopping_rounds\n        self._params[\"verbose_eval\"] = verbose_eval\n        self._params[\"task_type\"] = \"GPU\" if get_gpu_device_count() > 0 else \"CPU\"\n        self.model = CatBoost(self._params, **kwargs)\n\n        # train the model\n        self.model.fit(train_pool, eval_set=valid_pool, use_best_model=True, **kwargs)\n\n        evals_result = self.model.get_evals_result()\n        evals_result[\"train\"] = list(evals_result[\"learn\"].values())[0]\n        evals_result[\"valid\"] = list(evals_result[\"validation\"].values())[0]\n\n    def predict(self, dataset: DatasetH, segment: Union[Text, slice] = \"test\"):\n        if self.model is None:\n            raise ValueError(\"model is not fitted yet!\")\n        x_test = dataset.prepare(segment, col_set=\"feature\", data_key=DataHandlerLP.DK_I)\n        return pd.Series(self.model.predict(x_test.values), index=x_test.index)\n\n    def get_feature_importance(self, *args, **kwargs) -> pd.Series:\n        \"\"\"get feature importance\n\n        Notes\n        -----\n            parameters references:\n            https://catboost.ai/docs/concepts/python-reference_catboost_get_feature_importance.html#python-reference_catboost_get_feature_importance\n        \"\"\"\n        return pd.Series(\n            data=self.model.get_feature_importance(*args, **kwargs), index=self.model.feature_names_\n        ).sort_values(ascending=False)\n\n\nif __name__ == \"__main__\":\n    cat = CatBoostModel()","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/catboost_model.py#L64-L100","documentation":"Thrown by CatBoostModel.predict when self.model is None, i.e. predict is called before fit ever ran. The model attribute only gets a CatBoost instance inside fit, so predicting from a freshly constructed (or failed-to-fit) CatBoostModel is rejected.","triggerScenarios":"Instantiating CatBoostModel and calling predict(dataset) directly; a fit call that raised earlier (e.g. empty data) leaving self.model unset, followed by predict in a finally/except block; serializing/deserializing incorrectly so model is lost.","commonSituations":"Running a backtest/workflow where the model section was skipped; an exception in fit being swallowed and the pipeline continuing to the prediction stage.","solutions":["Call model.fit(dataset) before model.predict(dataset)","If fit previously failed, fix the underlying fit error (often 'Empty data from dataset') before predicting","When loading a dumped model, ensure you restore the fitted object, not a fresh instance"],"exampleFix":"# before\nmodel = CatBoostModel()\npred = model.predict(dataset)  # ValueError: model is not fitted yet!\n\n# after\nmodel = CatBoostModel()\nmodel.fit(dataset)\npred = model.predict(dataset)","handlingStrategy":"validation","validationCode":"assert model.model is not None, \"fit() must run before predict()\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat fit as a hard prerequisite; abort the pipeline if fit raises instead of continuing to predict","Check model.model is not None before predicting in long-running experiment loops"],"tags":["catboost","lifecycle","fit-before-predict","qlib"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}