--- title: APERTURE AUDIT emoji: 🔍 colorFrom: purple colorTo: gray sdk: streamlit sdk_version: "1.38.0" python_version: "3.10" app_file: app.py pinned: false --- # Aperture Audit — Model-Agnostic Explainability Dashboard **Portfolio project 4 of 5** — a demo response to the regulatory pressure tech giants like Meta face over unexplainable ad-targeting and recommendation algorithms. Frameworks like the EU AI Act impose real penalties for high-stakes automated decisions (credit, ads, hiring) that can't be explained at the individual level. This project audits a credit model's decisions with two independently-derived explanation methods that are checked against each other, not just asserted. > ⚠️ **All data in this project is synthetic.** `data/credit_applications.csv` > is generated by `generate_synthetic_data.py` from a known synthetic > weight vector (see the file for the exact formula). No real applicant, > credit bureau, or financial data is used anywhere in this repo. ## Why this exists Explainability tools are often trusted uncritically: a SHAP value looks authoritative, so it's treated as ground truth. But SHAP implementations can have bugs, and approximate methods (KernelSHAP, LIME) are themselves estimates that can be wrong. This project builds in a validation step: because logistic regression's SHAP values have an exact closed form, this demo can generate a second, independently-derived explanation (LIME, built from scratch via local perturbation) and check that they agree — a legitimate audit technique for any explainability pipeline, not just this one. ## Architecture ``` credit application (synthetic) | v Model <- model.py logistic regression, chosen deliberately: it's the case where SHAP attribution has an exact closed form, not an approximation | v +-------------------------+-------------------------------+ | | v v Exact SHAP attribution LIME local surrogate explanation <- explain/shap_exact.py <- explain/lime_local.py phi_i = coef_i * (x_i - mean_i) perturb applicant, refit locally, (closed form, no sampling) extract local linear weights | | +-------------------------+-------------------------------+ | v Cross-check panel: do the two independently-derived explanations agree on direction and rough magnitude? ``` ## Try it ```bash pip install -r requirements.txt streamlit run app.py ``` Pick a synthetic applicant from the dataset (or set feature values manually with the sliders) and step through the three tabs: the exact SHAP-style attribution chart, the LIME cross-check (with a per-feature agreement table), and a plain-language audit narrative citing the top 3 drivers of the decision — the level of detail EU AI Act Article 13-style regulations require for high-stakes automated decisions. ## Project structure ``` xai-compliance-dashboard/ ├── app.py # Streamlit UI ├── model.py # logistic regression training + inference ├── generate_synthetic_data.py # produces data/credit_applications.csv ├── explain/ │ ├── shap_exact.py # exact closed-form SHAP attribution │ └── lime_local.py # from-scratch LIME local surrogate ├── data/ │ └── credit_applications.csv # SYNTHETIC credit application data └── requirements.txt ``` ## Production upgrade path | Demo component | Production equivalent | |---|---| | Logistic regression | Any production model (XGBoost, neural net) | | `shap_exact.py` closed-form attribution | Real `shap` package: `TreeExplainer` (tree models) or `KernelExplainer` (any model) | | `lime_local.py` from-scratch LIME | The `lime` package, or a hardened re-implementation with categorical feature support | | Streamlit dashboard | FastAPI + React audit UI, with per-decision explanation logging for regulatory record-keeping | | Single logistic model | Full audit trail across model versions, with drift-triggered re-explanation | ## Project landing page `docs/index.html` is a standalone, single-file static landing page (no build step) summarizing the project's results, method, and findings. To host it live on GitHub Pages: repo **Settings → Pages → Source: Deploy from a branch → Branch: main, folder: /docs → Save**. It'll be live within a minute or two at `https://data-geek-astronomy.github.io/APERTURE_AUDIT/`.