DavidJyes commited on
Commit
7b8184f
·
verified ·
1 Parent(s): c2224ec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +3 -49
app.py CHANGED
@@ -8,7 +8,7 @@ from fastapi.responses import RedirectResponse
8
  from pydantic import BaseModel, Field
9
  from sklearn.base import BaseEstimator, TransformerMixin
10
 
11
- # --- 1. CLASSE PERSONNALISÉE (CORRECTION DU HASHING) ---
12
  class DFToHashedTokens(BaseEstimator, TransformerMixin):
13
  def __init__(self, columns=None):
14
  self.columns = columns
@@ -17,29 +17,21 @@ class DFToHashedTokens(BaseEstimator, TransformerMixin):
17
  return self
18
 
19
  def transform(self, X):
20
- # On s'assure que X est un DataFrame
21
  if not isinstance(X, pd.DataFrame):
22
  X = pd.DataFrame(X)
23
-
24
  X = X.copy()
25
  cols = getattr(self, 'columns', None)
26
-
27
  if cols is not None:
28
- # Pour chaque ligne, on crée une liste de chaînes de caractères
29
- # C'est ce que "iterable over iterables of strings" signifie
30
  return X[cols].astype(str).values.tolist()
31
  return X.astype(str).values.tolist()
32
 
33
- # Injection pour que joblib retrouve la classe
34
  __main__.DFToHashedTokens = DFToHashedTokens
35
 
36
  # --- 2. CHARGEMENT DU MODÈLE ---
37
  try:
38
  model = joblib.load('fraud_model_hashing.pkl')
39
- print("✅ Modèle chargé avec succès")
40
  except Exception as e:
41
  model = None
42
- print(f"❌ Erreur critique : {e}")
43
 
44
  # --- 3. CONFIGURATION API ---
45
  app = FastAPI(title="Fraud Detection API")
@@ -67,13 +59,11 @@ def root():
67
  # --- 4. LOGIQUE DE PRÉPARATION ---
68
  def prepare_input(data: dict):
69
  df = pd.DataFrame([data])
70
-
71
- # Dates & Temps
72
  dt = pd.to_datetime(df["trans_date_trans_time"], errors='coerce')
73
  dob = pd.to_datetime(df["dob"], errors='coerce')
74
 
75
  if dt.isna().any() or dob.isna().any():
76
- raise ValueError("Format de date invalide. Utilisez YYYY-MM-DD HH:MM:SS")
77
 
78
  df["hour"] = dt.dt.hour
79
  df["day_of_week"] = dt.dt.dayofweek
@@ -81,41 +71,5 @@ def prepare_input(data: dict):
81
  df["month"] = dt.dt.month
82
  df["age"] = ((dt - dob).dt.days / 365.25).astype("float32")
83
 
84
- # Distance
85
  lat1, lon1 = np.radians(df["lat"]), np.radians(df["long"])
86
- lat2, lon2 = np.radians(df["merch_lat"]), np.radians(df["merch_long"])
87
- d = np.sin((lat2-lat1)/2)**2 + np.cos(lat1)*np.cos(lat2)*np.sin((lon2-lon1)/2)**2
88
- df["distance"] = (6371 * 2 * np.arcsin(np.sqrt(d))).astype("float32")
89
-
90
- # Valeurs par défaut pour les agrégats
91
- df["avg_amt"] = df["amt"]
92
- df["std_amt"] = 0.0
93
- df["nb_trans"] = 1.0
94
-
95
- expected_cols = [
96
- 'amt', 'hour', 'day_of_week', 'day', 'month', 'age', 'lat', 'long',
97
- 'city_pop', 'distance', 'avg_amt', 'std_amt', 'nb_trans',
98
- 'category', 'gender', 'state', 'merchant', 'job'
99
- ]
100
- return df[expected_cols]
101
-
102
- # --- 5. ENDPOINT ---
103
- @app.post("/predict")
104
- def predict(data: Transaction):
105
- if model is None:
106
- return {"status": "error", "message": "Modèle non chargé."}
107
- try:
108
- X_processed = prepare_input(data.dict())
109
- # Le modèle Pipeline appellera automatiquement DFToHashedTokens.transform()
110
- prediction = model.predict(X_processed)
111
- return {
112
- "prediction": int(prediction[0]),
113
- "label": "FRAUDE" if int(prediction[0]) == 1 else "LÉGITIME",
114
- "status": "success"
115
- }
116
- except Exception as e:
117
- return {"status": "error", "message": str(e)}
118
-
119
- if __name__ == "__main__":
120
- import uvicorn
121
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
8
  from pydantic import BaseModel, Field
9
  from sklearn.base import BaseEstimator, TransformerMixin
10
 
11
+ # --- 1. CLASSE PERSONNALISÉE ---
12
  class DFToHashedTokens(BaseEstimator, TransformerMixin):
13
  def __init__(self, columns=None):
14
  self.columns = columns
 
17
  return self
18
 
19
  def transform(self, X):
 
20
  if not isinstance(X, pd.DataFrame):
21
  X = pd.DataFrame(X)
 
22
  X = X.copy()
23
  cols = getattr(self, 'columns', None)
 
24
  if cols is not None:
 
 
25
  return X[cols].astype(str).values.tolist()
26
  return X.astype(str).values.tolist()
27
 
 
28
  __main__.DFToHashedTokens = DFToHashedTokens
29
 
30
  # --- 2. CHARGEMENT DU MODÈLE ---
31
  try:
32
  model = joblib.load('fraud_model_hashing.pkl')
 
33
  except Exception as e:
34
  model = None
 
35
 
36
  # --- 3. CONFIGURATION API ---
37
  app = FastAPI(title="Fraud Detection API")
 
59
  # --- 4. LOGIQUE DE PRÉPARATION ---
60
  def prepare_input(data: dict):
61
  df = pd.DataFrame([data])
 
 
62
  dt = pd.to_datetime(df["trans_date_trans_time"], errors='coerce')
63
  dob = pd.to_datetime(df["dob"], errors='coerce')
64
 
65
  if dt.isna().any() or dob.isna().any():
66
+ raise ValueError("Format de date invalide.")
67
 
68
  df["hour"] = dt.dt.hour
69
  df["day_of_week"] = dt.dt.dayofweek
 
71
  df["month"] = dt.dt.month
72
  df["age"] = ((dt - dob).dt.days / 365.25).astype("float32")
73
 
 
74
  lat1, lon1 = np.radians(df["lat"]), np.radians(df["long"])
75
+ lat2, lon2 = np.radians