loanguard / src /models /catboost_model.py
adwitiyashukla's picture
update repo
44cd54e
Raw
History Blame Contribute Delete
2.31 kB
"""CatBoost fraud model - best out-of-the-box performance on categoricals."""
from __future__ import annotations
from typing import Any
import numpy as np
import pandas as pd
try:
from catboost import CatBoostClassifier # type: ignore
_CATBOOST_AVAILABLE = True
except ImportError: # pragma: no cover
CatBoostClassifier = None # type: ignore
_CATBOOST_AVAILABLE = False
from ..utils.logging import get_logger
from .base import FraudModel
log = get_logger(__name__)
class CatBoostFraudModel(FraudModel):
name = "catboost"
DEFAULT_PARAMS = {
"loss_function": "Logloss",
"eval_metric": "PRAUC",
"iterations": 800,
"depth": 6,
"learning_rate": 0.05,
"l2_leaf_reg": 3.0,
"auto_class_weights": "Balanced",
"random_seed": 42,
"verbose": False,
"allow_writing_files": False,
}
def __init__(self, params: dict | None = None, early_stopping_rounds: int = 50):
if not _CATBOOST_AVAILABLE:
raise ImportError(
"catboost is not installed. Install with `pip install catboost`."
)
self.params = {**self.DEFAULT_PARAMS, **(params or {})}
self.early_stopping_rounds = early_stopping_rounds
self.model: Any = None
self._trained = False
def fit(
self,
X: pd.DataFrame,
y: pd.Series | None = None,
eval_set: list[tuple[pd.DataFrame, pd.Series]] | None = None,
**kwargs,
) -> "CatBoostFraudModel":
if y is None:
raise ValueError("CatBoostFraudModel requires labels")
self.model = CatBoostClassifier(**self.params)
self.model.fit(
X,
y,
eval_set=eval_set[0] if eval_set else None,
early_stopping_rounds=self.early_stopping_rounds,
verbose=False,
)
self._trained = True
log.info(f"[CatBoost] trained. tree_count={self.model.tree_count_}")
return self
def predict_proba(self, X: pd.DataFrame) -> np.ndarray:
if not self._trained or self.model is None:
raise RuntimeError("Model not trained")
return self.model.predict_proba(X)[:, 1]
def get_params(self) -> dict[str, Any]:
return {"params": self.params}