Le principe d'observabilité

Le classifieur n'utilise que des features calculables sans connaître la réponse.

✅ Observable (autorisé)

FeatureSourcePourquoi c'est « aveugle »
areaGéométrie des segmentsMesurable physiquement, pas besoin de connaître le nom
num_windowsArêtes Window dans le grapheTopologie pure — on compte les connexions
sep_ratioSegments WL vs SEPRatio calculé à partir de la géométrie des murs
betweennessGraphe du niveauCentralité calculée sans labels
wl_countNombre de segments de murComptage géométrique pur

❌ Non-observable (interdit)

DonnéePourquoi interdite
Nom Revit de la pièceC'est la réponse — l'utiliser serait tricher
apt_id pour classifierUtilisé uniquement pour grouper, jamais pour décider du type
Annotations manuellesToute info humaine viole le principe
🎯
Pourquoi c'est important ? — Un classifieur aveugle est robuste aux conventions de nommage. Un projet qui nomme ses chambres "CH" au lieu de "CHAMBRE" ne le perturbera pas. Il généralise à tout projet BIM structuré de manière similaire.

Le gradient de confiance

La confiance décroît avec les passes, reflétant l'incertitude épistémique croissante.

🔒
Immutabilité — Les pièces à confidence = 1.0 sont protégées par la propriété unique is_locked (confidence >= 1.0). Aucune passe ultérieure ne peut les modifier. C'est un choix architectural fort : on sacrifie la possibilité de corriger une erreur en Passe 0 en échange de la garantie que les ancres fiables ne seront jamais corrompues par des passes moins sûres. Résultat : 0 faux positif sur 875 pièces verrouillées (P1+P2).

Les trois types d'évidence

Le classifieur combine trois natures d'information, dans un ordre de certitude décroissante.

🏗️ Évidence structurelle Passes 0 & 0.5

Qui est connecté à qui ? Quelle position dans le graphe ? L'isomorphisme WL et la betweenness centrality exploitent la structure pure du réseau de pièces. C'est l'évidence la plus fiable (conf 1.0).

Features : betweenness, closeness, signature WL, template matching

📐 Évidence géométrique Passe 1

Quelle surface ? Combien de fenêtres ? Quel ratio de séparateurs ? Les mesures physiques discriminent les types. C'est un arbre de décision classique avec 9 règles R1→R9.

Features : area, sep_ratio, num_windows, num_doors, glazing_ratio, wl_count, side

🏠 Évidence contextuelle Passes 2, 3, 4

L'appartement a-t-il une cuisine ? Un WC ? La composition globale contraint les possibilités. Le profil de voisinage corrige les erreurs.

Features : cluster_label, profil voisinage, composition apt, constraints R4a-R4e

Le développement error-driven

Chaque version est née de l'analyse des erreurs de la précédente — pas de l'ajout spéculatif de features.

1

Observer les erreurs

Analyser la matrice de confusion. Identifier les transferts d'erreur les plus fréquents. Ex : « 14 fausses chambres avaient 0 porte ».

2

Formuler une hypothèse

Identifier le discriminant qui sépare les erreurs des vrais positifs. Ex : « une chambre a toujours ≥1 porte ».

3

Implémenter la correction

Ajouter le garde dans la règle appropriée avec le seuil le plus prudent. Ex : R4 += doors ≥ 1.

4

Vérifier (anti-régression)

Lancer _baseline.py. Accepter uniquement si : P1 ≤ -0.5%, P2 ≤ -1.0%, score global ≤ 0. Sinon → discard.

🔄
Exemples concrets
• v5.5 → 14 chambres FP avaient doors=0 → ajout garde nd≥1 → 0 régression
• v6.1 → 7 terrasses classées jardin → Information Gain → arbre R1 réécrit → garden precision 38%→100%
• v6.3 → 4 chambres classées séjour → découverte glazing_ratio → seuil 0.23 → zone morte [0.20, 0.27]

Calibration prudentielle des seuils

Chaque seuil est calibré avec un biais de prudence : mieux vaut un faux négatif qu'un faux positif.

