InterpretML Documentation

repository·main·Indexed 27 days ago

https://github.com/interpretml/interpret

An open-source package for machine learning interpretability. It provides tools to train interpretable 'glassbox' models, such as Explainable Boosting Machines (EBM), APLR, and Decision Trees, and explain 'blackbox' systems using techniques like SHAP and LIME. The ecosystem includes the powerlift package for interactive benchmarking of ML models, supporting local execution and Azure Container Instances (ACI) for large-scale parallel evaluations.

Tokens
24.3K
Snippets
42
Records
141
Agent score
87%

What's inside InterpretML

  1. Understand Glassbox Models in InterpretML

    main
    Glassbox models in InterpretML are structured for direct interpretability. Unlike blackbox models, where explanations are typically approximations of the model's behavior, glassbox models provide exact and human-interpretable explanations because the model structure itself is transparent.
  2. Understand EBM internals for Regression, Classification, and Multiclass

    main

    The internal workings of Explainable Boosting Machines (EBM) are documented in three progressive parts:

    1. Regression for pure GAM models: Covers regression without interactions (ebm-internals-regression.ipynb).
    2. Binary Classification: Covers binary classification including interactions, ordinals, and missing values (ebm-internals-classification.ipynb).
    3. Multiclass and Unseen Values: Covers multiclass classification and handling of unseen values (ebm-internals-multiclass.ipynb).
  3. Understand InterpretML C++ Architecture Zones

    main

    The InterpretML C++ codebase is partitioned into specific 'Zones' to manage memory regions, compiler differences (e.g., SIMD, GPU, MPI), and to avoid One Definition Rule (ODR) violations. Developers working on the C++ core must adhere to these boundaries:

    • zone_main: The root C++ directory. Contains standard C++ code that stays in the main library. All code should be wrapped in the EbmMain namespace to prevent accidental sharing.
    • zone_separate: High-performance code (GPU/SIMD/MPI). This code is re-compiled with different flags and linked together. Everything here must be in separate namespaces to avoid ODR violations.
    • zone_c_interface: The transition layer between zone_main and zone_separate. Uses extern "C" functions, function pointers, and POD (Plain Old Data) types. It contains no classes or structures to ensure maximum safety.
    • zone_cpp_interface: Provides access to shared POD data structures between zones. While it uses C++ templates for memory optimization, it relies on POD layout guarantees. Headers in this zone must not include any other headers; all necessary includes must be placed in the .cpp translation units before including these headers.
    • zone_shared: Contains utility functions or C++ classes used across the codebase but not required for cross-zone communication. Code here must be in a unique namespace to remain ODR compliant.
    • zone_safe: Pure C-compliant files and headers. These can be included anywhere without special namespace requirements. They are used for common C utilities and macros (e.g., LIKELY/UNLIKELY).
  4. Use Blackbox Explainers for model behavior approximation

    main
    Blackbox explainers provide approximate explanations of how a model behaves or why it makes specific predictions. They are particularly useful for interpreting complex pipelines where individual components are not directly interpretable (e.g., deep learning models or complex ensembles).
  5. Use interpret-inline for notebook visualizations

    main

    The interpret-inline JavaScript library is used to enable InterpretML visualizations to render correctly in both local and cloud notebook environments (such as Jupyter or Google Colab).

    Note: This package is not intended to be used as a standalone library; it is a supporting component for the Python interpret package.

  6. Run experiments using Azure Container Instances (ACI) executor

    main

    For large-scale parallel evaluations, you can use the AzureContainerInstance executor. This requires setting environment variables for Azure credentials and providing a connection string to your database (e.g., via AZURE_DB_URL).

    Required environment variables:

    • AZURE_DB_URL
    • AZURE_TENANT_ID
    • AZURE_SUBSCRIPTION_ID
    • AZURE_CLIENT_ID
    • AZURE_CLIENT_SECRET
    • AZURE_RESOURCE_GROUP
    from powerlift.executors import AzureContainerInstance
    from powerlift.bench import Benchmark, Store
    import os
    
    store = Store(os.getenv("AZURE_DB_URL"))
    
    executor = AzureContainerInstance(
        store,
        azure_tenant_id=os.getenv("AZURE_TENANT_ID"),
        subscription_id=os.getenv("AZURE_SUBSCRIPTION_ID"),
        azure_client_id=os.getenv("AZURE_CLIENT_ID"),
        azure_client_secret=os.getenv("AZURE_CLIENT_SECRET"),
        resource_group=os.getenv("AZURE_RESOURCE_GROUP"),
        n_running_containers=5
    )
    
    benchmark = Benchmark(store, name="ACI Experiment")
    benchmark.run(trial_runner, trial_filter, timeout=10, executor=executor)
    benchmark.wait_until_complete()
  7. Exception Handling and Memory Management in libebm

    main

    The core C++ library (libebm) follows a C-oriented style to prioritize performance, portability, and memory control.

    Exception Usage

    • Core Library: Exceptions are used very sparingly. They are primarily reserved for interfacing with STL classes or custom Objective classes.
    • Testing: Using exceptions and standard C++ styles is permitted in testing code.
    • Error Handling: Because the interface to higher-level languages uses pure C, errors must be handled via error codes at the boundary.

    Memory Management

    • Allocation: The library prefers malloc/free over new/delete to maintain uniformity and avoid issues with partial object construction and std::nothrow portability.
    • Manual Management: Many objects are not RAII-compliant due to the use of POD (Plain Old Data) structures for performance (e.g., the "struct hack" for multiclass support) and to ensure compatibility with future MPI data transfers.
    • Safety: Use tools like valgrind, clang-tidy, and Clang sanitizers to catch allocation issues instead of relying solely on RAII smart pointers.
  8. Tune Explainable Boosting Machine (EBM) hyperparameters

    main

    Explainable Boosting Machines (EBMs) can be improved through hyperparameter tuning. Parameters are ordered by tuning importance in the documentation. While default settings balance efficiency and accuracy, tuning can improve model performance.

    Key Tuning Strategies:

    • High Importance: max_leaves, smoothing_rounds, learning_rate, and interactions.
    • Computational Trade-offs: inner_bags and outer_bags significantly impact fitting time.
    • Interpretability vs. Accuracy: Increasing interactions improves accuracy but reduces interpretability.
  9. Avoid One Definition Rule (ODR) violations in InterpretML compute modules

    main

    When developing or extending the compute modules in InterpretML, be aware that different translation units (e.g., .cpp files) may be compiled with different compiler switches (such as different SIMD or GPU optimization flags). To prevent crashes caused by One Definition Rule (ODR) violations or Application Binary Interface (ABI) mismatches, follow these architectural constraints:

    1. Use C Interfaces for Cross-Module Communication: Since C++ name mangling and class layouts are not standardized across different compiler options, use extern "C" interfaces when linking different modules (e.g., between standard CPU code and SIMD/GPU-optimized code).
    2. Restrict Shared Data to POD Types: Only use Plain Old Data (POD) structures or basic types when sharing data between translation units that are not compiled with identical compiler switches.
    3. Use Internal Linkage for Local Entities: For functions and variables that do not need to be shared across translation units, use the static keyword (often combined with inline or constexpr).
    4. Use Anonymous Namespaces for Local Classes: To give class definitions internal linkage and prevent them from being visible/conflicting across translation units, wrap them in anonymous namespaces.
  10. Initialize the Powerlift database and populate datasets

    main

    To use Powerlift, you must first initialize a Store using a connection string (e.g., SQLite). You can then use populate_with_datasets to download and feed datasets into the database once.

    import os
    from powerlift.bench import Store, populate_with_datasets
    
    # Initialize database
    conn_str = f"sqlite:///{os.getcwd()}/powerlift.db"
    store = Store(conn_str, force_recreate=False)
    
    # Download datasets once and feed into the database
    populate_with_datasets(store, cache_dir="~/.powerlift", exist_ok=True)