feat: Phase 1 - Système d'évaluation de la qualité
- Sélection et copie de 27 documents représentatifs (10 simples, 12 moyens, 5 complexes) - Outil d'annotation CLI complet (tools/annotation_tool.py) - Guide d'annotation détaillé (docs/annotation_guide.md) - Évaluateur de qualité (evaluation/quality_evaluator.py) * Calcul Précision, Rappel, F1-Score * Identification faux positifs/négatifs * Métriques par type de PII * Export JSON et rapports texte - Scanner de fuite (evaluation/leak_scanner.py) * Détection PII résiduels (CRITIQUE) * Détection nouveaux PII (HAUTE) * Scan métadonnées PDF (MOYENNE) - Benchmark de performance (evaluation/benchmark.py) * Mesure temps de traitement * Mesure CPU/RAM * Export JSON/CSV - Tests unitaires complets pour tous les composants - Documentation complète du module d'évaluation Tâches complétées: - 1.1.1 Sélection de 27 documents (au lieu de 30) - 1.1.2 Outil d'annotation CLI - 1.2.1 Évaluateur de qualité - 1.2.2 Scanner de fuite - 1.2.3 Benchmark de performance Prochaines étapes: - 1.1.3 Annotation des 27 documents (manuel) - 1.1.4 Enrichissement stopwords médicaux - 1.3 Mesure de la baseline
This commit is contained in:
262
evaluation/README.md
Normal file
262
evaluation/README.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# Module d'Évaluation de la Qualité d'Anonymisation
|
||||
|
||||
Ce module fournit des outils pour évaluer et valider la qualité de l'anonymisation des documents PDF médicaux.
|
||||
|
||||
## Composants
|
||||
|
||||
### 1. QualityEvaluator
|
||||
|
||||
Évalue la qualité d'anonymisation en comparant les annotations manuelles (ground truth) avec les détections automatiques.
|
||||
|
||||
**Métriques calculées** :
|
||||
- Précision (Precision) : TP / (TP + FP)
|
||||
- Rappel (Recall) : TP / (TP + FN)
|
||||
- F1-Score : 2 × (Precision × Recall) / (Precision + Recall)
|
||||
|
||||
**Usage** :
|
||||
```python
|
||||
from evaluation import QualityEvaluator
|
||||
from pathlib import Path
|
||||
|
||||
evaluator = QualityEvaluator(Path("tests/ground_truth/pdfs"))
|
||||
|
||||
# Évaluer un document
|
||||
result = evaluator.evaluate(
|
||||
pdf_path=Path("tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.pdf"),
|
||||
audit_path=Path("tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.audit.jsonl")
|
||||
)
|
||||
|
||||
print(f"Précision: {result.precision:.4f}")
|
||||
print(f"Rappel: {result.recall:.4f}")
|
||||
print(f"F1-Score: {result.f1_score:.4f}")
|
||||
|
||||
# Générer un rapport
|
||||
report = evaluator.generate_report([result])
|
||||
print(report)
|
||||
|
||||
# Exporter en JSON
|
||||
evaluator.export_json([result], Path("evaluation_results.json"))
|
||||
```
|
||||
|
||||
### 2. LeakScanner
|
||||
|
||||
Scanne les documents anonymisés pour détecter les fuites de PII (données personnelles résiduelles).
|
||||
|
||||
**Vérifications** :
|
||||
- PII originaux encore présents (CRITIQUE)
|
||||
- Nouveaux PII détectés (HAUTE)
|
||||
- Métadonnées PDF suspectes (MOYENNE)
|
||||
|
||||
**Usage** :
|
||||
```python
|
||||
from evaluation import LeakScanner
|
||||
from pathlib import Path
|
||||
|
||||
scanner = LeakScanner()
|
||||
|
||||
# Scanner un document anonymisé
|
||||
report = scanner.scan(
|
||||
anonymized_pdf=Path("output/document.redacted.pdf"),
|
||||
original_audit=Path("output/document.audit.jsonl")
|
||||
)
|
||||
|
||||
if report.is_safe:
|
||||
print("✓ Document sûr - Aucune fuite détectée")
|
||||
else:
|
||||
print(f"✗ {report.leak_count} fuite(s) détectée(s)")
|
||||
for leak in report.leaks:
|
||||
print(f" - {leak['severity']}: {leak['message']}")
|
||||
|
||||
# Générer un rapport
|
||||
report_text = scanner.generate_report(report, Path("document.pdf"))
|
||||
print(report_text)
|
||||
|
||||
# Exporter en JSON
|
||||
scanner.export_json(report, Path("leak_report.json"))
|
||||
```
|
||||
|
||||
### 3. Benchmark
|
||||
|
||||
Mesure les performances du système d'anonymisation (temps, CPU, RAM).
|
||||
|
||||
**Métriques collectées** :
|
||||
- Temps de traitement (total, par page)
|
||||
- Utilisation CPU (%)
|
||||
- Utilisation RAM (MB)
|
||||
- Nombre de PII détectés
|
||||
|
||||
**Usage** :
|
||||
```python
|
||||
from evaluation import Benchmark
|
||||
from pathlib import Path
|
||||
|
||||
benchmark = Benchmark(Path("tests/ground_truth/pdfs"))
|
||||
|
||||
# Définir la fonction d'anonymisation à benchmarker
|
||||
def anonymize_func(pdf_path):
|
||||
# Votre code d'anonymisation ici
|
||||
# Retourner le chemin vers le fichier .audit.jsonl
|
||||
return pdf_path.parent / f"{pdf_path.stem}.audit.jsonl"
|
||||
|
||||
# Benchmarker des documents
|
||||
pdf_list = list(Path("tests/ground_truth/pdfs").glob("*.pdf"))
|
||||
results = benchmark.run(pdf_list, anonymize_func)
|
||||
|
||||
# Générer un rapport
|
||||
report = benchmark.generate_report(results)
|
||||
print(report)
|
||||
|
||||
# Exporter en JSON
|
||||
benchmark.export_json(results, Path("benchmark_results.json"))
|
||||
|
||||
# Exporter en CSV
|
||||
benchmark.export_csv(results, Path("benchmark_results.csv"))
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Dépendances requises :
|
||||
```bash
|
||||
pip install pymupdf psutil
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Exécuter les tests unitaires :
|
||||
```bash
|
||||
pytest tests/unit/test_quality_evaluator.py -v
|
||||
pytest tests/unit/test_leak_scanner.py -v
|
||||
pytest tests/unit/test_benchmark.py -v
|
||||
```
|
||||
|
||||
## Format des Données
|
||||
|
||||
### Annotations (ground truth)
|
||||
|
||||
Format JSON :
|
||||
```json
|
||||
{
|
||||
"pdf_path": "document.pdf",
|
||||
"metadata": {
|
||||
"annotator": "annotator_1",
|
||||
"annotation_date": "2024-01-15T10:30:00",
|
||||
"document_type": "compte_rendu",
|
||||
"page_count": 3,
|
||||
"difficulty": "medium"
|
||||
},
|
||||
"annotations": [
|
||||
{
|
||||
"id": "ann_001",
|
||||
"page": 0,
|
||||
"type": "NOM",
|
||||
"text": "DUPONT",
|
||||
"bbox": null,
|
||||
"context": "Dr. DUPONT a examiné le patient",
|
||||
"mandatory": true,
|
||||
"difficulty": "easy",
|
||||
"detection_method_expected": ["regex", "ner", "contextual"]
|
||||
}
|
||||
],
|
||||
"medical_terms_to_preserve": [
|
||||
"Médecin DIM",
|
||||
"Service de cardiologie"
|
||||
],
|
||||
"statistics": {
|
||||
"total_pii": 1,
|
||||
"by_type": {
|
||||
"NOM": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Audit (détections)
|
||||
|
||||
Format JSONL (une ligne par PII détecté) :
|
||||
```json
|
||||
{"page": 0, "kind": "NOM", "original": "DUPONT", "placeholder": "[NOM]"}
|
||||
{"page": 0, "kind": "TEL", "original": "01 23 45 67 89", "placeholder": "[TEL]"}
|
||||
```
|
||||
|
||||
## Métriques Cibles
|
||||
|
||||
Pour garantir la conformité RGPD et la qualité d'anonymisation :
|
||||
|
||||
- **Rappel (Recall)** : ≥ 99.5% (maximum 0.5% de PII manqués)
|
||||
- **Précision (Precision)** : ≥ 97% (maximum 3% de faux positifs)
|
||||
- **F1-Score** : ≥ 0.98
|
||||
- **Taux de documents sûrs** : ≥ 98% (documents avec 0 faux négatif)
|
||||
|
||||
## Workflow Complet
|
||||
|
||||
1. **Annoter les documents** : Utiliser `tools/annotation_tool.py`
|
||||
2. **Anonymiser les documents** : Utiliser le système d'anonymisation
|
||||
3. **Évaluer la qualité** : Utiliser `QualityEvaluator`
|
||||
4. **Scanner les fuites** : Utiliser `LeakScanner`
|
||||
5. **Benchmarker les performances** : Utiliser `Benchmark`
|
||||
6. **Analyser les résultats** : Identifier les améliorations nécessaires
|
||||
|
||||
## Exemples de Rapports
|
||||
|
||||
### Rapport d'Évaluation
|
||||
|
||||
```
|
||||
================================================================================
|
||||
RAPPORT D'ÉVALUATION DE LA QUALITÉ D'ANONYMISATION
|
||||
================================================================================
|
||||
|
||||
Documents évalués: 27
|
||||
|
||||
MÉTRIQUES GLOBALES:
|
||||
True Positives: 245
|
||||
False Positives: 8
|
||||
False Negatives: 2
|
||||
|
||||
Précision moyenne: 0.9684 (96.84%)
|
||||
Rappel moyen: 0.9919 (99.19%)
|
||||
F1-Score moyen: 0.9800
|
||||
|
||||
RÉSULTATS PAR DOCUMENT:
|
||||
001_simple_unknown_BACTERIO_23018396.pdf
|
||||
Précision: 1.0000 Rappel: 1.0000 F1: 1.0000
|
||||
TP: 10 FP: 0 FN: 0
|
||||
```
|
||||
|
||||
### Rapport de Fuite
|
||||
|
||||
```
|
||||
================================================================================
|
||||
RAPPORT DE FUITE - document.redacted.pdf
|
||||
================================================================================
|
||||
|
||||
✓ DOCUMENT SÛR - Aucune fuite détectée
|
||||
|
||||
================================================================================
|
||||
```
|
||||
|
||||
### Rapport de Benchmark
|
||||
|
||||
```
|
||||
================================================================================
|
||||
RAPPORT DE BENCHMARK - PERFORMANCE D'ANONYMISATION
|
||||
================================================================================
|
||||
|
||||
SYSTÈME:
|
||||
OS: Linux 6.8.0
|
||||
CPU: AMD Ryzen 9 9950X
|
||||
Cœurs: 16 physiques / 32 logiques
|
||||
RAM: 128.0 GB
|
||||
Python: 3.12.0
|
||||
|
||||
RÉSUMÉ:
|
||||
Documents: 27
|
||||
Temps moyen: 8.5s
|
||||
Temps min/max: 2.1s / 25.3s
|
||||
CPU moyen: 45.2%
|
||||
RAM moyenne: 1024.5 MB
|
||||
PII détectés: 245 (moy: 9.1)
|
||||
```
|
||||
|
||||
## Licence
|
||||
|
||||
Ce module fait partie du système d'anonymisation de documents PDF médicaux.
|
||||
Reference in New Issue
Block a user