SeuilValeurAlternative rejetéeRaison
sep_ratio (terrasse étage)≥ 0.55≥ 0.40Protège 6 loggias P2 à 0.50
btw_min (entrées)≥ 0.10≥ 0.05Élimine 20 faux positifs, 0 vrai perdu
glazing_ratio (séjour)≥ 0.23≥ 0.20Zone morte [0.20, 0.27] sépare chambres/séjours
area (WC)≤ 3.2 m²≤ 4.0Au-delà → confusion avec petites SDB
area (garden)≥ 25 m²≥ 15Élimine petites terrasses de RDC

La limite théorique toilet/storage

Un WC et un placard sont topologiquement isomorphes. C'est une limite irréductible de l'approche.

⚠️
Pourquoi WL ne peut pas les distinguer ?
Le WC et le placard ont les mêmes features observables (0 fenêtre, <3.5m², même type de voisin). Leur hash WL est identique à toutes les itérations. Seule une information non-topologique (points d'eau, équipements sanitaires) pourrait briser cette collision.

Solution adoptée : les templates partiels (v5.8). On accepte l'ambiguïté et on délègue la résolution aux passes géométriques (wl_count=5 → storage, area ≤3.2 → toilet).

Évolution historique (v1 → v8.1)

22 versions, de 40.9% à 99.4% d'accuracy. Chaque point est une leçon.

VersionP1P2Changement clé
v140.9%Géométrie brute uniquement
v388.4%72.3%+ wl_count, sep_ratio
v4.292.8%76.6%+ leaf nodes + centralité de graphe
v4.697.8%86.2%+ R_kitchen_bedroom, Passe 3 aveugle
v5.299.4%90.9%R5 supprimé, clustering v2
v5.695.0%90.9%⚠️ Dataset P1 élargi 199→1402 pièces (pas une régression)
v5.892.2%91.7%Passe 0.5 : templates partiels WL
v6.193.4%R1 aveugle : Information Gain → garden 100%
v6.296.8%93.4%Point-in-Polygon vertical overlap
v6.397.0%93.4%glazing_ratio ≥ 0.23
v7.197.5%93.4%Palier par closeness centrality
v8.199.4%94.5%11 post-pass rules, WL local, motifs locaux, entrée coherence
📉
Le « faux drop » v5.2→v5.6 — L'accuracy P1 passe de 99.4% à 95.0%, mais c'est un artefact : le dataset P1 a été élargi de 199 à 1 402 pièces. L'algorithme n'a pas régressé — il a été testé sur un jeu de données 7× plus grand et plus diversifié.

Pistes non retenues

Ce qui a été essayé et abandonné — et pourquoi.

PisteRésultatRaison du rejet
K-means clustering (k=9)60.6%Fusionne toilet+laundry+storage en un seul cluster
1-NN (leave-one-out)87.5%Meilleur que K-means mais < règles manuelles
Hub seul (max degree)53%Insuffisant sans filtrage par type
R_topo hub ≥ 3 types voisinsInstableDépend des types déjà prédits (récursion circulaire)
Ensemble multi-config WLAbandonnéComplexité d'implémentation vs gain marginal (+0.2%)

Axes de recherche

6 axes identifiés pour poursuivre l'optimisation.

🔷 Axe C — WL Local Hash

32 hashes corridor purs, +0.3%. Cible 98.5% atteinte.

✅ Terminé

🔶 Axe D — WL Config Tuning

Explorer d'autres combinaisons d'observables (W, D, S, A, WC).

✅ Terminé

🟡 Axe E — Enrichissement graphe

Distance topo à l'entrée, type de porte, longueur mur partagé.

🟡 Discovery done

❌ Axe F — Ensemble multi-vote

Combiner les votes de N configs WL.

❌ Abandonné

🔷 Axe G — Méta-erreurs

Matrice de confusion multi-projets, zones de confusion features.

✅ Terminé

🔷 Axe H — Validation

Accuracy par typo, robustesse, sensitivity à la suppression de portes.

✅ Terminé