FinRiskGuard / src /pipelines /predict_pipeline.py
Sarvarbek13's picture
Add src pipeline code
2d2a96b
Raw
History Blame Contribute Delete
8.6 kB
import json
import joblib
import numpy as np
import pandas as pd
from pathlib import Path
ROOT_DIR = Path(__file__).resolve().parents[2]
class FraudPredictor:
MODELS_DIR = ROOT_DIR / "outputs" / "models" / "fraud"
def __init__(self):
self.fe_artifacts = joblib.load(self.MODELS_DIR / "fe_artifacts.pkl")
self.prep_artifacts = joblib.load(self.MODELS_DIR / "prep_artifacts.pkl")
self.fs_artifacts = joblib.load(self.MODELS_DIR / "fs_artifacts.pkl")
self.model = joblib.load(self.MODELS_DIR / "fraud_model.pkl")
with open(self.MODELS_DIR / "fraud_model_metadata.json") as f:
self.metadata = json.load(f)
self.threshold = self.metadata["threshold"]
self.model_name = self.metadata["model_name"]
self.final_feats = self.fs_artifacts["final_features"]
def _apply_fe(self, df):
from src.features.ieee_cis.feature_engineer import feature_engineer_test
return feature_engineer_test(df, self.fe_artifacts)
def _apply_prep(self, df):
from src.data.ieee_cis.preprocessor import preprocess_test
return preprocess_test(df, self.prep_artifacts)
def _apply_fs(self, df):
missing = [c for c in self.final_feats if c not in df.columns]
for col in missing:
df[col] = 0.0
return df[self.final_feats]
def _predict_proba(self, X):
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
is_stacking = (
isinstance(self.model, LogisticRegression) or
isinstance(self.model, Pipeline)
)
if is_stacking:
xgb = joblib.load(self.MODELS_DIR / "tuned_xgb.pkl")
lgb = joblib.load(self.MODELS_DIR / "tuned_lgb.pkl")
cat = joblib.load(self.MODELS_DIR / "tuned_cat.pkl")
meta_input = np.column_stack([
xgb.predict_proba(X)[:, 1],
lgb.predict_proba(X)[:, 1],
cat.predict_proba(X)[:, 1],
])
return self.model.predict_proba(meta_input)[:, 1]
return self.model.predict_proba(X)[:, 1]
def predict(self, raw_df):
df = raw_df.copy()
df = self._apply_fe(df)
df = self._apply_prep(df)
# Barcha ustunlarni numeric qilib, xatolarni 0.0 bilan to'ldiramiz
df = df.apply(pd.to_numeric, errors="coerce").fillna(0.0)
X = self._apply_fs(df)
proba = self._predict_proba(X)
flags = (proba >= self.threshold).tolist()
proba_list = proba.tolist()
if len(proba_list) == 1:
return {
"fraud_probability": round(proba_list[0], 6),
"is_fraud": flags[0],
"threshold": self.threshold,
"model": self.model_name,
}
return {
"fraud_probability": [round(p, 6) for p in proba_list],
"is_fraud": flags,
"threshold": self.threshold,
"model": self.model_name,
}
def predict_single(self, transaction):
return self.predict(pd.DataFrame([transaction]))
def get_metadata(self):
return {
"model_name" : self.metadata["model_name"],
"auc_roc" : self.metadata["auc_roc"],
"auc_pr" : self.metadata["auc_pr"],
"f1" : self.metadata["f1"],
"precision" : self.metadata["precision"],
"recall" : self.metadata["recall"],
"threshold" : self.metadata["threshold"],
"features_used" : self.metadata["features_used"],
"class_imbalance": self.metadata["class_imbalance"],
"cv_method" : self.metadata["cv_method"],
"task" : "fraud_detection",
"dataset" : "IEEE-CIS (Vesta Corp)",
}
class CreditPredictor:
MODELS_DIR = ROOT_DIR / "outputs" / "models" / "credit"
def __init__(self):
self.fe_artifacts = joblib.load(self.MODELS_DIR / "fe_artifacts.pkl")
self.prep_artifacts = joblib.load(self.MODELS_DIR / "prep_artifacts.pkl")
self.fs_artifacts = joblib.load(self.MODELS_DIR / "fs_artifacts.pkl")
self.model = joblib.load(self.MODELS_DIR / "credit_model.pkl")
with open(self.MODELS_DIR / "credit_model_metadata.json") as f:
self.metadata = json.load(f)
self.threshold = self.metadata["threshold"]
self.model_name = self.metadata["model_name"]
self.final_feats = self.fs_artifacts["final_features"]
def _apply_fe(self, df):
from src.features.home_credit.feature_engineer import feature_engineer_test
empty_tables = {
"bureau" : pd.DataFrame(),
"bureau_balance": pd.DataFrame(),
"previous_app" : pd.DataFrame(),
"pos_cash" : pd.DataFrame(),
"installments" : pd.DataFrame(),
"credit_card" : pd.DataFrame(),
}
return feature_engineer_test(df, empty_tables, self.fe_artifacts)
def _apply_prep(self, df):
from src.data.home_credit.preprocessor import preprocess_test
return preprocess_test(df, self.prep_artifacts)
def _apply_fs(self, df):
missing = [c for c in self.final_feats if c not in df.columns]
for col in missing:
df[col] = 0.0
return df[self.final_feats]
def _predict_proba(self, X):
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
is_stacking = (
isinstance(self.model, LogisticRegression) or
isinstance(self.model, Pipeline)
)
if is_stacking:
xgb = joblib.load(self.MODELS_DIR / "tuned_xgb.pkl")
lgb = joblib.load(self.MODELS_DIR / "tuned_lgb.pkl")
cat = joblib.load(self.MODELS_DIR / "tuned_cat.pkl")
meta_input = np.column_stack([
xgb.predict_proba(X)[:, 1],
lgb.predict_proba(X)[:, 1],
cat.predict_proba(X)[:, 1],
])
return self.model.predict_proba(meta_input)[:, 1]
return self.model.predict_proba(X)[:, 1]
def predict(self, raw_df):
df = raw_df.copy()
df = self._apply_fe(df)
df = self._apply_prep(df)
# Barcha ustunlarni numeric qilib, xatolarni 0.0 bilan to'ldiramiz
df = df.apply(pd.to_numeric, errors="coerce").fillna(0.0)
X = self._apply_fs(df)
proba = self._predict_proba(X)
flags = (proba >= self.threshold).tolist()
proba_list = proba.tolist()
if len(proba_list) == 1:
return {
"default_probability": round(proba_list[0], 6),
"will_default": flags[0],
"threshold": self.threshold,
"model": self.model_name,
}
return {
"default_probability": [round(p, 6) for p in proba_list],
"will_default": flags,
"threshold": self.threshold,
"model": self.model_name,
}
def predict_single(self, applicant):
return self.predict(pd.DataFrame([applicant]))
def get_metadata(self):
return {
"model_name" : self.metadata["model_name"],
"auc_roc" : self.metadata["auc_roc"],
"auc_pr" : self.metadata["auc_pr"],
"f1" : self.metadata["f1"],
"precision" : self.metadata["precision"],
"recall" : self.metadata["recall"],
"threshold" : self.metadata["threshold"],
"features_used" : self.metadata["features_used"],
"class_imbalance": self.metadata["class_imbalance"],
"cv_method" : self.metadata["cv_method"],
"task" : "credit_default_scoring",
"dataset" : "Home Credit Default Risk",
}
_fraud_predictor = None
_credit_predictor = None
def get_fraud_predictor():
global _fraud_predictor
if _fraud_predictor is None:
_fraud_predictor = FraudPredictor()
return _fraud_predictor
def get_credit_predictor():
global _credit_predictor
if _credit_predictor is None:
_credit_predictor = CreditPredictor()
return _credit_predictor