fioriclass commited on
Commit
1a758de
·
1 Parent(s): 513cd3c
src/base_trainer.py CHANGED
@@ -3,7 +3,7 @@
3
  # =========================
4
 
5
  from abc import ABC, abstractmethod
6
- from typing import Union, Optional, TYPE_CHECKING
7
  import cupy as cp
8
  from scipy.sparse import csr_matrix
9
 
@@ -55,10 +55,12 @@ class BaseTrainer(ABC):
55
  pass
56
 
57
  @abstractmethod
58
- def evaluate(self) -> None:
59
  """
60
  Méthode abstraite. Évalue le modèle entraîné, par exemple
61
  sur un jeu de validation ou de test, et calcule les métriques.
 
 
62
  """
63
  pass
64
 
@@ -114,7 +116,14 @@ class BaseTrainer(ABC):
114
  Implementé ici en tant que méthode non-abstraite, mais la logique de logging
115
  devrait être assurée dans l'environnement MLflow approprié.
116
  """
117
- pass
 
 
 
 
 
 
 
118
 
119
  def _prepare_input_for_fit(
120
  self, X: Union[cp.ndarray,
 
3
  # =========================
4
 
5
  from abc import ABC, abstractmethod
6
+ from typing import Union, Optional
7
  import cupy as cp
8
  from scipy.sparse import csr_matrix
9
 
 
55
  pass
56
 
57
  @abstractmethod
58
+ def evaluate(self) -> dict:
59
  """
60
  Méthode abstraite. Évalue le modèle entraîné, par exemple
61
  sur un jeu de validation ou de test, et calcule les métriques.
62
+
63
+ :return: Dictionnaire contenant les métriques calculées.
64
  """
65
  pass
66
 
 
116
  Implementé ici en tant que méthode non-abstraite, mais la logique de logging
117
  devrait être assurée dans l'environnement MLflow approprié.
118
  """
119
+ import mlflow
120
+ # Logue les paramètres du config.model
121
+ if self.config.model.params:
122
+ mlflow.log_params(self.config.model.params)
123
+
124
+ # Logue aussi les hyperparamètres du classifieur s'il offre get_params()
125
+ if self.classifier and hasattr(self.classifier, "get_params"):
126
+ mlflow.log_params(self.classifier.get_params())
127
 
