Blind Room Classification
Classification aveugle des pièces d'un bâtiment à partir d'un graphe spatial (Revit BIM).
Aucun nom Revit n'est utilisé pour classer les pièces.
Seule la géométrie, la topologie du graphe et le contexte d'appartement sont exploités.
📊 Performances (v8.1)
| Dataset |
Pièces évaluées |
Accuracy |
| P1 (multi-projets) |
1 217 |
99.4% |
| P2 (LD-CLL) |
362 |
94.5% |
🚀 Démarrage rapide
# Prérequis : Python ≥ 3.10 (stdlib uniquement, aucune dépendance)
# Interface web (recommandé)
python classify_launcher.py
# → http://localhost:8500
# Ligne de commande
python src/export_viewer.py data/spatial_graph_P1.json
# → output/spatial_graph_P1_viewer.html
# Benchmark d'accuracy
python src/_baseline.py
🏗️ Architecture
classify_launcher.py → Interface web locale (port 8500)
data/ → Fichiers JSON d'entrée (graphes spatiaux P1–P5)
src/
├── blind_classifier.py → Orchestrateur du pipeline de classification
├── apartment_clustering_v2.py → Clustering par betweenness + BFS
├── export_viewer.py → Générateur de viewer HTML interactif
├── graph_metrics.py → Métriques de centralité (btw, closeness, degree, eigen)
├── graph_templates.py → 44 templates WL globaux
├── _baseline.py → Benchmark d'accuracy P1/P2
├── rules/ → Règles de classification modulaires
│ ├── geometric.py → Passe 1 : R1–R10 (géométrie pure)
│ ├── templates.py → Passe 0.5 : template matching WL global
│ ├── motifs.py → Passe 1.5 : motifs locaux (suite parentale, hub, annexe)
│ ├── inter_pass.py → Inter-passes + post-pass corrections (11 règles)
│ ├── topological.py → Passe 2 : propagation topologique
│ ├── apartment_context.py → Passe 3 : contexte d'appartement
│ ├── cluster_correction.py → Passe 4 : correction par cluster
│ └── entrance_coherence.py → Passe 5 : cohérence des entrées
└── wl/ → Module Weisfeiler-Lehman (hasher + analyzer)
output/ → Fichiers générés (viewers HTML, résultats JSON)
docs/guide/ → Documentation interactive (12 pages HTML)
docs/research/ → Artifacts de recherche (handoffs, rapports, roadmap)
autoresearch/ → Framework d'expérimentation autonome (Karpathy loop)
🔬 Pipeline de classification
Passe 0 — Entrées structurelles (betweenness centrality) conf 1.0
Passe 0.5 — Template matching WL (44 templates globaux) conf 1.0
Passe 1 — Géométrie pure (R1–R10 : area, portes, fenêtres) conf 0.65–0.95
Passe 1.5 — Motifs locaux (suite parentale, hub, annexe cuisine) conf 0.85–0.95
Inter — Corrections architecturales (R_adj, R_bedroom, etc.)
Passe 2 — Propagation topologique (voisinage d'ancres fiables) conf 0.55–0.85
Passe 3 — Contexte d'appartement (buanderie, cuisine, centralité)
Passe 4 — Correction par cluster (types manquants) conf 0.55–0.78
Passe 5 — Cohérence des entrées (1 entrée par appartement) conf 0.80
Post — 11 règles de raffinement (hubs, WL local, fallbacks) conf 0.55–0.85
📖 Documentation
🔧 Prérequis
- Python ≥ 3.10 (stdlib uniquement, aucune dépendance externe)
Spatial Graph Classifier — CLAUDE.md
Objectif principal
Transparence et maintenabilité, pas le score. Le score P1/P2 est un garde-fou de non-régression, pas l'objectif. Avant toute modification : privilégier la lisibilité, les noms explicites, les constantes documentées. Voir la philosophie complète dans SGC-Cortex/00-index.md.
Commandes clés
# Benchmark d'accuracy (P1 + P2)
python src/_baseline.py
# Smoke test complet (P1–P5 + seuils + score no-memo observationnel)
python tools/smoke_test.py
# Matrice d'ablation (contribution de chaque passe/règle — OBLIGATOIRE avant
# d'ajouter une règle ; ~15 s)
python tools/ablation_matrix.py
# Viewer HTML interactif pour un dataset
python src/export_viewer.py data/spatial_graph_P1.json # → output/
# Interface web locale
python classify_launcher.py # → http://localhost:8500
Seuils de qualité (gates P1/P2)
| Dataset |
Seuil obligatoire |
Valeur actuelle (v9.0) |
| P1 (1 217 pièces) |
≥ 99.0% |
99.1% |
| P2 (397 pièces) |
≥ 94.0% |
94.7% |
P3, P4, P5 : scores observationnels, jamais des gates — P3 91.5%, P4 92.4%, P5 85.0% (P5 ré-exporté 2026-07). Une partie de l'ancien « écart P5 » (65%) était causée par une règle toxique supprimée en v9.0 (R_bathroom_leaf, cf. docs/research/REVUE_CRITIQUE_2026-07.md) ; le reste venait du champ side amont, réparé par la consommation F25 de wl_ext_ratio (cf. SGC-Cortex/experiments/f25-side-fallback.md).
Architecture
classify_launcher.py → Serveur web local (port 8500)
src/
blind_classifier.py → Orchestrateur principal
apartment_clustering_v2.py → Clustering betweenness + BFS
export_viewer.py → Générateur HTML
graph_metrics.py → btw, closeness, degree, eigenvector
graph_templates.py → 44 templates WL globaux (v1, fallback)
graph_templates_v2.py → 222 templates WL (v1 + minés MSD, actif ;
régénérable par msd/wl_mining/)
_baseline.py → Benchmark P1/P2
rules/
geometric.py → Passe 1 : R1–R9 (géométrie ; R6/R10 supprimées v9.0)
templates.py → Passe 0.5 : template matching WL
inter_pass.py → Inter-passes (NR_leaf_*) + post-passes (7 règles)
topological.py → Passe 2 : propagation
apartment_context.py → Passe 3 : kitchen recovery
wl/ → Module Weisfeiler-Lehman
data/ → JSON Revit (P1–P5)
tools/smoke_test.py → Tests de non-régression P1–P5
output/ → Viewers HTML générés
Pipeline de classification
Passe 0 — Entrées (betweenness centrality, nœuds sans fenêtre) conf 1.0
Passe 0.5 — Template WL global (44 templates) conf 1.0
Passe 1 — Géométrie pure (area, portes, fenêtres) + fallback conf 0.25–0.95
Inter — Corrections NR_leaf_* (annexes de bedroom/kitchen/living)
Passe 2 — Propagation topologique (ancres → voisins) conf 0.80–0.90
Passe 3 — Contexte appartement (kitchen recovery) conf 0.78
Post — 7 règles de raffinement finales conf 0.55–0.78
v9.0 (2026-07) : pipeline purgé sur la base d'une matrice d'ablation mesurée
(docs/research/REVUE_CRITIQUE_2026-07.md + docs/research/ablations/).
Supprimés : passes 1.5/4/5, R6, R10, R_bathroom_leaf (toxique : −11.5 pts P5),
_recover_laundry_t3 (−4.6 pts P4), 3b centralité, branche placard (nom de porte),
et 4 sous-règles mortes. Toute règle nouvelle doit prouver sa contribution via
le harnais d'ablation avant d'entrer.
Règle d'immutabilité : toute pièce classée avec confidence == 1.0 (Passes 0 et 0.5) est verrouillée (SpatialRoom.is_locked). Les passes suivantes ne peuvent pas la modifier. Chaque affectation passe par SpatialRoom.propose() (journal _history par pièce).
Données d'entrée (format JSON Revit)
- Nœuds :
RM (pièce), DR (porte), WD (fenêtre), SEP (séparateur)
- Arêtes :
Connected, Adjacent, Window
- Features clés par pièce :
area, nw (fenêtres), nd (portes), sep_ratio, glazing_ratio, btw, closeness
Knowledge base
Le dossier SGC-Cortex/ est la base de connaissance vivante du projet :
00-index.md — index général + performances actuelles
concepts/ — description détaillée de chaque passe
rules/classification-rules.md — dictionnaire exhaustif des règles
rules/constraints.md — contraintes architecturales françaises
experiments/baseline-p1-p2.md — historique complet des versions
Début de session : lire SGC-Cortex/00-index.md, puis les notes pertinentes à la tâche.
Fin de session : mettre à jour les notes modifiées et ajouter une entrée dans experiments/.