Spaces:
Sleeping
Sleeping
File size: 3,519 Bytes
fe22c25 4368d52 9772d68 a642ce8 c2224ec a642ce8 ca1611c 9772d68 7b8184f ca1611c c2224ec ca1611c a642ce8 c2224ec 9772d68 fe22c25 a642ce8 ca1611c fe22c25 a642ce8 c2224ec ca1611c a642ce8 9772d68 4368d52 9772d68 a642ce8 4368d52 a642ce8 7b8184f a642ce8 ca1611c 4368d52 fa0092c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | import sys
import pandas as pd
import numpy as np
import joblib
import __main__
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
from pydantic import BaseModel, Field
from sklearn.base import BaseEstimator, TransformerMixin
# --- 1. CLASSE PERSONNALISÉE ---
class DFToHashedTokens(BaseEstimator, TransformerMixin):
def __init__(self, columns=None):
self.columns = columns
def fit(self, X, y=None):
return self
def transform(self, X):
if not isinstance(X, pd.DataFrame):
X = pd.DataFrame(X)
X = X.copy()
cols = getattr(self, 'columns', None)
if cols is not None:
return X[cols].astype(str).values.tolist()
return X.astype(str).values.tolist()
__main__.DFToHashedTokens = DFToHashedTokens
# --- 2. CHARGEMENT DU MODÈLE ---
try:
model = joblib.load('fraud_model_hashing.pkl')
except Exception as e:
model = None
# --- 3. CONFIGURATION API ---
app = FastAPI(title="Fraud Detection API")
class Transaction(BaseModel):
amt: float = Field(..., example=85.20)
trans_date_trans_time: str = Field(..., example="2024-02-18 14:30:00")
dob: str = Field(..., example="1985-05-20")
lat: float = Field(..., example=48.8566)
long: float = Field(..., example=2.3522)
merch_lat: float = Field(..., example=48.8584)
merch_long: float = Field(..., example=2.2945)
city_pop: float = Field(..., example=2000000)
category: str = Field(..., example="shopping_net")
gender: str = Field(..., example="F")
state: str = Field(..., example="NY")
merchant: str = Field(..., example="Amazon")
job: str = Field(..., example="Data Scientist")
cc_num: int = Field(..., example=1234567890123456)
@app.get("/", include_in_schema=False)
def root():
return RedirectResponse(url="/docs")
# --- 4. LOGIQUE DE PRÉPARATION ---
def prepare_input(data: dict):
df = pd.DataFrame([data])
dt = pd.to_datetime(df["trans_date_trans_time"], errors='coerce')
dob = pd.to_datetime(df["dob"], errors='coerce')
if dt.isna().any() or dob.isna().any():
raise ValueError("Format de date invalide.")
df["hour"] = dt.dt.hour
df["day_of_week"] = dt.dt.dayofweek
df["day"] = dt.dt.day
df["month"] = dt.dt.month
df["age"] = ((dt - dob).dt.days / 365.25).astype("float32")
lat1, lon1 = np.radians(df["lat"]), np.radians(df["long"])
lat2, lon2 = np.radians(df["merch_lat"]), np.radians(df["merch_long"])
d = np.sin((lat2-lat1)/2)**2 + np.cos(lat1)*np.cos(lat2)*np.sin((lon2-lon1)/2)**2
df["distance"] = (6371 * 2 * np.arcsin(np.sqrt(d))).astype("float32")
df["avg_amt"] = df["amt"]
df["std_amt"] = 0.0
df["nb_trans"] = 1.0
expected_cols = [
'amt', 'hour', 'day_of_week', 'day', 'month', 'age', 'lat', 'long',
'city_pop', 'distance', 'avg_amt', 'std_amt', 'nb_trans',
'category', 'gender', 'state', 'merchant', 'job'
]
return df[expected_cols]
# --- 5. ENDPOINT NETTOYÉ ---
@app.post("/predict")
def predict(data: Transaction):
if model is None:
return {"error": "Modèle non chargé"}
try:
X_processed = prepare_input(data.dict())
prediction = model.predict(X_processed)
# On ne renvoie que la valeur brute
return int(prediction[0])
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860) |