Djohell commited on
Commit
de2aa99
·
1 Parent(s): cf9d30a
Files changed (5) hide show
  1. .gitignore +1 -0
  2. Dockerfile +30 -0
  3. README.md +5 -4
  4. model.py +228 -0
  5. requirements.txt +7 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .secrets
Dockerfile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ WORKDIR /home/app
4
+
5
+ # Installation des dépendances système
6
+ RUN apt-get update && apt-get install -y \
7
+ build-essential \
8
+ libpq-dev \
9
+ git \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Installation des dépendances Python
13
+ COPY requirements.txt requirements.txt
14
+ RUN pip install -r requirements.txt
15
+
16
+ # Exposition du port MLflow
17
+ EXPOSE 5000
18
+
19
+ # Définir les variables d'environnement pour AWS et MLflow
20
+ ENV AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
21
+ ENV AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
22
+ ENV BACKEND_STORE_URI=$BACKEND_STORE_URI
23
+ ENV MLFLOW_DEFAULT_ARTIFACT_ROOT=$MLFLOW_DEFAULT_ARTIFACT_ROOT
24
+
25
+
26
+ # Commande pour démarrer le serveur MLflow
27
+ CMD mlflow server -p $PORT \
28
+ --host 0.0.0.0 \
29
+ --backend-store-uri $BACKEND_STORE_URI \
30
+ --default-artifact-root $MLFLOW_DEFAULT_ARTIFACT_ROOT
README.md CHANGED
@@ -1,10 +1,11 @@
1
  ---
2
- title: Mlflow Projet Feux
3
- emoji: 🔥
4
- colorFrom: indigo
5
- colorTo: pink
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Mlflow Get
3
+ emoji: 🏃
4
+ colorFrom: pink
5
+ colorTo: blue
6
  sdk: docker
7
  pinned: false
