Spaces:
Sleeping
Sleeping
Download data_prep.py from OthmaneW/Detection-Fraude-PFA: direct link, hf CLI and curl.
- Browser
- Download file 8.65 kB
-
https://huggingface.co/spaces/OthmaneW/Detection-Fraude-PFA/resolve/main/data_prep.py
- Command line
-
hf download hf://spaces/OthmaneW/Detection-Fraude-PFA/data_prep.py
-
curl -L -o data_prep.py https://huggingface.co/spaces/OthmaneW/Detection-Fraude-PFA/resolve/main/data_prep.py
8.65 kB
| """ | |
| data_prep.py โ Pipeline de Prรฉparation des Donnรฉes | |
| ==================================================== | |
| PFA : Systรจme de Dรฉtection d'Anomalies dans les Transactions Financiรจres | |
| Auteurs : Othmane & Ramzi | |
| Dataset : Kaggle Credit Card Fraud Detection (creditcard.csv) | |
| Sortie : Datasets transformรฉs dans ./data/ (format .pkl) | |
| Usage : python data_prep.py | |
| """ | |
| import os | |
| import joblib | |
| import pandas as pd | |
| import numpy as np | |
| from sklearn.model_selection import train_test_split | |
| from sklearn.preprocessing import StandardScaler | |
| from imblearn.over_sampling import SMOTE | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # Configuration | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| DATA_DIR = os.path.join(os.path.dirname(__file__), "data") | |
| CSV_PATH = os.path.join(os.path.dirname(__file__), "creditcard.csv") | |
| RANDOM_STATE = 42 | |
| TEST_SIZE = 0.2 | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # 1. Chargement des donnรฉes | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| def load_data(path: str) -> pd.DataFrame: | |
| """Charge le CSV et affiche les statistiques de base.""" | |
| print(f"[1/5] Chargement du dataset : {path}") | |
| df = pd.read_csv(path) | |
| print(f" Shape : {df.shape}") | |
| print(f" Colonnes : {list(df.columns)}") | |
| print(f" Valeurs NaN : {df.isnull().sum().sum()}") | |
| n_fraud = (df["Class"] == 1).sum() | |
| n_legit = (df["Class"] == 0).sum() | |
| pct_fraud = n_fraud / len(df) * 100 | |
| print(f"\n Distribution des classes :") | |
| print(f" Lรฉgitimes (0) : {n_legit:,} ({100 - pct_fraud:.2f}%)") | |
| print(f" Fraudes (1) : {n_fraud:,} ({pct_fraud:.4f}%)") | |
| return df | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # 2. Prรฉprocessing | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| def preprocess(df: pd.DataFrame) -> tuple[pd.DataFrame, pd.Series, StandardScaler]: | |
| """ | |
| Normalise les colonnes 'Time' et 'Amount' avec StandardScaler. | |
| Les features V1โV28 sont dรฉjร normalisรฉes (rรฉsultat de PCA sur le dataset original). | |
| Retourne : X (features), y (labels), scaler (pour rรฉutilisation en infรฉrence) | |
| """ | |
| print("\n[2/5] Prรฉprocessing โ Normalisation de Time et Amount") | |
| df = df.copy() | |
| scaler = StandardScaler() | |
| df[["Time", "Amount"]] = scaler.fit_transform(df[["Time", "Amount"]]) | |
| X = df.drop(columns=["Class"]) | |
| y = df["Class"] | |
| print(f" Features : {X.shape[1]} colonnes") | |
| print(f" Target : 'Class' (0=Lรฉgitime, 1=Fraude)") | |
| return X, y, scaler | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # 3. Split Train / Test | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| def split_data( | |
| X: pd.DataFrame, | |
| y: pd.Series, | |
| test_size: float = TEST_SIZE, | |
| random_state: int = RANDOM_STATE, | |
| ) -> tuple: | |
| """ | |
| Split stratifiรฉ 80/20. | |
| La stratification garantit que la proportion de fraudes est prรฉservรฉe | |
| dans les deux splits, malgrรฉ le dรฉsรฉquilibre extrรชme du dataset. | |
| """ | |
| print(f"\n[3/5] Split Train/Test (stratifiรฉ, test_size={test_size})") | |
| X_train, X_test, y_train, y_test = train_test_split( | |
| X, y, | |
| test_size=test_size, | |
| random_state=random_state, | |
| stratify=y, | |
| ) | |
| print(f" Train : {X_train.shape[0]:,} samples " | |
| f"(fraudes : {y_train.sum():,} โ {y_train.mean()*100:.4f}%)") | |
| print(f" Test : {X_test.shape[0]:,} samples " | |
| f"(fraudes : {y_test.sum():,} โ {y_test.mean()*100:.4f}%)") | |
| return X_train, X_test, y_train, y_test | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # 4. SMOTE โ Rรฉรฉquilibrage (Train uniquement !) | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| def apply_smote( | |
| X_train: pd.DataFrame, | |
| y_train: pd.Series, | |
| random_state: int = RANDOM_STATE, | |
| ) -> tuple[pd.DataFrame, pd.Series]: | |
| """ | |
| Applique SMOTE sur le jeu d'entraรฎnement UNIQUEMENT. | |
| Raison critique : Appliquer SMOTE sur le test set provoquerait du | |
| data leakage et des mรฉtriques artificiellement gonflรฉes. Le test | |
| set doit rester dans sa distribution naturelle (dรฉsรฉquilibrรฉe) | |
| pour simuler des conditions rรฉelles de dรฉtection. | |
| """ | |
| print("\n[4/5] Application de SMOTE (sur X_train/y_train uniquement)") | |
| print(f" Avant SMOTE : {y_train.value_counts().to_dict()}") | |
| smote = SMOTE(random_state=random_state) | |
| X_train_res, y_train_res = smote.fit_resample(X_train, y_train) | |
| print(f" Aprรจs SMOTE : {pd.Series(y_train_res).value_counts().to_dict()}") | |
| print(f" Ratio : 1:1 (parfaitement รฉquilibrรฉ)") | |
| return X_train_res, y_train_res | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # 5. Sauvegarde des Artifacts | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| def save_artifacts( | |
| X_train: pd.DataFrame | np.ndarray, | |
| X_test: pd.DataFrame | np.ndarray, | |
| y_train: pd.Series | np.ndarray, | |
| y_test: pd.Series | np.ndarray, | |
| scaler: StandardScaler, | |
| ) -> None: | |
| """Sauvegarde tous les artifacts dans ./data/ au format .pkl.""" | |
| print(f"\n[5/5] Sauvegarde dans : {DATA_DIR}/") | |
| os.makedirs(DATA_DIR, exist_ok=True) | |
| artifacts = { | |
| "X_train_balanced.pkl": X_train, | |
| "X_test.pkl": X_test, | |
| "y_train_balanced.pkl": y_train, | |
| "y_test.pkl": y_test, | |
| "scaler.pkl": scaler, | |
| } | |
| for filename, obj in artifacts.items(): | |
| path = os.path.join(DATA_DIR, filename) | |
| joblib.dump(obj, path) | |
| size_mb = os.path.getsize(path) / 1_000_000 | |
| print(f" [OK] {filename:<30} ({size_mb:.2f} MB)") | |
| print("\n[DONE] Pipeline de donnees terminee avec succes.") | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| # Main | |
| # โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| def main(): | |
| print("=" * 60) | |
| print(" PFA โ Pipeline de Prรฉparation des Donnรฉes") | |
| print("=" * 60) | |
| # 1. Chargement | |
| df = load_data(CSV_PATH) | |
| # 2. Prรฉprocessing | |
| X, y, scaler = preprocess(df) | |
| # 3. Split | |
| X_train, X_test, y_train, y_test = split_data(X, y) | |
| # 4. SMOTE (train uniquement) | |
| X_train_balanced, y_train_balanced = apply_smote(X_train, y_train) | |
| # 5. Sauvegarde | |
| save_artifacts(X_train_balanced, X_test, y_train_balanced, y_test, scaler) | |
| print("\n--- Recapitulatif final ---") | |
| print(f" X_train_balanced : {X_train_balanced.shape}") | |
| print(f" X_test : {X_test.shape}") | |
| print(f" y_train_balanced : {pd.Series(y_train_balanced).value_counts().to_dict()}") | |
| print(f" y_test : {y_test.value_counts().to_dict()}") | |
| if __name__ == "__main__": | |
| main() | |