Attrition_API / app.py
your_username
Deploy IBM Attrition FastAPI
f1b21db
Raw
History Blame Contribute Delete
3.96 kB
from fastapi import FastAPI
from pydantic import BaseModel
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
import numpy as np
import joblib
import os
# ------------------------------------------------------------------
# Initialisation de l'API
# ------------------------------------------------------------------
app = FastAPI(
title="IBM Attrition API",
description="API qui prédit si un employé va quitter l'entreprise.",
version="1.0",
)
# ------------------------------------------------------------------
# Définition du schéma des données d'entrée (avec Pydantic)
# ------------------------------------------------------------------
class Employee(BaseModel):
age: int
monthly_income: float
years_at_company: int
job_satisfaction: int # de 1 à 4
work_life_balance: int # de 1 à 4
overtime: int # 0 ou 1
# ------------------------------------------------------------------
# Entraînement (ou chargement) du modèle au démarrage de l'API
# ------------------------------------------------------------------
MODEL_PATH = "attrition_model.joblib"
SCALER_PATH = "attrition_scaler.joblib"
def train_dummy_model():
"""Entraîne un mini modèle de régression logistique sur des données synthétiques."""
rng = np.random.default_rng(seed=42)
n = 500
# Génération de données synthétiques cohérentes.
age = rng.integers(22, 60, n)
income = rng.normal(5000, 2000, n).clip(1000, 20000)
years = rng.integers(0, 30, n)
satisfaction = rng.integers(1, 5, n)
wlb = rng.integers(1, 5, n)
overtime = rng.integers(0, 2, n)
# Règle simple : risque d'attrition élevé si jeune, faible satisfaction, overtime.
risk = (
(60 - age) * 0.02
+ (5 - satisfaction) * 0.3
+ (5 - wlb) * 0.2
+ overtime * 0.5
- years * 0.05
)
proba = 1 / (1 + np.exp(-risk))
attrition = (rng.random(n) < proba).astype(int)
X = np.column_stack([age, income, years, satisfaction, wlb, overtime])
y = attrition
scaler = StandardScaler().fit(X)
X_scaled = scaler.transform(X)
model = LogisticRegression().fit(X_scaled, y)
joblib.dump(model, MODEL_PATH)
joblib.dump(scaler, SCALER_PATH)
return model, scaler
# On entraîne le modèle au démarrage si le fichier n'existe pas.
if os.path.exists(MODEL_PATH) and os.path.exists(SCALER_PATH):
model = joblib.load(MODEL_PATH)
scaler = joblib.load(SCALER_PATH)
else:
model, scaler = train_dummy_model()
# ------------------------------------------------------------------
# Endpoints de l'API
# ------------------------------------------------------------------
@app.get("/")
def root():
"""Page d'accueil avec les instructions."""
return {
"message": "IBM Attrition API",
"endpoints": {
"/predict": "POST avec les caractéristiques d'un employé pour prédire l'attrition",
"/docs": "Interface Swagger pour tester l'API",
},
}
@app.post("/predict")
def predict(employee: Employee):
"""Prédit la probabilité que l'employé quitte l'entreprise."""
features = np.array([[
employee.age,
employee.monthly_income,
employee.years_at_company,
employee.job_satisfaction,
employee.work_life_balance,
employee.overtime,
]])
features_scaled = scaler.transform(features)
proba = float(model.predict_proba(features_scaled)[0, 1])
prediction = int(proba >= 0.5)
return {
"attrition_probability": round(proba, 3),
"will_leave": bool(prediction),
"interpretation": (
"L'employé est à risque de quitter l'entreprise."
if prediction
else "L'employé devrait rester."
),
}
@app.get("/health")
def health():
"""Endpoint de santé pour vérifier que l'API tourne."""
return {"status": "ok"}