Skip to content

Commit

Permalink
ML implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Arctusol committed Dec 5, 2024
1 parent c291169 commit 994fafa
Show file tree
Hide file tree
Showing 26 changed files with 51,830 additions and 747 deletions.
150 changes: 150 additions & 0 deletions machine_learning/README.md
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 machine_learning/classification_service/service_classifier.py
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 machine_learning/duration_prediction/duration_predictor.py
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
Loading

0 comments on commit 994fafa

Please sign in to comment.