8
+ license: apache-2.0
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
model.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import plotly.express as px
3
+ import matplotlib.pyplot as plt
4
+ import plotly.io as pio
5
+ import sklearn
6
+ import warnings
7
+ from scipy.special import expit, logit
8
+ import sksurv.datasets
9
+ import numpy as np
10
+ import joblib
11
+ import xgboost as xgb
12
+ from xgboost import XGBRegressor
13
+ from xgboost import XGBClassifier
14
+ from xgboost import DMatrix
15
+ from xgboost import train
16
+ from lifelines import CoxPHFitter
17
+ from itertools import product
18
+ from tqdm import tqdm
19
+ from xgbse import XGBSEKaplanNeighbors
20
+ from xgbse.converters import convert_to_structured
21
+ from sklearn.metrics import roc_auc_score
22
+ from sklearn.preprocessing import StandardScaler
23
+ from sklearn.impute import SimpleImputer
24
+ from sklearn.pipeline import Pipeline
25
+ from sklearn.model_selection import train_test_split
26
+ from sklearn.ensemble import RandomForestClassifier
27
+ from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
28
+ from sklearn.exceptions import UndefinedMetricWarning
29
+ from sklearn import set_config
30
+ from sklearn.model_selection import GridSearchCV, KFold
31
+ from sklearn.pipeline import make_pipeline
32
+ from sklearn.model_selection import ParameterGrid
33
+ from sksurv.datasets import load_breast_cancer
34
+ from sksurv.metrics import cumulative_dynamic_auc
35
+ from sksurv.metrics import concordance_index_censored
36
+ from sksurv.linear_model import CoxnetSurvivalAnalysis, CoxPHSurvivalAnalysis
37
+ from sksurv.preprocessing import OneHotEncoder
38
+ from sksurv.util import Surv
39
+ from dotenv import load_dotenv
40
+ import boto3
41
+ import mlflow
42
+ import os
43
+ import io
44
+
45
+ from sksurv.ensemble import GradientBoostingSurvivalAnalysis
46
+
47
+
48
+ load_dotenv(dotenv_path=".secrets")
49
+
50
+ mlflow.set_tracking_uri(os.getenv('BACKEND_STORE_URI=postgresql+psycopg2://neondb_owner:npg_GZ5FuPYjaf3b@ep-fancy-lab-adrdogpa-pooler.c-2.us-east-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require'))
51
+ os.environ['AWS_ACCESS_KEY_ID'] = os.getenv('AWS_ACCESS_KEY_ID')
52
+ os.environ['AWS_SECRET_ACCESS_KEY'] = os.getenv('AWS_SECRET_ACCESS_KEY')
53
+ os.environ['MLFLOW_DEFAULT_ARTIFACT_ROOT'] = os.getenv('MLFLOW_DEFAULT_ARTIFACT_ROOT')
54
+ os.environ['S3_BUCKET'] = os.getenv('S3_BUCKET')
55
+
56
+ # Log configurations au démarrage
57
+ print("=== Configuration MLflow ===")
58
+ print(f"Tracking URI: {mlflow.get_tracking_uri()}")
59
+ print(f"Artifact Store: {os.getenv('MLFLOW_DEFAULT_ARTIFACT_ROOT')}")
60
+ print(f"AWS Access: {'Configuré' if os.getenv('AWS_ACCESS_KEY_ID') else 'Manquant'}")
61
+
62
+ s3 = boto3.client('s3')
63
+ try:
64
+ response = s3.list_objects_v2(Bucket=os.getenv('S3_BUCKET'))
65
+ print("S3 contents:", response.get('Contents', []))
66
+ except Exception as e:
67
+ print("S3 error:", e)
68
+
69
+
70
+ warnings.filterwarnings("ignore", category=UndefinedMetricWarning)
71
+ set_config(display="text")
72
+
73
+ df=pd.read_csv('https://projet-feux-fullstack.s3.eu-west-3.amazonaws.com/datas/dataset_modele_decompte2.csv', sep=';', low_memory=False)
74
+ mask = df.Année == 2025
75
+ df = df[~mask]
76
+ df['Feu prévu'] = df['Feu prévu'].astype(bool)
77
+ df_clean = df.copy()
78
+
79
+ features = [
80
+ 'moyenne precipitations mois', 'moyenne temperature mois',
81
+ 'moyenne evapotranspiration mois', 'moyenne vitesse vent année',
82
+ 'moyenne vitesse vent mois', 'moyenne temperature année',
83
+ 'RR', 'UM', 'ETPMON', 'TN', 'TX', 'Nombre de feu par an',
84
+ 'Nombre de feu par mois', 'jours_sans_pluie', 'jours_TX_sup_30',
85
+ 'ETPGRILLE_7j',
86
+ 'compteur jours vers prochain feu','compteur feu log','Année', 'Mois',
87
+ 'moyenne precipitations année', 'moyenne evapotranspiration année'
88
+ ]
89
+ features = [f for f in features if f in df_clean.columns]
90
+
91
+ # Nous mettons à 0 les NAN de la colonne décompte
92
+ df_clean["décompte"] = df_clean["décompte"].fillna(0)
93
+
94
+
95
+ # 🔹 Préparation des données réelles
96
+ df_clean = df_clean.rename(columns={"Feu prévu": "event", "décompte": "duration"})
97
+ y_structured = Surv.from_dataframe("event", "duration", df_clean)
98
+
99
+ X = df_clean[features]
100
+ y = y_structured
101
+
102
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
103
+
104
+ event_train = y_train["event"]
105
+ duration_train = y_train["duration"]
106
+ event_test = y_test["event"]
107
+ duration_test = y_test["duration"]
108
+
109
+ # 🔹 Pipeline XGBoost survie avec StandardScaler
110
+ pipeline = Pipeline([
111
+ ("imputer", SimpleImputer(strategy="median")),
112
+ ("scaler", StandardScaler()),
113
+ ("xgb", XGBRegressor(
114
+ objective="survival:cox",
115
+ n_estimators=100,
116
+ learning_rate=0.05,
117
+ max_depth=3,
118
+ tree_method="hist",
119
+ device="cuda",
120
+ random_state=42
121
+ ))
122
+ ])
123
+
124
+
125
+
126
+ def train_evaluate_model_with_mlflow(model, X_train, X_test, y_train, y_test, model_name):
127
+ print(f"\n=== Démarrage entraînement {model_name} ===")
128
+ print(f"Tracking URI: {mlflow.get_tracking_uri()}")
129
+ print(f"Registry URI: {mlflow.get_registry_uri()}")
130
+
131
+ mlflow.set_experiment("fire_survival")
132
+ print(f"Experiment: fire_survival")
133
+ s3 = boto3.client('s3')
134
+
135
+ with mlflow.start_run() as run:
136
+ print(f"Run ID: {run.info.run_id}")
137
+
138
+ print("Entraînement du modèle...")
139
+ model.fit(X_train, duration_train, xgb__sample_weight=event_train)
140
+
141
+ #save model to S3
142
+ print("Enregistrement du modèle sur S3...")
143
+ model_path = f"mlflow/models/{model_name}_{run.info.run_id}.joblib"
144
+
145
+ # mlflow.sklearn.log_model(model, "model")
146
+
147
+ buffer = io.BytesIO()
148
+ joblib.dump(model, buffer)
149
+ s3.put_object(
150
+ Bucket=os.getenv('S3_BUCKET'),
151
+ Key=model_path,
152
+ Body=buffer.getvalue()
153
+ )
154
+ print("Modèle enregistré")
155
+
156
+ # 🔹 Prédictions réelles (log(HR)) sur données test
157
+ log_hr_test = model.predict(X_test)
158
+
159
+ # 🔹 Jeu factice pour estimer le modèle de Cox
160
+ df_fake = pd.DataFrame({
161
+ "duration": duration_train,
162
+ "event": event_train,
163
+ "const": 1
164
+ })
165
+ dtrain_fake = DMatrix(df_fake[["const"]])
166
+ dtrain_fake.set_float_info("label", df_fake["duration"])
167
+ dtrain_fake.set_float_info("label_lower_bound", df_fake["duration"])
168
+ dtrain_fake.set_float_info("label_upper_bound", df_fake["duration"])
169
+ dtrain_fake.set_float_info("weight", df_fake["event"])
170
+
171
+ params = {
172
+ "objective": "survival:cox",
173
+ "eval_metric": "cox-nloglik",
174
+ "learning_rate": 0.1,
175
+ "max_depth": 1,
176
+ "verbosity": 0
177
+ }
178
+ bst_fake = train(params, dtrain_fake, num_boost_round=100)
179
+
180
+ log_hr_fake = bst_fake.predict(dtrain_fake)
181
+ df_risque = pd.DataFrame({
182
+ "duration": duration_train,
183
+ "event": event_train,
184
+ "log_risque": log_hr_fake
185
+ })
186
+ # insertion de bruit pour aider le modèle à converger
187
+ df_risque["log_risque"] += np.random.normal(0, 1e-4, size=len(df_risque))
188
+
189
+ # 🔹 Modèle de Cox factice
190
+ cph = CoxPHFitter()
191
+ cph.fit(df_risque, duration_col="duration", event_col="event", show_progress=False)
192
+
193
+ # 🔹 Évaluation avec le c-index
194
+ c_index = concordance_index_censored(event_test, duration_test, log_hr_test)[0]
195
+ print(f"\nC-index (test) : {c_index:.3f}")
196
+
197
+
198
+ print("\nEnregistrement des métriques...")
199
+ mlflow.log_metric("c_index", c_index)
200
+
201
+
202
+ # mlflow.register_model(
203
+ # f"runs:/{run.info.run_id}/model",
204
+ # "fire_survival"
205
+ # )
206
+ # Exemple : une ligne de ton jeu de données
207
+ input_example = X_train.iloc[:1]
208
+ mlflow.sklearn.log_model(
209
+ sk_model=model,
210
+ artifact_path="model",
211
+ input_example=input_example
212
+ )
213
+
214
+ # 🔹 Enregistrer dans le Registry
215
+ result = mlflow.register_model(
216
+ model_uri=f"runs:/{run.info.run_id}/model",
217
+ name="fire_survival"
218
+ )
219
+ return model, run.info.run_id
220
+
221
+ if __name__ == "__main__":
222
+ xgb_final = pipeline
223
+ _, run_id = train_evaluate_model_with_mlflow(
224
+ xgb_final, X_train, X_test, y_train, y_test, "xgboost_survivalCOX_model"
225
+ )
226
+ print(f"Run ID: {run_id}")
227
+
228
+
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ mlflow==2.15.0
2
+ psycopg2-binary
3
+ boto3
4
+ sqlalchemy
5
+ scikit-learn
6
+ pandas
7
+ numpy