Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Enhanced field extraction with targeted logement improvements. | |
| Adds: | |
| 1. Post-processing numeric pattern matching for logement fields | |
| 2. Confidence thresholding for noisy extractions | |
| 3. Field-specific regex fallback patterns | |
| 4. Suggestions for data augmentation and retraining | |
| """ | |
| import re | |
| from typing import Dict, List | |
| # Common patterns for logement fields observed in documents | |
| LOGEMENT_PATTERNS = { | |
| 'nb_log_totale': { | |
| # Numbers after "total" keyword | |
| 'patterns': [ | |
| r'(?:nombre|nb|total).*?(?:logement|lot|log).*?[\s:]+(\d+)', | |
| r'nb total de logements.*?[:\s]+(\d+)', | |
| r'logements.*?[:\s]+(\d+)', | |
| ], | |
| 'min_conf': 0.3, | |
| 'description': 'Total number of housing units' | |
| }, | |
| 'Nb_log_pro': { | |
| 'patterns': [ | |
| r'(?:nb|nombre).*?(?:log|logement).*?pro.*?[:\s]+(\d+)', | |
| r'professional.*?[:\s]+(\d+)', | |
| ], | |
| 'min_conf': 0.4, | |
| 'description': 'Number of professional units' | |
| }, | |
| 'Nb_log_res': { | |
| 'patterns': [ | |
| r'(?:nb|nombre).*?(?:log|logement).*?(?:res|rΓ©sidentiel).*?[:\s]+(\d+)', | |
| r'residential.*?[:\s]+(\d+)', | |
| ], | |
| 'min_conf': 0.4, | |
| 'description': 'Number of residential units' | |
| }, | |
| 'Nombre_Logement_Lot_MacroLot': { | |
| 'patterns': [ | |
| r'(?:nombre|nb).*?(?:logement|lot|macro).*?[:\s]+(\d+)', | |
| r'macrolot.*?[:\s]+(\d+)', | |
| ], | |
| 'min_conf': 0.35, | |
| 'description': 'Number of housing units per lot or macrolot' | |
| }, | |
| } | |
| def extract_with_regex_fallback(ocr_text: str, field_name: str, model_confidence: float = 0.0) -> str: | |
| """ | |
| Fallback extraction using regex patterns for numeric fields. | |
| Used when model confidence is too low or no extraction found. | |
| """ | |
| if field_name not in LOGEMENT_PATTERNS: | |
| return "" | |
| config = LOGEMENT_PATTERNS[field_name] | |
| if model_confidence < config['min_conf']: | |
| for pattern in config['patterns']: | |
| match = re.search(pattern, ocr_text, re.IGNORECASE) | |
| if match: | |
| return match.group(1) | |
| return "" | |
| def enhance_extracted_fields(extracted_fields: Dict[str, str], | |
| ocr_text: str, | |
| field_confidences: Dict[str, float] = None) -> Dict[str, str]: | |
| """ | |
| Post-process extracted fields with logement-specific improvements. | |
| Args: | |
| extracted_fields: Dict from model extraction | |
| ocr_text: Original OCR text | |
| field_confidences: Optional confidence scores per field | |
| Returns: | |
| Enhanced fields dict with logement improvements applied | |
| """ | |
| if field_confidences is None: | |
| field_confidences = {k: 1.0 for k in extracted_fields} | |
| enhanced = extracted_fields.copy() | |
| # For each logement field, try regex fallback if missing or low confidence | |
| for field_name in LOGEMENT_PATTERNS.keys(): | |
| confidence = field_confidences.get(field_name, 0.0) | |
| # Empty extraction or low confidence β try regex | |
| if not enhanced.get(field_name) or confidence < LOGEMENT_PATTERNS[field_name]['min_conf']: | |
| regex_result = extract_with_regex_fallback(ocr_text, field_name, confidence) | |
| if regex_result: | |
| enhanced[field_name] = regex_result | |
| print(f" [regex fallback] {field_name}: {regex_result}") | |
| return enhanced | |
| # RECOMMENDATIONS FOR FURTHER IMPROVEMENT: | |
| IMPROVEMENT_RECOMMENDATIONS = """ | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β LOGEMENT FIELD IMPROVEMENT ROADMAP β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| 1. DATA AUGMENTATION (SHORT TERM - immediate impact) | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β’ Generate synthetic logement annotations by: | |
| - Copying existing 75 logement records | |
| - Applying geometric transforms (rotation, scaling) | |
| - Simulating OCR noise/variations | |
| β’ Target: 300-500 augmented examples per field | |
| β’ Expected improvement: 5-15 percentage points in extraction F1 | |
| 2. TARGETED RETRAINING (MEDIUM TERM - 1-2 hours) | |
| ββββββββββββββββββββββββββββββββββββββββββββββ | |
| β’ Retrain extractor with class weights favoring rare fields: | |
| weight_for_field = 1.0 / sqrt(example_count) | |
| β’ Focus: 5-10 additional epochs focusing on underrepresented fields | |
| β’ Configuration changes needed in train_extractor_v3.py: | |
| - Increase class weights for fields 4-7 | |
| - Maybe: use class_weights in loss computation | |
| β’ Expected improvement: 10-25 percentage points | |
| 3. SPECIALIZED NUMERIC PREPROCESSING (IMMEDIATE) | |
| ββββββββββββββββββββββββββββββββββββββββββββββ | |
| β’ Pre-extract numeric regions from OCR before model inference | |
| β’ Segment page into "number tables" vs "text regions" | |
| β’ Run separate small OCR model or regex on number tables | |
| β’ Expected improvement: 20-30 percentage points (if tables found) | |
| 4. HYBRID EXTRACTION PIPELINE (IMMEDIATE - no retraining) | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β Already partially implemented via regex fallback above | |
| β’ Combine model output + regex patterns | |
| β’ Rule: if model confidence < 0.3, use regex | |
| β’ Add geometric constraints from OCR document layout | |
| β’ Expected improvement: 15-25 percentage points immediately | |
| 5. DOCUMENT-SPECIFIC RULES (QUICK WIN) | |
| ββββββββββββββββββββββββββββββββββ | |
| For "fiche" documents specifically: | |
| β’ Logement fields appear in a fixed table around coordinates (1700-2000, 1600-2000) | |
| β’ Extract numeric values from that region directly | |
| β’ Expected improvement: 30-50 percentage points for fiche class | |
| IMMEDIATE ACTIONS YOU CAN TAKE: | |
| ββββββββββββββββββββββββββββββββ | |
| a) Deploy regex fallback (see extract_with_regex_fallback function) | |
| b) Set min_conf thresholds per field (currently 0.3-0.4) | |
| c) Collect 20-30 more labeled logement examples | |
| d) Retrain with field-weighted loss (next iteration) | |
| EXPECTED GAINS: | |
| βββββββββββββββ | |
| Approach | Effort | Gain | |
| ββββββββββββββββββββββΌββββββββββΌββββββββββββββ | |
| Regex fallback | 30min | +15-25% | |
| Data augmentation | 1-2h | +10-30% | |
| Retraining w/ weights| 2-4h | +15-40% | |
| Document-specific | 1-2h | +25-50% (class-specific) | |
| Combined approach | 4-6h | +40-70% (estimated) | |
| """ | |
| if __name__ == "__main__": | |
| print(IMPROVEMENT_RECOMMENDATIONS) | |