Presidio Research

repository·main·Indexed 43 days ago

https://github.com/data-privacy-stack/presidio-research

A framework providing evaluation and data-science capabilities for Presidio and PII detection models. It includes the presidio-evaluator package (v0.3.2) for measuring Named Entity Recognition (NER) performance using precision, recall, and error analysis, as well as tools for synthetic data generation and standardized data representation.

Tokens
41.7K
Snippets
104
Records
167
Agent score
53%

What's inside Presidio Research

  1. Handle one-to-many mapping scenarios

    main

    A single model prediction may correspond to multiple distinct entities annotated in a dataset. At coarse depths, these merge effectively, but at fine depths, the model's predictions may be considered imprecise. Examples include:

    • Model LOCATION $\rightarrow$ Dataset CITY, STATE, COUNTRY, POSTAL_CODE, etc.
    • Model PERSON $\rightarrow$ Dataset FIRST_NAME, LAST_NAME, FULL_NAME, etc.
    • Model ID $\rightarrow$ Dataset SSN, PASSPORT, DRIVER_LICENSE, etc.
  2. How data generation works in presidio-evaluator

    main

    The data generation process creates synthetic sentences based on templates (e.g., My name is {{name}}) and samples fake PII values.

    Once generated, the process:

    1. Tokenizes the data.
    2. Creates tags (IO, BIO, or BILUO).
    3. Creates spans for the newly created samples.

    You can split this generated data into train/test/validation sets while ensuring that each template only exists in one set to avoid leakage.

  3. Address temporal ambiguity in dates, ages, and durations

    main
    Numeric and temporal spans are often ambiguous across entity types. A single span like "25" could be an AGE, BUILDING_NUMBER, ID, or AMOUNT. Similarly, "March 15" could be a DATE, BIRTH_DATE, or DEATH_DATE. These differences become critical at depth 3 of the evaluation, where canonicalization paths diverge.
  4. Manage conflicting mapping decisions at different evaluation depths

    main

    A manual mapping override that is valid at a coarse depth (e.g., depth 2) may become ambiguous or incorrect at a finer depth (e.g., depth 3).

    For example, mapping NRP to LOCATION at depth 2 might work for a high-level view, but at depth 3, NRP canonically resolves to NATIONALITY (under DEMOGRAPHIC). Forcing it to LOCATION creates ambiguity regarding whether it should map to LOCATION → ADDRESS or LOCATION → GPE.

  5. Understand CanonicalMapper issue types

    main

    When running .analyze(), the mapper identifies several types of mapping issues. These are categorized by severity:

    Issue TypeSeverityDescription
    UNRESOLVEDERRORThe label cannot be matched to the hierarchy. Must be resolved before calling get_mapped_results_dataframe().
    COLLISION_TRIVIALINFOA trivial collision that is typically auto-fixed.
    COLLISION_CROSS_BRANCHINFOA collision between two different branches of the hierarchy. Includes overlap_counts for context.
    PREDICTION_ONLYINFOAn entity predicted by the model that does not exist in the dataset. Default behavior counts these as False Positives (FP).
    DATASET_ONLYINFOAn entity present in the dataset but not predicted by the model. Default behavior counts these as False Negatives (FN).
  6. Understand the Presidio Evaluator redesign architecture

    main

    The redesigned presidio_evaluator follows a strict three-layer architecture where each layer communicates via a standardized DataFrame. This separation of concerns ensures that the model handles prediction, the mapper handles canonicalization, and the evaluator handles scoring without overlapping responsibilities.

    The Three-Layer Pipeline:

    1. Model: Performs prediction using BaseModel.predict_dataset(dataset).
    2. Mapper: Canonicalizes labels using CanonicalMapper.
    3. Evaluator: Calculates scores using SpanEvaluator or TokenEvaluator.

    Standard DataFrame Schema: All layers exchange data using a DataFrame with exactly these 5 columns:

    • sentence_id (int)
    • token (str)
    • annotation (str)
    • prediction (str)
    • start_indices (int)
  7. How Presidio Evaluator components work together

    main

    Presidio Evaluator is a framework for assessing PII detection models using several interconnected components:

    1. BaseEvaluator: The foundation for all strategies. It compares ground truth annotations with predictions and calculates metrics like precision, recall, and F-score. The primary entry point is calculate_score_on_df().
    2. Evaluation Strategies:
      • Token Evaluation: Compares labels at the individual token level.
      • Span Evaluation: Evaluates entire entity boundaries and types, which is generally more accurate for multi-token entities.
    3. EvaluationResult: An object that encapsulates the output of an evaluation, including global/per-type metrics and confusion matrices.
    4. Plotter: A visualization tool that takes EvaluationResult objects to generate charts and heatmaps.

    To extend the framework, you can implement custom evaluators by inheriting from BaseEvaluator (e.g., using an LLM as a judge).

  8. How hierarchical evaluation levels work

    main

    The presidio_evaluator uses a hierarchical approach to evaluate PII detection accuracy by projecting labels into different levels of granularity. This allows you to measure performance at different depths of the entity hierarchy.

    1. Binary Level: The simplest check. Did the model detect any PII? (Labels are either PII or O).
    2. Branch Level: Checks if the model identified the correct high-level category (e.g., PERSON vs LOCATION). This uses depth-2 ancestors.
    3. Detailed Level: The most granular check. Compares the specific hierarchy node (e.g., NAME vs ADDRESS) identified by the model against the ground truth.

    By using MappedResults, you can switch between these levels by passing the corresponding DataFrame (.binary, .branch, or .detailed) to evaluation functions or plotting tools.

  9. Handle country-prefixed labels in regulatory datasets

    main

    For datasets using country-prefixed labels (e.g., GERMANY_PASSPORT_NUMBER or BRAZIL_CPF), the mapper uses two identification tiers before attempting fuzzy matching:

    1. COUNTRY tier: Attempts to strip the country prefix (demonym or ISO code) and perform an alias lookup on the remainder.
    2. COUNTRY_FALLBACK tier: Strips the leading country code and tries again.

    Ensure that your labels follow consistent patterns (e.g., using ISO codes vs demonyms) to ensure reliable resolution to canonical nodes like PASSPORT or TAX_ID.

  10. Identify PHI data types under HIPAA

    main

    Under HIPAA, Protected Health Information (PHI) includes 18 specific types of identifiers. When building or testing de-identification systems, ensure your models or evaluators account for these categories:

    • Names or part of names
    • Geographical identifiers
    • Phone numbers
    • Email addresses
    • Medical record numbers
    • Account numbers
    • Vehicle license plate numbers
    • Web URLs
    • Fingerprints, retinal and voice prints
    • Any other unique identifying characteristic
    • Dates directly related to an individual
    • Fax numbers
    • Social Security numbers
    • Health insurance beneficiary numbers
    • Certificate or license numbers
    • Device identifiers and serial numbers
    • IP addresses
    • Full face or any comparable photographic images
  11. How Dataset-Anchored Entity Mapping works with CanonicalMapper

    main

    The CanonicalMapper is used to resolve vocabulary mismatches between dataset annotations and model predictions. Unlike previous versions, it uses a dataset-anchored approach where annotations define the evaluation contract at their native depth and are never modified or projected.

    The Mapping Process

    The mapping occurs in two distinct phases:

    1. Phase 1 — Identify (Inside CanonicalMapper): Every raw label is resolved to a canonical entity in the hierarchy using a tiered strategy:

      • EXACT: Case-insensitive, delimiter-normalized match (e.g., email_address → EMAIL_ADDRESS).
      • COUNTRY: Recognized country prefix + known document type (e.g., GERMANY_PASSPORT_NUMBER → PASSPORT).
      • COUNTRY_FALLBACK: Recognized country prefix + unknown remainder (e.g., NIGERIA_UNICORN_CARD → NATIONAL_ID).
      • FUZZY: String match above a threshold (default 0.80).
      • UNRESOLVED: No match found (flagged as ERROR).
      • Note: BIO/BIOES/BILOU prefixes/suffixes are stripped before matching, and the O token is mapped to None.
    2. Phase 2 — Hierarchical Evaluation (Inside SpanEvaluator): Once identified, depth-level comparison is performed using the descendant-credit rule:

      • TP: If the prediction is equal to or a descendant of the annotation on the same branch.
      • FP+FN: If the prediction is an ancestor (too coarse) or on a different branch.

    Key Workflow

    1. Call analyze() to run the identification phase.
    2. Inspect issues using render_html() or get_issues().
    3. Resolve UNRESOLVED (ERROR) labels using map() or resolve_interactively().
    4. Extract results via get_mapped_results_dataframe().
  12. How projection and collision resolution works in CanonicalMapper

    main

    During the projection phase, CanonicalMapper maps prediction entities onto the dataset's entity set. When entities do not match exactly, it uses the following rules:

    • Exact Matches: Kept as is.
    • Descendants: Mapped up to the nearest ancestor present in the dataset. If this is a same-branch ancestor/descendant relationship, it is flagged as COLLISION_TRIVIAL and can be auto-fixed.
    • Unambiguous Ancestors: Mapped down to the specific descendant. Flagged as COLLISION_TRIVIAL.
    • Ambiguous Ancestors: If an ancestor could map to multiple descendants, it is flagged as COLLISION_AMBIGUOUS and requires user intervention.
    • Cross-branch Entities: If an entity belongs to a different branch of the hierarchy, it is flagged as COLLISION_CROSS_BRANCH and requires user intervention.

    Entity Detection Defaults:

    • DATASET_ONLY entities: Kept by default (False Negatives are considered informative).
    • PREDICTION_ONLY entities: Removed by default (to avoid inflating False Positives).