-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
51,830 additions
and
747 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
# Système de Recommandation d'Hôpitaux | ||
|
||
Ce dossier contient l'ensemble du système de machine learning pour la recommandation d'hôpitaux basée sur les pathologies et les besoins des patients. | ||
|
||
## Structure du Projet | ||
|
||
``` | ||
machine_learning/ | ||
├── classification_service/ # Classification du service médical approprié | ||
├── duration_prediction/ # Prédiction de la durée d'hospitalisation | ||
├── recommendation/ # Système de recommandation d'hôpitaux | ||
├── evaluation/ # Évaluation et validation des modèles | ||
│ ├── metrics.py # Métriques d'évaluation | ||
│ ├── temporal_validation.py # Validation temporelle | ||
│ ├── tests/ # Tests unitaires | ||
│ └── evaluate_models.ipynb # Notebook d'évaluation | ||
├── utils/ # Utilitaires et préparation des données | ||
└── model_development/ # Notebooks de développement | ||
``` | ||
|
||
## Description des Composants | ||
|
||
### 1. Classification des Services (`classification_service/`) | ||
- **service_classifier.py** : Module pour prédire le service médical approprié (M, C, SSR, O, ESND, PSY) | ||
- Utilise PyCaret pour l'entraînement automatisé | ||
- Inclut la gestion des encodeurs pour les variables catégorielles | ||
- Features : pathologie, tranches d'âge, taux standardisés, etc. | ||
|
||
### 2. Prédiction de Durée (`duration_prediction/`) | ||
- **duration_predictor.py** : Module pour estimer la durée d'hospitalisation | ||
- Optimisé pour la régression | ||
- Utilise des features spécifiques à la durée de séjour | ||
- Intègre le tuning automatique des hyperparamètres | ||
|
||
### 3. Système de Recommandation (`recommendation/`) | ||
- **hospital_recommender.py** : Système principal de recommandation | ||
- Combine les prédictions des différents modèles | ||
- Calcule des scores basés sur : | ||
- Distance géographique | ||
- Capacité d'accueil | ||
- Compatibilité des services | ||
- Durée estimée du séjour | ||
|
||
### 4. Évaluation (`evaluation/`) | ||
- **metrics.py** : Métriques personnalisées pour l'évaluation | ||
- Métriques de classification des services | ||
- Métriques de prédiction de durée | ||
- Métriques de qualité des recommandations | ||
- **temporal_validation.py** : Validation temporelle des modèles | ||
- Splits temporels des données | ||
- Analyse des tendances | ||
- Évaluation de la stabilité | ||
- **tests/** : Tests unitaires pour chaque composant | ||
- **evaluate_models.ipynb** : Notebook d'évaluation complète | ||
|
||
### 5. Utilitaires (`utils/`) | ||
- **data_preparation.py** : Préparation et chargement des données | ||
- Gestion de la connexion BigQuery | ||
- Préparation des features pour les modèles | ||
- Séparation train/test par années | ||
|
||
## État d'Avancement | ||
|
||
### Complété | ||
1. **Structure de Base** | ||
- Architecture modulaire | ||
- Intégration avec MLflow et PyCaret | ||
- Connexion BigQuery | ||
|
||
2. **Modèles de Base** | ||
- Classification des services | ||
- Prédiction de durée | ||
- Système de scoring | ||
|
||
3. **Évaluation** | ||
- Framework de métriques | ||
- Validation temporelle | ||
- Tests unitaires | ||
- Notebook d'évaluation | ||
|
||
### En Cours | ||
1. **Optimisation des Modèles** | ||
- [ ] Affiner les hyperparamètres | ||
- [ ] Optimiser les poids du système de scoring | ||
- [ ] Ajouter des features supplémentaires | ||
|
||
2. **Interface et Intégration** | ||
- [ ] Créer une API REST | ||
- [ ] Développer une interface utilisateur | ||
- [ ] Intégrer dans l'application principale | ||
|
||
### À Faire | ||
1. **Documentation et Maintenance** | ||
- [ ] Compléter la documentation utilisateur | ||
- [ ] Mettre en place le monitoring | ||
- [ ] Ajouter des exemples d'utilisation | ||
|
||
2. **Améliorations Futures** | ||
- [ ] Intégrer les avis patients | ||
- [ ] Ajouter des données en temps réel | ||
- [ ] Développer un système de feedback | ||
|
||
## Utilisation | ||
|
||
1. Installation des dépendances : | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
|
||
2. Configuration : | ||
- Configurer les credentials BigQuery | ||
- Initialiser MLflow pour le tracking des expériences | ||
|
||
3. Évaluation des modèles : | ||
```python | ||
# Exécuter le notebook d'évaluation | ||
jupyter notebook evaluation/evaluate_models.ipynb | ||
``` | ||
|
||
4. Utilisation du système : | ||
```python | ||
from recommendation.hospital_recommender import HospitalRecommender | ||
|
||
recommender = HospitalRecommender() | ||
recommender.load_models(service_run_id='...', duration_run_id='...') | ||
recommendations = recommender.predict(patient_data) | ||
``` | ||
|
||
## Dépendances Principales | ||
|
||
- PyCaret | ||
- MLflow | ||
- Google Cloud BigQuery | ||
- pandas | ||
- scikit-learn | ||
- geopy | ||
- pytest (pour les tests) | ||
- jupyter (pour les notebooks) | ||
|
||
## Contribution | ||
|
||
Pour contribuer au projet : | ||
1. Créer une nouvelle branche pour chaque feature | ||
2. Suivre les conventions de code établies | ||
3. Documenter les changements | ||
4. Soumettre une pull request | ||
|
||
## Contact | ||
|
||
Pour toute question ou suggestion, contacter l'équipe de développement. |
109 changes: 109 additions & 0 deletions
109
machine_learning/classification_service/service_classifier.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
from pycaret.classification import * | ||
import mlflow | ||
import pandas as pd | ||
from typing import Optional, Tuple, Dict | ||
from sklearn.preprocessing import LabelEncoder | ||
|
||
def prepare_service_data(data: pd.DataFrame) -> Tuple[pd.DataFrame, Dict]: | ||
""" | ||
Prépare les données pour la classification des services | ||
Args: | ||
data: DataFrame contenant les données brutes | ||
Returns: | ||
DataFrame préparé et dictionnaire des encodeurs | ||
""" | ||
# Sélectionner les colonnes pertinentes | ||
features = [ | ||
'pathologie', 'code_pathologie', 'nom_pathologie', | ||
'tranche_age_0_1', 'tranche_age_1_4', 'tranche_age_5_14', | ||
'tranche_age_15_24', 'tranche_age_25_34', 'tranche_age_35_44', | ||
'tranche_age_45_54', 'tranche_age_55_64', 'tranche_age_65_74', | ||
'tranche_age_75_84', 'tranche_age_85_et_plus', | ||
'tx_brut_tt_age_pour_mille', 'tx_standard_tt_age_pour_mille', | ||
'classification' # target variable | ||
] | ||
|
||
df = data[features].copy() | ||
|
||
# Créer les encodeurs pour les variables catégorielles | ||
encoders = {} | ||
categorical_features = ['pathologie', 'nom_pathologie', 'classification'] | ||
|
||
for feature in categorical_features: | ||
encoders[feature] = LabelEncoder() | ||
df[feature] = encoders[feature].fit_transform(df[feature]) | ||
|
||
return df, encoders | ||
|
||
def train_service_classifier( | ||
data: pd.DataFrame, | ||
target_col: str = 'classification', | ||
fold: int = 5, | ||
experiment_name: str = 'service_classification' | ||
) -> Tuple[object, Dict]: | ||
""" | ||
Entraîne un modèle de classification pour prédire le service médical approprié | ||
Args: | ||
data: DataFrame contenant les données d'entraînement | ||
target_col: Nom de la colonne cible (service médical) | ||
fold: Nombre de folds pour la validation croisée | ||
experiment_name: Nom de l'expérience MLflow | ||
Returns: | ||
Le meilleur modèle entraîné et les encodeurs utilisés | ||
""" | ||
try: | ||
# Préparer les données | ||
prepared_data, encoders = prepare_service_data(data) | ||
|
||
# Setup PyCaret sans MLflow | ||
clf_setup = setup( | ||
data=prepared_data, | ||
target=target_col, | ||
session_id=123, | ||
fold=fold, | ||
log_experiment=False, # Désactiver l'intégration MLflow de PyCaret | ||
verbose=False | ||
) | ||
|
||
# Entraîner le modèle | ||
best_model = compare_models(n_select=1) | ||
|
||
# Log manuel avec MLflow | ||
mlflow.set_experiment(experiment_name) | ||
with mlflow.start_run(): | ||
# Log des paramètres de base | ||
mlflow.log_param("target_col", target_col) | ||
mlflow.log_param("fold", fold) | ||
|
||
# Log des métriques de performance | ||
results = pull() | ||
for metric in results.columns[1:]: | ||
mlflow.log_metric(metric, results.iloc[0][metric]) | ||
|
||
return best_model, encoders | ||
|
||
except Exception as e: | ||
print(f"Une erreur s'est produite lors de l'entraînement : {str(e)}") | ||
raise | ||
|
||
def load_service_classifier(run_id: str) -> Tuple[Optional[object], Optional[Dict]]: | ||
""" | ||
Charge un modèle de classification de service depuis MLflow | ||
Args: | ||
run_id: ID MLflow du run contenant le modèle | ||
Returns: | ||
Le modèle chargé et les encodeurs, ou None si le chargement échoue | ||
""" | ||
try: | ||
model = mlflow.pycaret.load_model(f"runs:/{run_id}/service_classifier") | ||
encoders = mlflow.load_dict(f"runs:/{run_id}/label_encoders.json") | ||
return model, encoders | ||
except Exception as e: | ||
print(f"Erreur lors du chargement du modèle: {str(e)}") | ||
return None, None |
122 changes: 122 additions & 0 deletions
122
machine_learning/duration_prediction/duration_predictor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from pycaret.regression import * | ||
import mlflow | ||
import pandas as pd | ||
from typing import Optional, Tuple, Dict | ||
from sklearn.preprocessing import LabelEncoder | ||
|
||
def prepare_duration_data(data: pd.DataFrame) -> Tuple[pd.DataFrame, Dict]: | ||
""" | ||
Prépare les données pour la prédiction de durée | ||
Args: | ||
data: DataFrame contenant les données brutes | ||
Returns: | ||
DataFrame préparé et dictionnaire des encodeurs | ||
""" | ||
# Sélectionner les colonnes pertinentes | ||
features = [ | ||
'pathologie', 'code_pathologie', 'nom_pathologie', | ||
'classification', 'sexe', | ||
'tranche_age_0_1', 'tranche_age_1_4', 'tranche_age_5_14', | ||
'tranche_age_15_24', 'tranche_age_25_34', 'tranche_age_35_44', | ||
'tranche_age_45_54', 'tranche_age_55_64', 'tranche_age_65_74', | ||
'tranche_age_75_84', 'tranche_age_85_et_plus', | ||
'tx_brut_tt_age_pour_mille', 'tx_standard_tt_age_pour_mille', | ||
'AVG_duree_hospi' # target variable | ||
] | ||
|
||
df = data[features].copy() | ||
|
||
# Créer les encodeurs pour les variables catégorielles | ||
encoders = {} | ||
categorical_features = ['pathologie', 'nom_pathologie', 'classification', 'sexe'] | ||
|
||
for feature in categorical_features: | ||
encoders[feature] = LabelEncoder() | ||
df[feature] = encoders[feature].fit_transform(df[feature]) | ||
|
||
return df, encoders | ||
|
||
def train_duration_predictor( | ||
data: pd.DataFrame, | ||
target_col: str = 'AVG_duree_hospi', | ||
fold: int = 5, | ||
experiment_name: str = 'duration_prediction' | ||
) -> Tuple[object, Dict]: | ||
""" | ||
Entraîne un modèle de régression pour prédire la durée d'hospitalisation | ||
Args: | ||
data: DataFrame contenant les données d'entraînement | ||
target_col: Nom de la colonne cible (durée moyenne d'hospitalisation) | ||
fold: Nombre de folds pour la validation croisée | ||
experiment_name: Nom de l'expérience MLflow | ||
Returns: | ||
Le meilleur modèle entraîné et les encodeurs utilisés | ||
""" | ||
# Préparer les données | ||
prepared_data, encoders = prepare_duration_data(data) | ||
|
||
# Configurer MLflow | ||
mlflow.set_experiment(experiment_name) | ||
|
||
# Setup PyCaret | ||
reg_setup = setup( | ||
data=prepared_data, | ||
target=target_col, | ||
session_id=123, | ||
fold=fold, | ||
log_experiment=False, | ||
experiment_name=experiment_name, | ||
feature_selection=True, | ||
remove_multicollinearity=True, | ||
normalize=True, | ||
transformation=True, | ||
) | ||
|
||
# Comparer différents modèles | ||
best_model = compare_models(n_select=1) | ||
|
||
# Tuner le meilleur modèle | ||
tuned_model = tune_model(best_model) | ||
|
||
# Log du modèle et des métriques avec MLflow | ||
with mlflow.start_run(): | ||
# Log des paramètres | ||
mlflow.log_params(tuned_model.get_params()) | ||
|
||
# Log du modèle | ||
mlflow.pycaret.log_model(tuned_model, "duration_predictor") | ||
|
||
# Log des métriques de performance | ||
results = pull() | ||
for metric in results.columns[1:]: | ||
mlflow.log_metric(metric, results.iloc[0][metric]) | ||
|
||
# Log des encodeurs | ||
mlflow.log_dict( | ||
{k: v.classes_.tolist() for k, v in encoders.items()}, | ||
"label_encoders.json" | ||
) | ||
|
||
return tuned_model, encoders | ||
|
||
def load_duration_predictor(run_id: str) -> Tuple[Optional[object], Optional[Dict]]: | ||
""" | ||
Charge un modèle de prédiction de durée depuis MLflow | ||
Args: | ||
run_id: ID MLflow du run contenant le modèle | ||
Returns: | ||
Le modèle chargé et les encodeurs, ou None si le chargement échoue | ||
""" | ||
try: | ||
model = mlflow.pycaret.load_model(f"runs:/{run_id}/duration_predictor") | ||
encoders = mlflow.load_dict(f"runs:/{run_id}/label_encoders.json") | ||
return model, encoders | ||
except Exception as e: | ||
print(f"Erreur lors du chargement du modèle: {str(e)}") | ||
return None, None |
Oops, something went wrong.