128
  def _prepare_input_for_fit(
129
  self, X: Union[cp.ndarray,
src/cuml_trainer.py CHANGED
@@ -57,7 +57,9 @@ class CuMLTrainer(BaseTrainer, ABC):
57
  data = cudf.read_csv(self.data_path)
58
 
59
  # Séparation des textes et des étiquettes
60
- texts = data.drop(columns=[self.target_column])
 
 
61
  labels = data[self.target_column].values
62
 
63
  # Vectorisation des textes
@@ -66,7 +68,7 @@ class CuMLTrainer(BaseTrainer, ABC):
66
  # Entraînement du modèle
67
  self.classifier.fit(X_prepared, labels)
68
 
69
- def evaluate(self) -> None:
70
  """
71
  Évalue le classifieur et calcule les métriques.
72
  Cette implémentation générique fonctionne pour tous les trainers cuML.
@@ -75,7 +77,9 @@ class CuMLTrainer(BaseTrainer, ABC):
75
  data = cudf.read_csv(self.data_path)
76
 
77
  # Séparation des textes et des étiquettes
78
- texts = data.drop(columns=[self.target_column])
 
 
79
  y_true = data[self.target_column].values
80
 
81
  # Vectorisation et prédiction
@@ -93,6 +97,8 @@ class CuMLTrainer(BaseTrainer, ABC):
93
 
94
  # Afficher les résultats
95
  print(f"Métriques d'évaluation {prefix}: {metrics}")
 
 
96
 
97
  def _prepare_input_for_fit(self, X: Union[cp.ndarray,
98
  csr_matrix]) -> cp.ndarray:
 
57
  data = cudf.read_csv(self.data_path)
58
 
59
  # Séparation des textes et des étiquettes
60
+ # Supposons que la colonne de texte est la première colonne qui n'est pas la colonne cible
61
+ text_column = [col for col in data.columns if col != self.target_column][0]
62
+ texts = data[text_column] # Extraire la série de texte
63
  labels = data[self.target_column].values
64
 
65
  # Vectorisation des textes
 
68
  # Entraînement du modèle
69
  self.classifier.fit(X_prepared, labels)
70
 
71
+ def evaluate(self) -> dict:
72
  """
73
  Évalue le classifieur et calcule les métriques.
74
  Cette implémentation générique fonctionne pour tous les trainers cuML.
 
77
  data = cudf.read_csv(self.data_path)
78
 
79
  # Séparation des textes et des étiquettes
80
+ # Supposons que la colonne de texte est la première colonne qui n'est pas la colonne cible
81
+ text_column = [col for col in data.columns if col != self.target_column][0]
82
+ texts = data[text_column] # Extraire la série de texte
83
  y_true = data[self.target_column].values
84
 
85
  # Vectorisation et prédiction
 
97
 
98
  # Afficher les résultats
99
  print(f"Métriques d'évaluation {prefix}: {metrics}")
100
+
101
+ return metrics
102
 
103
  def _prepare_input_for_fit(self, X: Union[cp.ndarray,
104
  csr_matrix]) -> cp.ndarray:
src/main.py CHANGED
@@ -24,6 +24,7 @@ from mlflow_integration.mlflow_decorator import MLflowDecorator
24
 
25
  # Import de la configuration
26
  from config import Config
 
27
 
28
  # Configuration du logging
29
  logger = logging.getLogger(__name__)
@@ -40,7 +41,7 @@ def get_trainer(config: Config):
40
  Une instance concrète de BaseTrainer
41
  """
42
  model_type = config.model.type.lower()
43
-
44
  # Mapping des types de modèles vers leurs trainers
45
  trainer_map = {
46
  "svm": SvmTrainer,
@@ -49,10 +50,10 @@ def get_trainer(config: Config):
49
  "linear_regression": LinearRegressionTrainer,
50
  "transformer": HuggingFaceTransformerTrainer,
51
  }
52
-
53
  if model_type not in trainer_map:
54
  raise ValueError(f"Type de modèle non supporté: {model_type}")
55
-
56
  # Création de l'instance du trainer avec la configuration
57
  trainer_class = trainer_map[model_type]
58
  return trainer_class(
@@ -73,16 +74,16 @@ def get_optimizer(config: Config):
73
  Une instance concrète de HyperparameterOptimizer
74
  """
75
  optimizer_type = config.hyperparameters.optimizer.lower()
76
-
77
  # Mapping des types d'optimizers
78
  optimizer_map = {
79
  "optuna": OptunaOptimizer,
80
  "raytune": RayTuneOptimizer,
81
  }
82
-
83
  if optimizer_type not in optimizer_map:
84
  raise ValueError(f"Type d'optimizer non supporté: {optimizer_type}")
85
-
86
  # Création de l'instance de l'optimizer
87
  optimizer_class = optimizer_map[optimizer_type]
88
  return optimizer_class()
@@ -99,16 +100,17 @@ def main(cfg: DictConfig) -> None:
99
  # Conversion de la configuration Hydra en configuration Pydantic
100
  config_dict = OmegaConf.to_container(cfg, resolve=True)
101
  config = Config(**config_dict)
102
-
103
  logger.info(f"Configuration chargée: {config}")
104
-
105
  # Création du trainer approprié
106
  trainer = get_trainer(config)
107
-
108
  # Construction des composants (vectorizer, classifier, etc.)
109
  trainer.build_components()
110
-
111
-
 
112
  mlflow_decorator = MLflowDecorator(
113
  experiment_name=config.mlflow.experiment_name,
114
  tracking_uri=config.mlflow.tracking_uri
@@ -117,23 +119,20 @@ def main(cfg: DictConfig) -> None:
117
  train_with_mlflow = mlflow_decorator(trainer.train)
118
  evaluate_with_mlflow = mlflow_decorator(trainer.evaluate)
119
  log_params_with_mlflow = mlflow_decorator(trainer.log_parameters_to_mlflow)
120
- optimize_if_needed_with_mlflow = mlflow_decorator(trainer.optimize_if_needed) # Décorer aussi l'optimisation
121
-
122
  logger.info("Vérification et lancement de l'optimisation des hyperparamètres si nécessaire (avec MLflow)...")
123
  optimize_if_needed_with_mlflow()
124
-
125
- # Exécuter l'entraînement (toujours avec MLflow)
126
  logger.info("Lancement de l'entraînement avec MLflow...")
127
  train_with_mlflow()
128
-
129
- # Exécuter l'évaluation (toujours avec MLflow)
130
  logger.info("Lancement de l'évaluation avec MLflow...")
131
  evaluate_with_mlflow()
132
 
133
- # Logger les paramètres (toujours avec MLflow)
134
  logger.info("Logging des paramètres avec MLflow...")
135
  log_params_with_mlflow()
136
-
137
  logger.info("Entraînement, évaluation et logging des paramètres terminés avec succès via MLflow.")
138
 
139
 
 
24
 
25
  # Import de la configuration
26
  from config import Config
27
+ import mlflow
28
 
29
  # Configuration du logging
30
  logger = logging.getLogger(__name__)
 
41
  Une instance concrète de BaseTrainer
42
  """
43
  model_type = config.model.type.lower()
44
+
45
  # Mapping des types de modèles vers leurs trainers
46
  trainer_map = {
47
  "svm": SvmTrainer,
 
50
  "linear_regression": LinearRegressionTrainer,
51
  "transformer": HuggingFaceTransformerTrainer,
52
  }
53
+
54
  if model_type not in trainer_map:
55
  raise ValueError(f"Type de modèle non supporté: {model_type}")
56
+
57
  # Création de l'instance du trainer avec la configuration
58
  trainer_class = trainer_map[model_type]
59
  return trainer_class(
 
74
  Une instance concrète de HyperparameterOptimizer
75
  """
76
  optimizer_type = config.hyperparameters.optimizer.lower()
77
+
78
  # Mapping des types d'optimizers
79
  optimizer_map = {
80
  "optuna": OptunaOptimizer,
81
  "raytune": RayTuneOptimizer,
82
  }
83
+
84
  if optimizer_type not in optimizer_map:
85
  raise ValueError(f"Type d'optimizer non supporté: {optimizer_type}")
86
+
87
  # Création de l'instance de l'optimizer
88
  optimizer_class = optimizer_map[optimizer_type]
89
  return optimizer_class()
 
100
  # Conversion de la configuration Hydra en configuration Pydantic
101
  config_dict = OmegaConf.to_container(cfg, resolve=True)
102
  config = Config(**config_dict)
103
+
104
  logger.info(f"Configuration chargée: {config}")
105
+
106
  # Création du trainer approprié
107
  trainer = get_trainer(config)
108
+
109
  # Construction des composants (vectorizer, classifier, etc.)
110
  trainer.build_components()
111
+
112
+
113
+
114
  mlflow_decorator = MLflowDecorator(
115
  experiment_name=config.mlflow.experiment_name,
116
  tracking_uri=config.mlflow.tracking_uri
 
119
  train_with_mlflow = mlflow_decorator(trainer.train)
120
  evaluate_with_mlflow = mlflow_decorator(trainer.evaluate)
121
  log_params_with_mlflow = mlflow_decorator(trainer.log_parameters_to_mlflow)
122
+ optimize_if_needed_with_mlflow = mlflow_decorator(trainer.optimize_if_needed)
123
+
124
  logger.info("Vérification et lancement de l'optimisation des hyperparamètres si nécessaire (avec MLflow)...")
125
  optimize_if_needed_with_mlflow()
126
+
 
127
  logger.info("Lancement de l'entraînement avec MLflow...")
128
  train_with_mlflow()
129
+
 
130
  logger.info("Lancement de l'évaluation avec MLflow...")
131
  evaluate_with_mlflow()
132
 
 
133
  logger.info("Logging des paramètres avec MLflow...")
134
  log_params_with_mlflow()
135
+
136
  logger.info("Entraînement, évaluation et logging des paramètres terminés avec succès via MLflow.")
137
 
138
 
src/mlflow_integration/mlflow_decorator.py CHANGED
@@ -36,7 +36,7 @@ class MLflowDecorator:
36
  def wrapper(*args, **kwargs):
37
  mlflow.set_tracking_uri(self.tracking_uri)
38
  mlflow.set_experiment(self.experiment_name)
39
- with mlflow.start_run():
40
  result = func(*args, **kwargs)
41
  return result
42
 
 
36
  def wrapper(*args, **kwargs):
37
  mlflow.set_tracking_uri(self.tracking_uri)
38
  mlflow.set_experiment(self.experiment_name)
39
+ with mlflow.start_run(log_system_metrics=True):
40
  result = func(*args, **kwargs)
41
  return result
42
 
src/trainers/cuml/linear_regression_trainer.py CHANGED
@@ -68,13 +68,15 @@ class LinearRegressionTrainer(CuMLTrainer):
68
  # Inheriting from CuMLTrainer => loads data, vectorizes, fits
69
  super().train()
70
 
71
- def evaluate(self) -> None:
72
  """
73
  Évalue le classifieur LinearRegression et calcule les métriques appropriées.
74
 
75
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
76
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
77
  et du calcul des métriques via le metrics_calculator.
 
 
78
  """
79
  # Inheriting from CuMLTrainer => loads data, vectorizes, calls the metrics calculator
80
- super().evaluate()
 
68
  # Inheriting from CuMLTrainer => loads data, vectorizes, fits
69
  super().train()
70
 
71
+ def evaluate(self) -> dict:
72
  """
73
  Évalue le classifieur LinearRegression et calcule les métriques appropriées.
74
 
75
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
76
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
77
  et du calcul des métriques via le metrics_calculator.
78
+
79
+ :return: Dictionnaire contenant les métriques calculées.
80
  """
81
  # Inheriting from CuMLTrainer => loads data, vectorizes, calls the metrics calculator
82
+ return super().evaluate()
src/trainers/cuml/logistic_regression_trainer.py CHANGED
@@ -67,12 +67,14 @@ class LogisticRegressionTrainer(CuMLTrainer):
67
  """
68
  super().train()
69
 
70
- def evaluate(self) -> None:
71
  """
72
  Évalue le classifieur LogisticRegression et calcule les métriques appropriées.
73
 
74
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
75
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
76
  et du calcul des métriques via le metrics_calculator.
 
 
77
  """
78
- super().evaluate()
 
67
  """
68
  super().train()
69
 
70
+ def evaluate(self) -> dict:
71
  """
72
  Évalue le classifieur LogisticRegression et calcule les métriques appropriées.
73
 
74
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
75
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
76
  et du calcul des métriques via le metrics_calculator.
77
+
78
+ :return: Dictionnaire contenant les métriques calculées.
79
  """
80
+ return super().evaluate()
src/trainers/cuml/random_forest_trainer.py CHANGED
@@ -70,15 +70,17 @@ class RandomForestTrainer(CuMLTrainer):
70
  """
71
  super().train()
72
 
73
- def evaluate(self) -> None:
74
  """
75
  Évalue le classifieur RandomForest et calcule les métriques appropriées.
76
 
77
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
78
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
79
  et du calcul des métriques via le metrics_calculator.
 
 
80
  """
81
- super().evaluate()
82
 
83
  def _get_binary_predictions(self, X: cp.ndarray) -> cp.ndarray:
84
  """
 
70
  """
71
  super().train()
72
 
73
+ def evaluate(self) -> dict:
74
  """
75
  Évalue le classifieur RandomForest et calcule les métriques appropriées.
76
 
77
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
78
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
79
  et du calcul des métriques via le metrics_calculator.
80
+
81
+ :return: Dictionnaire contenant les métriques calculées.
82
  """
83
+ return super().evaluate()
84
 
85
  def _get_binary_predictions(self, X: cp.ndarray) -> cp.ndarray:
86
  """
src/trainers/cuml/svm_trainer.py CHANGED
@@ -70,15 +70,17 @@ class SvmTrainer(CuMLTrainer):
70
  """
71
  super().train()
72
 
73
- def evaluate(self) -> None:
74
  """
75
  Évalue le classifieur SVC et calcule les métriques appropriées.
76
 
77
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
78
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
79
  et du calcul des métriques via le metrics_calculator.
 
 
80
  """
81
- super().evaluate()
82
 
83
  def _get_binary_predictions(self, X: cp.ndarray) -> cp.ndarray:
84
  """
 
70
  """
71
  super().train()
72
 
73
+ def evaluate(self) -> dict:
74
  """
75
  Évalue le classifieur SVC et calcule les métriques appropriées.
76
 
77
  Utilise l'implémentation fournie par la classe parente CuMLTrainer,
78
  qui s'occupe du chargement des données, de la vectorisation, de la prédiction
79
  et du calcul des métriques via le metrics_calculator.
80
+
81
+ :return: Dictionnaire contenant les métriques calculées.
82
  """
83
+ return super().evaluate()
84
 
85
  def _get_binary_predictions(self, X: cp.ndarray) -> cp.ndarray:
86
  """
src/trainers/huggingface/huggingface_transformer_trainer.py CHANGED
@@ -62,12 +62,15 @@ class HuggingFaceTransformerTrainer(BaseTrainer):
62
  """
63
  pass
64
 
65
- def evaluate(self) -> None:
66
  """
67
  Évalue le modèle Hugging Face; la logique de calcul
68
  des métriques est en partie assurée par le HF Trainer.
 
 
69
  """
70
- pass
 
71
 
72
  def _create_torch_dataset(self, texts: cudf.Series,
73
  labels: cp.ndarray) -> torch.utils.data.Dataset:
 
62
  """
63
  pass
64
 
65
+ def evaluate(self) -> dict:
66
  """
67
  Évalue le modèle Hugging Face; la logique de calcul
68
  des métriques est en partie assurée par le HF Trainer.
69
+
70
+ :return: Dictionnaire contenant les métriques calculées.
71
  """
72
+ # À implémenter
73
+ return {}
74
 
75
  def _create_torch_dataset(self, texts: cudf.Series,
76
  labels: cp.ndarray) -> torch.utils.data.Dataset: