Spaces:
Sleeping
Sleeping
Upload 8 files
Browse files- README.md +45 -7
- app.py +348 -0
- examples.csv +4 -0
- reachfirst_v1.pkl +3 -0
- reference.json +442 -0
- requirements.txt +7 -0
- sample_month.csv +0 -0
- space_config.json +472 -0
README.md
CHANGED
|
@@ -1,15 +1,53 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 6.31.0
|
| 8 |
-
python_version:
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
| 11 |
license: cc-by-4.0
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
---
|
| 14 |
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Crosswind Workforce Partnership ReachFirst
|
| 3 |
+
emoji: 📬
|
| 4 |
+
colorFrom: green
|
| 5 |
+
colorTo: gray
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 6.31.0
|
| 8 |
+
python_version: "3.12"
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
| 11 |
license: cc-by-4.0
|
| 12 |
+
models:
|
| 13 |
+
- drdavidprivacy/reachfirst-model
|
| 14 |
+
datasets:
|
| 15 |
+
- drdavidprivacy/reachfirst-data
|
| 16 |
+
- drdavidprivacy/practicum-case-packs
|
| 17 |
+
short_description: ReachFirst v1, the signed model and its dossier
|
| 18 |
---
|
| 19 |
|
| 20 |
+
# ReachFirst v1: Crosswind Workforce Partnership
|
| 21 |
+
|
| 22 |
+
**Governance analyst:** [YOUR NAME]
|
| 23 |
+
|
| 24 |
+
**Program:** AI Governance Practicum, Track 1, cohort 1
|
| 25 |
+
|
| 26 |
+
This page is the public home of a governed system. The model is ReachFirst v1, the version the Chief AI Officer signed in Week 6. The app has three pages: the model (its fixed weights and three example records), monitoring (upload a monthly file and read it against the training file and the tripwires), and the dossier (the six documents below).
|
| 27 |
+
|
| 28 |
+
## The signed version
|
| 29 |
+
|
| 30 |
+
- File: `reachfirst_v1.pkl`, 4,300 bytes, SHA-256 `120234d9f9a111028a2d605d2779a9d8e151ff8d6f85df4ec0497f651595b953`
|
| 31 |
+
- Operating point: the top 20 percent of the ranked file
|
| 32 |
+
- Libraries: scikit-learn 1.9.1, fairlearn 0.15.0
|
| 33 |
+
- Data: the remediated working file in the program's dataset repository, loaded by link, never copied here: https://huggingface.co/datasets/drdavidprivacy/practicum-case-packs/resolve/main/crosswind_pilot_extract_remediated.csv (MD5 `ca9ed6d4b9dfd59f3f586b09da05b31f`)
|
| 34 |
+
|
| 35 |
+
- Model repository (the model card and the weights): https://huggingface.co/drdavidprivacy/reachfirst-model. Dataset repository (the datasheet and the remediation log): https://huggingface.co/datasets/drdavidprivacy/reachfirst-data
|
| 36 |
+
|
| 37 |
+
## The dossier
|
| 38 |
+
|
| 39 |
+
The six deliverables, in course order. Each opens in the browser.
|
| 40 |
+
- [Use Case Assessment (Week 1)](docs/01_Use-Case-Assessment.pdf)
|
| 41 |
+
- [EDA Observation Log (Week 2)](docs/02_EDA-Observation-Log.pdf)
|
| 42 |
+
- [Dataset Datasheet (Week 3)](docs/03_Dataset-Datasheet.pdf)
|
| 43 |
+
- [Model Selection Rationale (Week 4)](docs/04_Model-Selection-Rationale.pdf)
|
| 44 |
+
- [Model Card (Week 6)](docs/05_Model-Card.pdf)
|
| 45 |
+
- [Go/No-Go Decision Record (Week 7)](docs/06_Go-No-Go-Decision-Record.pdf)
|
| 46 |
+
|
| 47 |
+
## What this page is not
|
| 48 |
+
|
| 49 |
+
A score says where a household's record ranks on one list. It is not a decision about the household. The decisions, and the conditions on them, are in the Go/No-Go Decision Record above.
|
| 50 |
+
|
| 51 |
+
## Source
|
| 52 |
+
|
| 53 |
+
Built for the AI Governance Practicum (AI Governance Collective). The organization, the people, and the program are fictional. The data is a public dataset, remediated and documented in the dossier's datasheet.
|
app.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""The public page of a governed system: the signed model, its monitoring page, and the dossier.
|
| 2 |
+
Built for the AI Governance Practicum (AI Governance Collective). One app.py serves all three organizations; space_config.json says which."""
|
| 3 |
+
import json, os, pickle, io, warnings
|
| 4 |
+
import numpy as np, pandas as pd
|
| 5 |
+
import gradio as gr
|
| 6 |
+
import matplotlib
|
| 7 |
+
matplotlib.use("Agg")
|
| 8 |
+
import matplotlib.pyplot as plt
|
| 9 |
+
warnings.filterwarnings("ignore")
|
| 10 |
+
|
| 11 |
+
HERE = os.path.dirname(os.path.abspath(__file__))
|
| 12 |
+
|
| 13 |
+
# Hugging Face's free tier runs Gradio Spaces on ZeroGPU, which refuses to start an app that declares no GPU function.
|
| 14 |
+
# This app needs no GPU: the declaration below satisfies the check and is never called. On a plain CPU Space it is skipped.
|
| 15 |
+
try:
|
| 16 |
+
import spaces
|
| 17 |
+
@spaces.GPU
|
| 18 |
+
def _gpu_not_used():
|
| 19 |
+
return "This app runs on the CPU."
|
| 20 |
+
except Exception:
|
| 21 |
+
pass
|
| 22 |
+
CFG = json.load(open(os.path.join(HERE, "space_config.json")))
|
| 23 |
+
REF = json.load(open(os.path.join(HERE, "reference.json")))
|
| 24 |
+
MODEL = pickle.load(open(os.path.join(HERE, CFG["model_file"]), "rb"))
|
| 25 |
+
RECAL = pickle.load(open(os.path.join(HERE, CFG["recal_file"]), "rb")) if CFG.get("recal_file") else None
|
| 26 |
+
REASONS = pd.read_csv(os.path.join(HERE, CFG["reasons_file"])) if CFG.get("reasons_file") else None
|
| 27 |
+
EXAMPLES = pd.read_csv(os.path.join(HERE, "examples.csv"), keep_default_na=False)
|
| 28 |
+
INPUTS, KEPT, SHARE = CFG["inputs"], CFG["kept"], CFG["share"]
|
| 29 |
+
CAL_FLOOR = 25 # a calibration band is read only when it expects at least this many outcomes; a smaller band says nothing either way
|
| 30 |
+
SPACE_ID = os.environ.get("SPACE_ID", "")
|
| 31 |
+
WEEK6 = CFG["week6"]
|
| 32 |
+
|
| 33 |
+
# ----------------------------------------------------------------------------- scoring
|
| 34 |
+
def score_frame(X):
|
| 35 |
+
"""The production score. Where the Week 6 memo ratified fitted steps (the recalibration and the odds correction), they run here."""
|
| 36 |
+
X = X[INPUTS]
|
| 37 |
+
if RECAL is not None:
|
| 38 |
+
pf = RECAL.predict_proba(X)[:, 1]; f = CFG["odds_factor"]
|
| 39 |
+
return pf * f / (pf * f + 1 - pf)
|
| 40 |
+
return MODEL.predict_proba(X)[:, 1]
|
| 41 |
+
|
| 42 |
+
def contributions(X):
|
| 43 |
+
"""Each input's fixed weight times the record's value on the scaled, remover-adjusted inputs. The record's own reasons."""
|
| 44 |
+
Z = X[INPUTS]
|
| 45 |
+
for name, step in MODEL.steps[:-1]:
|
| 46 |
+
Z = step.transform(Z)
|
| 47 |
+
coef = MODEL.named_steps["model"].coef_[0]
|
| 48 |
+
return pd.DataFrame(np.asarray(Z) * coef, columns=KEPT, index=X.index)
|
| 49 |
+
|
| 50 |
+
def allowed_reasons(con):
|
| 51 |
+
"""Drop the columns a reason may never cite: a medication the record marks No (Alderwyn, Week 6 memo, ruling 5)."""
|
| 52 |
+
drugs = CFG.get("drug_fields", [])
|
| 53 |
+
if not drugs: return con
|
| 54 |
+
keep = [c for c in con.index if not any(c == d + "_No" for d in drugs)]
|
| 55 |
+
return con[keep]
|
| 56 |
+
|
| 57 |
+
def allowed_reasons_frame(frame):
|
| 58 |
+
drugs = CFG.get("drug_fields", [])
|
| 59 |
+
return frame[[c for c in frame.columns if not any(c == d + "_No" for d in drugs)]] if drugs else frame
|
| 60 |
+
|
| 61 |
+
def readable(col):
|
| 62 |
+
if REASONS is not None:
|
| 63 |
+
r = REASONS.loc[(REASONS.input == col) | ((REASONS.input + "_" + REASONS.value.astype(str)) == col), "reason"]
|
| 64 |
+
if len(r): return r.iloc[0]
|
| 65 |
+
for c in CFG["categorical"]:
|
| 66 |
+
if col.startswith(c + "_"): return f"{c} is {col[len(c) + 1:]}"
|
| 67 |
+
return col
|
| 68 |
+
|
| 69 |
+
def coerce(df):
|
| 70 |
+
"""Read a file the way the working file is read: numeric inputs as numbers, categorical inputs as text."""
|
| 71 |
+
df = df.copy()
|
| 72 |
+
for c in CFG["numeric"]:
|
| 73 |
+
if c in df: df[c] = pd.to_numeric(df[c], errors="coerce")
|
| 74 |
+
for c in CFG["categorical"]:
|
| 75 |
+
if c in df: df[c] = df[c].astype(str)
|
| 76 |
+
return df
|
| 77 |
+
|
| 78 |
+
def groups_of(frame):
|
| 79 |
+
g = {}
|
| 80 |
+
for gname, d in CFG["groups"].items():
|
| 81 |
+
col = d["col"]
|
| 82 |
+
if col not in frame: continue
|
| 83 |
+
if "bands" in d:
|
| 84 |
+
v = pd.to_numeric(frame[col], errors="coerce"); lab = pd.Series(["unrecorded"] * len(frame), index=frame.index, dtype=object)
|
| 85 |
+
for lo, hi, name in d["bands"]: lab[(v >= lo) & (v <= hi)] = name
|
| 86 |
+
g[gname] = lab
|
| 87 |
+
else:
|
| 88 |
+
s = frame[col].astype(str); g[gname] = s.map(d["map"]).fillna(s) if d.get("map") else s
|
| 89 |
+
return pd.DataFrame(g, index=frame.index)
|
| 90 |
+
|
| 91 |
+
def pct(x, d=1): return f"{x * 100:.{d}f} percent"
|
| 92 |
+
|
| 93 |
+
# ----------------------------------------------------------------------------- the signed version (the collapsed panel at the top)
|
| 94 |
+
def model_header():
|
| 95 |
+
a = CFG["artifacts"][CFG["model_file"]]
|
| 96 |
+
L = [f"**Organization:** {CFG['org']}. **Signed by:** {CFG['caio']} ({CFG['memo_ref']}). **Kept by:** {CFG['lead']}.",
|
| 97 |
+
f"**File:** `{CFG['model_file']}`, {a['bytes']:,} bytes, SHA-256 `{a['sha256']}`."]
|
| 98 |
+
if RECAL is not None:
|
| 99 |
+
r = CFG["artifacts"][CFG["recal_file"]]
|
| 100 |
+
L.append(f"**Fitted steps the memo ratified:** the isotonic recalibration (`{CFG['recal_file']}`, SHA-256 `{r['sha256']}`), then the odds correction to the {int(CFG['calibration']['book_rate']*100)} percent book rate (factor {CFG['odds_factor']}). Every score on this page has both applied.")
|
| 101 |
+
L.append(f"**What it is:** a logistic regression with {len(KEPT)} fitted columns from {len(INPUTS)} input fields. The weights are fixed. The same record gets the same score every time.")
|
| 102 |
+
L.append(f"**Operating point:** the top {int(SHARE*100)} percent of the ranked file gets {CFG['action']}. On the Week 6 test set ({WEEK6['test_rows']:,} {CFG['units']}) that was {WEEK6['flagged']:,} {CFG['units']}, of which {WEEK6['caught']:,} were {CFG['positive_label']}. Test-set ROC-AUC {WEEK6['roc_auc']:.3f}.")
|
| 103 |
+
L.append(f"**Libraries:** scikit-learn {CFG['versions']['sklearn']}, fairlearn {CFG['versions']['fairlearn']}. The model does not load on another version of scikit-learn, by design.")
|
| 104 |
+
return "\n\n".join(L)
|
| 105 |
+
|
| 106 |
+
def weights_table(n=25):
|
| 107 |
+
return pd.DataFrame([dict(column=c, weight=round(w, 4), meaning=readable(c)) for c, w in CFG["weights"][:n]])
|
| 108 |
+
|
| 109 |
+
# ----------------------------------------------------------------------------- tab 1: one record
|
| 110 |
+
CAT = [c for c in INPUTS if c in CFG["categorical"]]
|
| 111 |
+
NUM = [c for c in INPUTS if c in CFG["numeric"]]
|
| 112 |
+
FORM = CAT + NUM # the order of the form's controls
|
| 113 |
+
|
| 114 |
+
def _typical():
|
| 115 |
+
d = {c: REF["numeric"][c]["median"] for c in NUM}
|
| 116 |
+
for c in CAT:
|
| 117 |
+
r = REF["categorical"][c]; d[c] = max(r, key=r.get)
|
| 118 |
+
return d
|
| 119 |
+
|
| 120 |
+
def _case_row(i):
|
| 121 |
+
row = EXAMPLES.iloc[i]
|
| 122 |
+
return {c: (float(row[c]) if c in NUM else str(row[c])) for c in FORM}
|
| 123 |
+
|
| 124 |
+
PRESETS = {f"Typical {CFG['unit']} (training-file medians and most common values)": _typical()}
|
| 125 |
+
for i in range(len(EXAMPLES)):
|
| 126 |
+
PRESETS[f"{EXAMPLES['case'].iloc[i].capitalize()} (Week 6 case, rank {EXAMPLES['week6_rank'].iloc[i]} of {WEEK6['test_rows']:,})"] = _case_row(i)
|
| 127 |
+
FIRST = list(PRESETS)[0]
|
| 128 |
+
|
| 129 |
+
def apply_preset(name):
|
| 130 |
+
d = PRESETS[name]
|
| 131 |
+
return [d[c] for c in FORM]
|
| 132 |
+
|
| 133 |
+
def field_label(c):
|
| 134 |
+
"""The input's name, with the meaning of its codes where the program's group definitions give one (SEX: 1 male, 2 female)."""
|
| 135 |
+
for d in CFG["groups"].values():
|
| 136 |
+
if d["col"] == c and d.get("map"):
|
| 137 |
+
return c + " (" + ", ".join(f"{k} {v}" for k, v in d["map"].items()) + ")"
|
| 138 |
+
return c
|
| 139 |
+
|
| 140 |
+
def choices_for(c):
|
| 141 |
+
ch = sorted(REF["categorical"][c], key=str)
|
| 142 |
+
for v in EXAMPLES[c].astype(str).unique():
|
| 143 |
+
if v not in ch: ch.append(v)
|
| 144 |
+
return ch
|
| 145 |
+
|
| 146 |
+
def score_one(*vals):
|
| 147 |
+
row = {c: v for c, v in zip(FORM, vals)}
|
| 148 |
+
X = coerce(pd.DataFrame([row]))
|
| 149 |
+
p = float(score_frame(X)[0]); cut = REF["cut_score"]; inside = p >= cut
|
| 150 |
+
verdict = (f"## Score: **{p:.1%}**\n\n"
|
| 151 |
+
f"### {'🔴 Above the cut' if inside else '🟢 Below the cut'} (Week 6 cut = {cut:.1%}, the score of the last {CFG['unit']} inside the top {int(SHARE*100)} percent)\n\n"
|
| 152 |
+
f"At the operating point the {CFG['memo_ref']} set, this {CFG['unit']} {'would' if inside else 'would not'} be {CFG['flagged_word']}: {CFG['action']}. "
|
| 153 |
+
f"The score says where the record ranks. It is not a decision about the {CFG['person']}.")
|
| 154 |
+
con = allowed_reasons(contributions(X).iloc[0])
|
| 155 |
+
up = con[con > 0].sort_values(ascending=False).head(6); down = con[con < 0].sort_values().head(4)
|
| 156 |
+
items = list(up.items()) + list(down.items())
|
| 157 |
+
labs = [readable(c) for c, _ in items][::-1]; v = [float(x) for _, x in items][::-1]
|
| 158 |
+
fig, ax = plt.subplots(figsize=(11, 0.45 * len(v) + 1.8))
|
| 159 |
+
ax.barh(range(len(v)), v, color=["#d62728" if x > 0 else "#2ca02c" for x in v])
|
| 160 |
+
ax.set_yticks(range(len(v))); ax.set_yticklabels(labs, fontsize=9); ax.axvline(0, color="black", lw=0.8)
|
| 161 |
+
ax.set_xlabel(f"Toward {CFG['positive_label']} (red) or away from it (green): the fixed weight times this record's value", fontsize=9)
|
| 162 |
+
ax.set_title(f"Why {CFG['system']} scored this {CFG['unit']} {p:.1%}: the record's own reasons", fontsize=11, loc="left")
|
| 163 |
+
fig.tight_layout()
|
| 164 |
+
return verdict, fig
|
| 165 |
+
|
| 166 |
+
# ----------------------------------------------------------------------------- tab 2: batch upload
|
| 167 |
+
def score_batch(file, top_n):
|
| 168 |
+
if file is None: return None, f"Upload a CSV of {CFG['units']} to score (the model's input columns, one row per {CFG['unit']}).", None
|
| 169 |
+
try: df = coerce(pd.read_csv(file.name if hasattr(file, "name") else file, low_memory=False, keep_default_na=False, na_values=[]))
|
| 170 |
+
except Exception as e: return None, f"Could not read the file: {e}", None
|
| 171 |
+
missing = [c for c in INPUTS if c not in df.columns]
|
| 172 |
+
if missing: return None, "The file is missing input columns: " + ", ".join(missing) + ". Nothing was scored.", None
|
| 173 |
+
s = score_frame(df); order = np.argsort(-s, kind="stable"); k = int(round(SHARE * len(df)))
|
| 174 |
+
idc = CFG.get("id_col"); ids = df[idc].values if idc and idc in df.columns else np.arange(1, len(df) + 1)
|
| 175 |
+
con = allowed_reasons_frame(contributions(df)); top = [readable(con.columns[i]) for i in np.argmax(con.values, axis=1)]
|
| 176 |
+
out = pd.DataFrame({(idc if idc and idc in df.columns else "row"): ids, "score": np.round(s, 4), "ranked_in": np.where(np.arange(len(df)) >= 0, "", ""), "top_reason": top})
|
| 177 |
+
out = out.iloc[order].reset_index(drop=True); out.insert(0, "rank", np.arange(1, len(df) + 1)); out["ranked_in"] = np.where(out["rank"] <= k, "yes", "no")
|
| 178 |
+
path = os.path.join("/tmp", "ranked_list.csv"); out.to_csv(path, index=False)
|
| 179 |
+
msg = (f"Scored **{len(df):,}** {CFG['units']}. The top {int(SHARE*100)} percent, the operating point, is **{k:,}** {CFG['units']}. "
|
| 180 |
+
f"Showing the top **{int(top_n)}** by score (the team's capacity). The download carries every record with its score, rank, whether it is ranked in, and its own top reason.")
|
| 181 |
+
return out.head(int(top_n)), msg, path
|
| 182 |
+
|
| 183 |
+
# ----------------------------------------------------------------------------- tab 2: monitoring
|
| 184 |
+
def psi(ref_shares, new_shares):
|
| 185 |
+
keys = set(ref_shares) | set(new_shares); eps = 1e-4; v = 0.0
|
| 186 |
+
for k in keys:
|
| 187 |
+
a, b = max(ref_shares.get(k, 0.0), eps), max(new_shares.get(k, 0.0), eps); v += (b - a) * np.log(b / a)
|
| 188 |
+
return float(v)
|
| 189 |
+
|
| 190 |
+
def drift_table(df):
|
| 191 |
+
rows = []
|
| 192 |
+
for c in INPUTS:
|
| 193 |
+
if c not in df.columns: continue
|
| 194 |
+
watch = c in CFG["watch_fields"]
|
| 195 |
+
if c in REF["numeric"]:
|
| 196 |
+
r = REF["numeric"][c]; v = pd.to_numeric(df[c], errors="coerce"); edges = r["edges"]
|
| 197 |
+
if len(edges) < 3: continue
|
| 198 |
+
def shares(x):
|
| 199 |
+
b = np.clip(np.searchsorted(edges, x, side="right") - 1, 0, len(edges) - 2); return {str(i): float((b == i).mean()) for i in range(len(edges) - 1)}
|
| 200 |
+
ref_sh = r["shares"]; new_sh = shares(v.dropna().values)
|
| 201 |
+
idx = psi(ref_sh, new_sh)
|
| 202 |
+
rows.append(dict(input=c, kind="number", training_file=f"mean {r['mean']:,.2f}, median {r['median']:,.2f}", this_file=f"mean {v.mean():,.2f}, median {v.median():,.2f}", missing=int(v.isna().sum()), stability_index=round(idx, 3), reading=reading(idx), watched="yes" if watch else ""))
|
| 203 |
+
elif c in REF["categorical"]:
|
| 204 |
+
r = REF["categorical"][c]; vc = df[c].astype(str).value_counts(normalize=True); new_sh = {str(k): float(x) for k, x in vc.items()}
|
| 205 |
+
idx = psi(r, new_sh); top_r = max(r, key=r.get); top_n = max(new_sh, key=new_sh.get) if new_sh else ""
|
| 206 |
+
new_levels = [k for k in new_sh if k not in r]
|
| 207 |
+
rows.append(dict(input=c, kind="category", training_file=f"most common {top_r} ({pct(r[top_r])})", this_file=f"most common {top_n} ({pct(new_sh.get(top_n, 0))})" + (f"; new levels: {', '.join(new_levels)}" if new_levels else ""),
|
| 208 |
+
missing=int((df[c].astype(str) == "nan").sum()), stability_index=round(idx, 3), reading=reading(idx), watched="yes" if watch else ""))
|
| 209 |
+
t = pd.DataFrame(rows)
|
| 210 |
+
return t.sort_values(["watched", "stability_index"], ascending=[False, False]).reset_index(drop=True) if len(t) else t
|
| 211 |
+
|
| 212 |
+
def reading(idx):
|
| 213 |
+
return "stable" if idx < 0.10 else ("watch" if idx < 0.25 else "SHIFTED")
|
| 214 |
+
|
| 215 |
+
def group_table(df, s, flag, y):
|
| 216 |
+
"""Each group's rate at the cut beside the Week 6 test-set reading and the tripwire. With outcomes: the ruled check (false alarm or miss). Without: the share ranked in."""
|
| 217 |
+
G = groups_of(df); rows = []; check = CFG["group_check"]; line = CFG["group_tripwire"]
|
| 218 |
+
if y is not None:
|
| 219 |
+
pos, neg = y == 1, y == 0
|
| 220 |
+
port = (((flag == 1) & neg).sum() / max(neg.sum(), 1)) if check == "false_alarm" else (((flag == 0) & pos).sum() / max(pos.sum(), 1))
|
| 221 |
+
for gname in G.columns:
|
| 222 |
+
d = CFG["groups"][gname]; order = [b[2] for b in d["bands"]] if "bands" in d else d.get("order", [])
|
| 223 |
+
for lvl in sorted(G[gname].unique(), key=lambda s: (order.index(s) if s in order else len(order), str(s))):
|
| 224 |
+
m = (G[gname] == lvl).values; n = int(m.sum())
|
| 225 |
+
wk6 = REF["group_rates"].get(gname, {}).get(str(lvl), {})
|
| 226 |
+
covered = n >= CFG["min_group"] # the memo's group floor, applied to the month's file
|
| 227 |
+
if y is not None:
|
| 228 |
+
rate = (((flag == 1) & neg & m).sum() / max((neg & m).sum(), 1)) if check == "false_alarm" else (((flag == 0) & pos & m).sum() / max((pos & m).sum(), 1))
|
| 229 |
+
base = wk6.get("false_alarm" if check == "false_alarm" else "miss", np.nan)
|
| 230 |
+
over = rate > port * (1 + line)
|
| 231 |
+
result = (f"not judged (under the group floor of {CFG['min_group']:,})" if not covered else ("TRIP" if over else "inside the line"))
|
| 232 |
+
rows.append({"group": gname, "level": lvl, "records this file": n, ("false alarm rate" if check == "false_alarm" else "miss rate"): pct(rate), "whole file": pct(port), "line": pct(port * (1 + line)), "Week 6 test set": pct(base) if base == base else "", "watched": "yes" if str(lvl) in CFG["watch_groups"] else "", "result": result})
|
| 233 |
+
else:
|
| 234 |
+
rate = float(flag[m].mean()); base = wk6.get("flagged_share", np.nan)
|
| 235 |
+
rows.append({"group": gname, "level": lvl, "records this file": n, "share ranked in": pct(rate), "whole file": pct(SHARE), "Week 6 test set": pct(base) if base == base else "", "watched": "yes" if str(lvl) in CFG["watch_groups"] else "", "result": "no outcomes yet: share ranked in only" if covered else f"not judged (under the group floor of {CFG['min_group']:,})"})
|
| 236 |
+
return pd.DataFrame(rows)
|
| 237 |
+
|
| 238 |
+
def calibration_table(s, y):
|
| 239 |
+
cal = CFG["calibration"]; rows = []
|
| 240 |
+
for lo, hi, name in cal["bands"]:
|
| 241 |
+
m = (s >= lo) & (s < hi)
|
| 242 |
+
if m.sum() == 0: rows.append(dict(band=name, records=0, predicted="", observed="", gap_share_of_observed="", result="empty band")); continue
|
| 243 |
+
mp, ob = float(s[m].mean()), float(y[m].mean()); gap = abs(mp - ob); expected = mp * m.sum()
|
| 244 |
+
if expected < CAL_FLOOR: res = f"not read (fewer than {CAL_FLOOR} expected outcomes in the band)"
|
| 245 |
+
else: res = "no outcomes in band" if ob == 0 else ("pass" if gap / ob <= cal["tripwire"] else "TRIP")
|
| 246 |
+
rows.append(dict(band=name, records=int(m.sum()), predicted=pct(mp, 2), observed=pct(ob, 2), gap_share_of_observed=(pct(gap / ob, 1) if ob else ""), result=res))
|
| 247 |
+
return pd.DataFrame(rows)
|
| 248 |
+
|
| 249 |
+
def monitor(file):
|
| 250 |
+
empty = (None, None, None)
|
| 251 |
+
if file is None: return "Upload a monthly file: one row per " + CFG["unit"] + ", the model's input columns, the measurement fields, and the outcome column once it is known.", *empty
|
| 252 |
+
try: df = coerce(pd.read_csv(file.name if hasattr(file, "name") else file, low_memory=False, keep_default_na=False, na_values=[]))
|
| 253 |
+
except Exception as e: return f"Could not read the file: {e}", *empty
|
| 254 |
+
missing = [c for c in INPUTS if c not in df.columns]
|
| 255 |
+
if missing: return "The file is missing input columns: " + ", ".join(missing) + ". The job would hold this file out of the cycle (the input contract).", *empty
|
| 256 |
+
s = score_frame(df); order = np.argsort(-s, kind="stable"); k = int(round(SHARE * len(df))); flag = np.zeros(len(df), int); flag[order[:k]] = 1
|
| 257 |
+
y = (df[CFG["outcome"]].astype(str) == str(CFG["positive"])).astype(int).values if CFG["outcome"] in df.columns else None
|
| 258 |
+
above_cut = float((s >= REF["cut_score"]).mean())
|
| 259 |
+
L = [f"**File:** {len(df):,} {CFG['units']}, {df.shape[1]} columns. Outcome column `{CFG['outcome']}`: " + ("present, so the ruled checks run." if y is not None else "absent, so only the input and score readings run. Upload again when the outcomes are known."),
|
| 260 |
+
f"**Scores:** mean {s.mean():.4f} (training-file positive rate {pct(REF['positive_rate'])}). {pct(above_cut)} of this file scores above the Week 6 cut of {REF['cut_score']:.4f}, against {pct(SHARE, 0)} by construction on the test set. The top {int(SHARE*100)} percent of this file is {k:,} {CFG['units']}.",
|
| 261 |
+
f"**Inputs:** the stability index compares each input's distribution with the training file's ({REF['rows']:,} rows). Under 0.10 is stable, 0.10 to 0.25 is watch, over 0.25 is shifted. These lines are the usual working lines, provisional until the Week 8 monitoring plan sets the program's own. Watched fields: {CFG['watch_fields_label']}."]
|
| 262 |
+
if y is not None:
|
| 263 |
+
pos = y == 1
|
| 264 |
+
L.append(f"**At the cut:** {int((flag & pos).sum()):,} of the {int(pos.sum()):,} {CFG['positive_label']} {CFG['units']} are ranked in ({pct((flag & pos).sum() / max(pos.sum(), 1))}); the whole-file {'false alarm' if CFG['group_check'] == 'false_alarm' else 'miss'} rate is the line every group is read against, plus {int(CFG['group_tripwire']*100)} percent ({CFG['memo_ref']}).")
|
| 265 |
+
cal = calibration_table(s, y) if (CFG.get("calibration") and y is not None) else None
|
| 266 |
+
if cal is not None:
|
| 267 |
+
worst = [r for r in cal.result if r == "TRIP"]; read = [r for r in cal.result if r in ("TRIP", "pass")]
|
| 268 |
+
L.append(f"**Calibration:** predicted against observed by score band, line {int(CFG['calibration']['tripwire']*100)} percent of observed. Bands that expect fewer than {CAL_FLOOR} outcomes are not read. " + (f"{len(read)} band(s) read, every one inside the line." if not worst else f"{len(worst)} of {len(read)} band(s) read are over the line: the calibration condition (ruling 1) is not met for this file."))
|
| 269 |
+
return "\n\n".join(L), drift_table(df), group_table(df, s, flag, y), cal
|
| 270 |
+
|
| 271 |
+
# ----------------------------------------------------------------------------- tab 4: the dossier
|
| 272 |
+
def dossier_markdown():
|
| 273 |
+
L = [f"## The dossier: {CFG['system']} at {CFG['org']}", "", "The six deliverables of the practicum, in course order. Each opens in the browser.", ""]
|
| 274 |
+
for f, label in CFG["docs"]:
|
| 275 |
+
p = os.path.join(HERE, "docs", f)
|
| 276 |
+
if SPACE_ID: url = f"https://huggingface.co/spaces/{SPACE_ID}/resolve/main/docs/{f}"
|
| 277 |
+
else: url = f"docs/{f}"
|
| 278 |
+
L.append(f"- [{label}]({url})" + ("" if os.path.exists(p) else " (not uploaded yet)"))
|
| 279 |
+
L += ["", f"**Monitoring targets from the {CFG['memo_ref']}:**"] + [f"- {m}" for m in CFG["monitoring_lines"]]
|
| 280 |
+
L += ["", f"**Data:** [{CFG['data_file']}]({CFG['data_url']}) in the program's dataset repository (MD5 `{CFG['md5']}`). The data is not copied into this page."]
|
| 281 |
+
return "\n".join(L)
|
| 282 |
+
|
| 283 |
+
# ----------------------------------------------------------------------------- the page
|
| 284 |
+
INTRO = f"""
|
| 285 |
+
# {CFG['system']} {CFG['version']}: {CFG['org']}
|
| 286 |
+
**Governance analyst: [YOUR NAME]** · a teaching deployment for the *AI Governance Practicum*, Track 1
|
| 287 |
+
|
| 288 |
+
---
|
| 289 |
+
|
| 290 |
+
{CFG['system']} estimates, for each {CFG['unit']}, the likelihood of {CFG['positive_label']}, ranks the file, and sends the top {int(SHARE*100)} percent to a person for {CFG['action']}. This page runs the signed version ({CFG['memo_ref']}). It is for **education**, not real decisions. A score says where a {CFG['person']}'s record ranks on one list. It is not a decision about the {CFG['person']}.
|
| 291 |
+
"""
|
| 292 |
+
|
| 293 |
+
with gr.Blocks(title=f"{CFG['org']} {CFG['system']}") as demo:
|
| 294 |
+
gr.Markdown(INTRO)
|
| 295 |
+
with gr.Accordion("About the signed version: the file, its hash, the fitted steps, the weights", open=False):
|
| 296 |
+
gr.Markdown(model_header())
|
| 297 |
+
gr.Markdown("**The fixed weights.** The largest by size, with what each column means. A positive weight pushes the score up.")
|
| 298 |
+
gr.Dataframe(weights_table(), interactive=False, wrap=True)
|
| 299 |
+
|
| 300 |
+
with gr.Tab(f"1 · Single {CFG['unit']}"):
|
| 301 |
+
gr.Markdown(f"Score one {CFG['unit']}, then read the **reasons**. Load a Week 6 case to fill the form, or edit any field and score again.")
|
| 302 |
+
with gr.Row():
|
| 303 |
+
preset = gr.Dropdown(list(PRESETS), label="Load an example", value=FIRST)
|
| 304 |
+
d0 = PRESETS[FIRST]
|
| 305 |
+
widgets = {}
|
| 306 |
+
with gr.Accordion("Categorical inputs", open=True):
|
| 307 |
+
for i in range(0, len(CAT), 4):
|
| 308 |
+
with gr.Row():
|
| 309 |
+
for c in CAT[i:i + 4]:
|
| 310 |
+
widgets[c] = gr.Dropdown(choices_for(c), value=d0[c], label=field_label(c), allow_custom_value=True)
|
| 311 |
+
with gr.Accordion("Numeric inputs", open=(len(CAT) == 0)):
|
| 312 |
+
for i in range(0, len(NUM), 4):
|
| 313 |
+
with gr.Row():
|
| 314 |
+
for c in NUM[i:i + 4]:
|
| 315 |
+
widgets[c] = gr.Number(value=d0[c], label=c)
|
| 316 |
+
ordered = [widgets[c] for c in FORM]
|
| 317 |
+
score_btn = gr.Button(f"Score this {CFG['unit']}", variant="primary")
|
| 318 |
+
out_md = gr.Markdown(); out_plot = gr.Plot()
|
| 319 |
+
preset.change(apply_preset, preset, ordered)
|
| 320 |
+
score_btn.click(score_one, ordered, [out_md, out_plot])
|
| 321 |
+
|
| 322 |
+
with gr.Tab("2 · Batch upload"):
|
| 323 |
+
gr.Markdown(f"Upload a CSV of {CFG['units']} (the same columns as the working file). {CFG['system']} scores every row, ranks the file, and marks the top {int(SHARE*100)} percent, the operating point the {CFG['memo_ref']} set. Top-N is how many of the ranked list the team can work. `sample_month.csv` in this repository is a file to try.")
|
| 324 |
+
with gr.Row():
|
| 325 |
+
up = gr.File(label=f"{CFG['units'].capitalize()} CSV", file_types=[".csv"])
|
| 326 |
+
with gr.Column():
|
| 327 |
+
topn = gr.Slider(5, 100, value=20, step=5, label="Top-N by capacity (how many the team can work)")
|
| 328 |
+
batch_btn = gr.Button("Score & rank", variant="primary")
|
| 329 |
+
batch_msg = gr.Markdown(); batch_tbl = gr.Dataframe(interactive=False, wrap=True); batch_dl = gr.File(label="Download the full ranked list")
|
| 330 |
+
batch_btn.click(score_batch, [up, topn], [batch_tbl, batch_msg, batch_dl])
|
| 331 |
+
|
| 332 |
+
with gr.Tab("3 · Monitoring"):
|
| 333 |
+
gr.Markdown(f"**One month at a time.** Upload the month's file. The page reads it against the training file and the tripwires the {CFG['memo_ref']} set: the inputs' distributions, the scores, the groups at the cut, " + ("and the calibration table." if CFG.get("calibration") else "and the ruled group check.") + f" `sample_month.csv` in this repository is a stand-in drawn from the Week 6 test set, so the page can be tried before a monthly file exists.")
|
| 334 |
+
mf = gr.File(label="Monthly file (CSV)", file_types=[".csv"])
|
| 335 |
+
mon_btn = gr.Button("Read this month", variant="primary")
|
| 336 |
+
m_msg = gr.Markdown()
|
| 337 |
+
m_drift = gr.Dataframe(interactive=False, label="Inputs against the training file", wrap=True)
|
| 338 |
+
m_groups = gr.Dataframe(interactive=False, label="Groups at the cut, against the whole file and the line", wrap=True)
|
| 339 |
+
m_cal = gr.Dataframe(interactive=False, label="Calibration by score band", visible=bool(CFG.get("calibration")))
|
| 340 |
+
mon_btn.click(monitor, mf, [m_msg, m_drift, m_groups, m_cal])
|
| 341 |
+
|
| 342 |
+
with gr.Tab("4 · The dossier"):
|
| 343 |
+
gr.Markdown(dossier_markdown())
|
| 344 |
+
|
| 345 |
+
gr.Markdown(f"---\n*{CFG['system']} is a fictional model built on a public dataset for the AI Governance Practicum (AI Governance Collective). The organization, the people, and the program are fictional. Data: [{CFG['data_file']}]({CFG['data_url']}).*")
|
| 346 |
+
|
| 347 |
+
if __name__ == "__main__":
|
| 348 |
+
demo.launch()
|
examples.csv
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
case,case_note,age,workclass,education,marital-status,occupation,capital-gain,capital-loss,hours-per-week,relationship_model,capital_gain_topcoded,income,sex,race,native_country_report,week6_rank
|
| 2 |
+
caught,"caught (ranked in, at or below the line)",20,Private,Some-college,Never-married,Priv-house-serv,0,0,45,Own-child,0,<=50K,Female,White,United-States,975
|
| 3 |
+
missed,"missed (ranked out, at or below the line; the first record below the cut)",28,Private,Some-college,Never-married,Adm-clerical,0,0,40,Other-relative,0,<=50K,Male,Black,United-States,1953
|
| 4 |
+
false alarm,"false alarm (ranked in, above the line; the highest-scored above-the-line record)",33,Private,7th-8th,Never-married,Farming-fishing,0,0,40,Not-in-family,0,>50K,Male,White,Mexico,417
|
reachfirst_v1.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:120234d9f9a111028a2d605d2779a9d8e151ff8d6f85df4ec0497f651595b953
|
| 3 |
+
size 4300
|
reference.json
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rows": 39032,
|
| 3 |
+
"test_rows": 9758,
|
| 4 |
+
"cut_score": 0.9864791972217691,
|
| 5 |
+
"share": 0.2,
|
| 6 |
+
"positive_rate": 0.7605810616929699,
|
| 7 |
+
"numeric": {
|
| 8 |
+
"age": {
|
| 9 |
+
"mean": 38.57839721254356,
|
| 10 |
+
"std": 13.709782584667774,
|
| 11 |
+
"median": 37.0,
|
| 12 |
+
"edges": [
|
| 13 |
+
17.0,
|
| 14 |
+
22.0,
|
| 15 |
+
26.0,
|
| 16 |
+
30.0,
|
| 17 |
+
33.0,
|
| 18 |
+
37.0,
|
| 19 |
+
41.0,
|
| 20 |
+
45.0,
|
| 21 |
+
50.0,
|
| 22 |
+
58.0,
|
| 23 |
+
90.0
|
| 24 |
+
],
|
| 25 |
+
"shares": {
|
| 26 |
+
"0": 0.09804775568764092,
|
| 27 |
+
"1": 0.10040479606476738,
|
| 28 |
+
"2": 0.09971305595408896,
|
| 29 |
+
"3": 0.07949887271981963,
|
| 30 |
+
"4": 0.11008915761426522,
|
| 31 |
+
"5": 0.10045603607296577,
|
| 32 |
+
"6": 0.09397417503586801,
|
| 33 |
+
"7": 0.10086595613855298,
|
| 34 |
+
"8": 0.11239495798319328,
|
| 35 |
+
"9": 0.10455523672883787
|
| 36 |
+
}
|
| 37 |
+
},
|
| 38 |
+
"capital-gain": {
|
| 39 |
+
"mean": 1078.3918067226891,
|
| 40 |
+
"std": 7454.4260044832945,
|
| 41 |
+
"median": 0.0,
|
| 42 |
+
"edges": [
|
| 43 |
+
0.0,
|
| 44 |
+
99999.0
|
| 45 |
+
],
|
| 46 |
+
"shares": {
|
| 47 |
+
"0": 1.0
|
| 48 |
+
}
|
| 49 |
+
},
|
| 50 |
+
"capital-loss": {
|
| 51 |
+
"mean": 86.47678827628613,
|
| 52 |
+
"std": 401.1241413791568,
|
| 53 |
+
"median": 0.0,
|
| 54 |
+
"edges": [
|
| 55 |
+
0.0,
|
| 56 |
+
4356.0
|
| 57 |
+
],
|
| 58 |
+
"shares": {
|
| 59 |
+
"0": 1.0
|
| 60 |
+
}
|
| 61 |
+
},
|
| 62 |
+
"hours-per-week": {
|
| 63 |
+
"mean": 40.41898954703833,
|
| 64 |
+
"std": 12.400096371479366,
|
| 65 |
+
"median": 40.0,
|
| 66 |
+
"edges": [
|
| 67 |
+
1.0,
|
| 68 |
+
24.0,
|
| 69 |
+
35.0,
|
| 70 |
+
40.0,
|
| 71 |
+
48.0,
|
| 72 |
+
55.0,
|
| 73 |
+
99.0
|
| 74 |
+
],
|
| 75 |
+
"shares": {
|
| 76 |
+
"0": 0.09469153515064563,
|
| 77 |
+
"1": 0.07765423242467719,
|
| 78 |
+
"2": 0.06730375076860012,
|
| 79 |
+
"3": 0.5458085673293708,
|
| 80 |
+
"4": 0.10965361754457881,
|
| 81 |
+
"5": 0.10488829678212748
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
},
|
| 85 |
+
"categorical": {
|
| 86 |
+
"workclass": {
|
| 87 |
+
"Private": 0.6928417708546833,
|
| 88 |
+
"Self-emp-not-inc": 0.07947325271572044,
|
| 89 |
+
"Local-gov": 0.06507481041196966,
|
| 90 |
+
"?": 0.05741442918630867,
|
| 91 |
+
"State-gov": 0.04078704652592744,
|
| 92 |
+
"Self-emp-inc": 0.03484320557491289,
|
| 93 |
+
"Federal-gov": 0.02897622463619594,
|
| 94 |
+
"Without-pay": 0.0004099200655872105,
|
| 95 |
+
"Never-worked": 0.0001793400286944046
|
| 96 |
+
},
|
| 97 |
+
"education": {
|
| 98 |
+
"HS-grad": 0.32232527157204344,
|
| 99 |
+
"Some-college": 0.2220998155359705,
|
| 100 |
+
"Bachelors": 0.16540274646443942,
|
| 101 |
+
"Masters": 0.054647468743594996,
|
| 102 |
+
"Assoc-voc": 0.041863086698093875,
|
| 103 |
+
"11th": 0.037046525927444146,
|
| 104 |
+
"Assoc-acdm": 0.033101045296167246,
|
| 105 |
+
"10th": 0.028258864521418323,
|
| 106 |
+
"7th-8th": 0.01916376306620209,
|
| 107 |
+
"Prof-school": 0.017114162738266037,
|
| 108 |
+
"9th": 0.015884402541504406,
|
| 109 |
+
"12th": 0.013783562205369953,
|
| 110 |
+
"Doctorate": 0.012425701988112318,
|
| 111 |
+
"5th-6th": 0.010401721664275465,
|
| 112 |
+
"1st-4th": 0.005021520803443328,
|
| 113 |
+
"Preschool": 0.0014603402336544375
|
| 114 |
+
},
|
| 115 |
+
"marital-status": {
|
| 116 |
+
"Married-civ-spouse": 0.4578038532486165,
|
| 117 |
+
"Never-married": 0.3324195531871285,
|
| 118 |
+
"Divorced": 0.13376204140192663,
|
| 119 |
+
"Widowed": 0.031461365033818404,
|
| 120 |
+
"Separated": 0.030769624923139987,
|
| 121 |
+
"Married-spouse-absent": 0.012963722074195532,
|
| 122 |
+
"Married-AF-spouse": 0.000819840131174421
|
| 123 |
+
},
|
| 124 |
+
"occupation": {
|
| 125 |
+
"Prof-specialty": 0.12689588030334084,
|
| 126 |
+
"Exec-managerial": 0.12435949989751999,
|
| 127 |
+
"Craft-repair": 0.12433387989342078,
|
| 128 |
+
"Adm-clerical": 0.11511067841770854,
|
| 129 |
+
"Sales": 0.11293297806927649,
|
| 130 |
+
"Other-service": 0.10089157614265218,
|
| 131 |
+
"Machine-op-inspct": 0.06212850994056159,
|
| 132 |
+
"?": 0.057593769215003074,
|
| 133 |
+
"Transport-moving": 0.04880610780897725,
|
| 134 |
+
"Handlers-cleaners": 0.04176060668169707,
|
| 135 |
+
"Farming-fishing": 0.030205984832957573,
|
| 136 |
+
"Tech-support": 0.029232424677187948,
|
| 137 |
+
"Protective-serv": 0.02034228325476532,
|
| 138 |
+
"Priv-house-serv": 0.00509838081574093,
|
| 139 |
+
"Armed-Forces": 0.00030744004919040785
|
| 140 |
+
},
|
| 141 |
+
"relationship_model": {
|
| 142 |
+
"Spouse": 0.45127075220332036,
|
| 143 |
+
"Not-in-family": 0.25586698093871696,
|
| 144 |
+
"Own-child": 0.15820352531256404,
|
| 145 |
+
"Unmarried": 0.10358167657306826,
|
| 146 |
+
"Other-relative": 0.031077064972330395
|
| 147 |
+
},
|
| 148 |
+
"capital_gain_topcoded": {
|
| 149 |
+
"0": 0.9950040992006559,
|
| 150 |
+
"1": 0.0049959007993441275
|
| 151 |
+
}
|
| 152 |
+
},
|
| 153 |
+
"groups": {
|
| 154 |
+
"sex": {
|
| 155 |
+
"Male": 26130,
|
| 156 |
+
"Female": 12902
|
| 157 |
+
},
|
| 158 |
+
"race": {
|
| 159 |
+
"White": 33372,
|
| 160 |
+
"Black": 3721,
|
| 161 |
+
"Asian-Pac-Islander": 1217,
|
| 162 |
+
"Amer-Indian-Eskimo": 387,
|
| 163 |
+
"Other": 335
|
| 164 |
+
},
|
| 165 |
+
"age band": {
|
| 166 |
+
"25 to 34": 10071,
|
| 167 |
+
"35 to 44": 9748,
|
| 168 |
+
"45 to 54": 6959,
|
| 169 |
+
"under 25": 6808,
|
| 170 |
+
"55 to 64": 3799,
|
| 171 |
+
"65 and over": 1647
|
| 172 |
+
},
|
| 173 |
+
"marital status": {
|
| 174 |
+
"Married-civ-spouse": 17869,
|
| 175 |
+
"Never-married": 12975,
|
| 176 |
+
"Divorced": 5221,
|
| 177 |
+
"Widowed": 1228,
|
| 178 |
+
"Separated": 1201,
|
| 179 |
+
"Married-spouse-absent": 506,
|
| 180 |
+
"Married-AF-spouse": 32
|
| 181 |
+
},
|
| 182 |
+
"country of origin": {
|
| 183 |
+
"United-States": 35034,
|
| 184 |
+
"all other": 953,
|
| 185 |
+
"Mexico": 745,
|
| 186 |
+
"unrecorded": 682,
|
| 187 |
+
"Philippines": 234,
|
| 188 |
+
"Germany": 166,
|
| 189 |
+
"Canada": 148,
|
| 190 |
+
"Puerto-Rico": 147,
|
| 191 |
+
"India": 125,
|
| 192 |
+
"El-Salvador": 122,
|
| 193 |
+
"Cuba": 120,
|
| 194 |
+
"England": 105,
|
| 195 |
+
"China": 101,
|
| 196 |
+
"South": 96,
|
| 197 |
+
"Italy": 95,
|
| 198 |
+
"Dominican-Republic": 80,
|
| 199 |
+
"Jamaica": 79
|
| 200 |
+
}
|
| 201 |
+
},
|
| 202 |
+
"portfolio": {
|
| 203 |
+
"false_alarm": 0.0029965753424657533,
|
| 204 |
+
"miss": 0.7379412557262194,
|
| 205 |
+
"flagged": 1952,
|
| 206 |
+
"caught": 1945
|
| 207 |
+
},
|
| 208 |
+
"group_rates": {
|
| 209 |
+
"sex": {
|
| 210 |
+
"Male": {
|
| 211 |
+
"n": 6484,
|
| 212 |
+
"false_alarm": 0.0025380710659898475,
|
| 213 |
+
"miss": 0.7780239255649092,
|
| 214 |
+
"flagged_share": 0.155305367057372
|
| 215 |
+
},
|
| 216 |
+
"Female": {
|
| 217 |
+
"n": 3274,
|
| 218 |
+
"false_alarm": 0.00546448087431694,
|
| 219 |
+
"miss": 0.6757221458046767,
|
| 220 |
+
"flagged_share": 0.28863775198533903
|
| 221 |
+
}
|
| 222 |
+
},
|
| 223 |
+
"race": {
|
| 224 |
+
"White": {
|
| 225 |
+
"n": 8342,
|
| 226 |
+
"false_alarm": 0.0028142589118198874,
|
| 227 |
+
"miss": 0.7516908212560387,
|
| 228 |
+
"flagged_share": 0.18556701030927836
|
| 229 |
+
},
|
| 230 |
+
"Black": {
|
| 231 |
+
"n": 962,
|
| 232 |
+
"false_alarm": 0.0,
|
| 233 |
+
"miss": 0.6485849056603774,
|
| 234 |
+
"flagged_share": 0.3097713097713098
|
| 235 |
+
},
|
| 236 |
+
"Amer-Indian-Eskimo": {
|
| 237 |
+
"n": 83,
|
| 238 |
+
"false_alarm": 0.0,
|
| 239 |
+
"miss": 0.6153846153846154,
|
| 240 |
+
"flagged_share": 0.3614457831325301
|
| 241 |
+
},
|
| 242 |
+
"Asian-Pac-Islander": {
|
| 243 |
+
"n": 300,
|
| 244 |
+
"false_alarm": 0.013157894736842105,
|
| 245 |
+
"miss": 0.7410714285714286,
|
| 246 |
+
"flagged_share": 0.19666666666666666
|
| 247 |
+
},
|
| 248 |
+
"Other": {
|
| 249 |
+
"n": 71,
|
| 250 |
+
"false_alarm": 0.0,
|
| 251 |
+
"miss": 0.7258064516129032,
|
| 252 |
+
"flagged_share": 0.23943661971830985
|
| 253 |
+
}
|
| 254 |
+
},
|
| 255 |
+
"age band": {
|
| 256 |
+
"under 25": {
|
| 257 |
+
"n": 1601,
|
| 258 |
+
"false_alarm": 0.07142857142857142,
|
| 259 |
+
"miss": 0.3314429741650914,
|
| 260 |
+
"flagged_share": 0.6633354153653966
|
| 261 |
+
},
|
| 262 |
+
"25 to 34": {
|
| 263 |
+
"n": 2493,
|
| 264 |
+
"false_alarm": 0.007537688442211055,
|
| 265 |
+
"miss": 0.7527446300715991,
|
| 266 |
+
"flagged_share": 0.2089851584436422
|
| 267 |
+
},
|
| 268 |
+
"35 to 44": {
|
| 269 |
+
"n": 2436,
|
| 270 |
+
"false_alarm": 0.0,
|
| 271 |
+
"miss": 0.8971393791844188,
|
| 272 |
+
"flagged_share": 0.069376026272578
|
| 273 |
+
},
|
| 274 |
+
"45 to 54": {
|
| 275 |
+
"n": 1806,
|
| 276 |
+
"false_alarm": 0.0,
|
| 277 |
+
"miss": 0.9044585987261147,
|
| 278 |
+
"flagged_share": 0.05813953488372093
|
| 279 |
+
},
|
| 280 |
+
"55 to 64": {
|
| 281 |
+
"n": 983,
|
| 282 |
+
"false_alarm": 0.006134969325153374,
|
| 283 |
+
"miss": 0.9162861491628614,
|
| 284 |
+
"flagged_share": 0.05798575788402848
|
| 285 |
+
},
|
| 286 |
+
"65 and over": {
|
| 287 |
+
"n": 439,
|
| 288 |
+
"false_alarm": 0.01020408163265306,
|
| 289 |
+
"miss": 0.8914956011730205,
|
| 290 |
+
"flagged_share": 0.08656036446469248
|
| 291 |
+
}
|
| 292 |
+
},
|
| 293 |
+
"marital status": {
|
| 294 |
+
"Never-married": {
|
| 295 |
+
"n": 3107,
|
| 296 |
+
"false_alarm": 0.030534351145038167,
|
| 297 |
+
"miss": 0.47043010752688175,
|
| 298 |
+
"flagged_share": 0.5085291277759897
|
| 299 |
+
},
|
| 300 |
+
"Separated": {
|
| 301 |
+
"n": 329,
|
| 302 |
+
"false_alarm": 0.0,
|
| 303 |
+
"miss": 0.7339743589743589,
|
| 304 |
+
"flagged_share": 0.25227963525835867
|
| 305 |
+
},
|
| 306 |
+
"Married-civ-spouse": {
|
| 307 |
+
"n": 4497,
|
| 308 |
+
"false_alarm": 0.0,
|
| 309 |
+
"miss": 0.9971887550200803,
|
| 310 |
+
"flagged_share": 0.00155659328441183
|
| 311 |
+
},
|
| 312 |
+
"Married-spouse-absent": {
|
| 313 |
+
"n": 121,
|
| 314 |
+
"false_alarm": 0.0,
|
| 315 |
+
"miss": 0.6181818181818182,
|
| 316 |
+
"flagged_share": 0.34710743801652894
|
| 317 |
+
},
|
| 318 |
+
"Divorced": {
|
| 319 |
+
"n": 1409,
|
| 320 |
+
"false_alarm": 0.013986013986013986,
|
| 321 |
+
"miss": 0.8570300157977883,
|
| 322 |
+
"flagged_share": 0.12987934705464868
|
| 323 |
+
},
|
| 324 |
+
"Widowed": {
|
| 325 |
+
"n": 290,
|
| 326 |
+
"false_alarm": 0.04,
|
| 327 |
+
"miss": 0.7886792452830189,
|
| 328 |
+
"flagged_share": 0.19655172413793104
|
| 329 |
+
},
|
| 330 |
+
"Married-AF-spouse": {
|
| 331 |
+
"n": 5,
|
| 332 |
+
"false_alarm": 0.0,
|
| 333 |
+
"miss": 1.0,
|
| 334 |
+
"flagged_share": 0.0
|
| 335 |
+
}
|
| 336 |
+
},
|
| 337 |
+
"country of origin": {
|
| 338 |
+
"United-States": {
|
| 339 |
+
"n": 8758,
|
| 340 |
+
"false_alarm": 0.0014012143858010276,
|
| 341 |
+
"miss": 0.7417258576394137,
|
| 342 |
+
"flagged_share": 0.1954784197305321
|
| 343 |
+
},
|
| 344 |
+
"all other": {
|
| 345 |
+
"n": 258,
|
| 346 |
+
"false_alarm": 0.0,
|
| 347 |
+
"miss": 0.7635467980295566,
|
| 348 |
+
"flagged_share": 0.18604651162790697
|
| 349 |
+
},
|
| 350 |
+
"Jamaica": {
|
| 351 |
+
"n": 27,
|
| 352 |
+
"false_alarm": 0.0,
|
| 353 |
+
"miss": 0.5833333333333334,
|
| 354 |
+
"flagged_share": 0.37037037037037035
|
| 355 |
+
},
|
| 356 |
+
"Canada": {
|
| 357 |
+
"n": 34,
|
| 358 |
+
"false_alarm": 0.0,
|
| 359 |
+
"miss": 1.0,
|
| 360 |
+
"flagged_share": 0.0
|
| 361 |
+
},
|
| 362 |
+
"unrecorded": {
|
| 363 |
+
"n": 174,
|
| 364 |
+
"false_alarm": 0.038461538461538464,
|
| 365 |
+
"miss": 0.7868852459016393,
|
| 366 |
+
"flagged_share": 0.16091954022988506
|
| 367 |
+
},
|
| 368 |
+
"Mexico": {
|
| 369 |
+
"n": 198,
|
| 370 |
+
"false_alarm": 0.07692307692307693,
|
| 371 |
+
"miss": 0.5621621621621622,
|
| 372 |
+
"flagged_share": 0.41414141414141414
|
| 373 |
+
},
|
| 374 |
+
"Germany": {
|
| 375 |
+
"n": 40,
|
| 376 |
+
"false_alarm": 0.0,
|
| 377 |
+
"miss": 0.8484848484848485,
|
| 378 |
+
"flagged_share": 0.125
|
| 379 |
+
},
|
| 380 |
+
"Puerto-Rico": {
|
| 381 |
+
"n": 37,
|
| 382 |
+
"false_alarm": 0.2,
|
| 383 |
+
"miss": 0.75,
|
| 384 |
+
"flagged_share": 0.24324324324324326
|
| 385 |
+
},
|
| 386 |
+
"Italy": {
|
| 387 |
+
"n": 10,
|
| 388 |
+
"false_alarm": 0.0,
|
| 389 |
+
"miss": 0.8333333333333334,
|
| 390 |
+
"flagged_share": 0.1
|
| 391 |
+
},
|
| 392 |
+
"Philippines": {
|
| 393 |
+
"n": 60,
|
| 394 |
+
"false_alarm": 0.0,
|
| 395 |
+
"miss": 0.673469387755102,
|
| 396 |
+
"flagged_share": 0.26666666666666666
|
| 397 |
+
},
|
| 398 |
+
"Dominican-Republic": {
|
| 399 |
+
"n": 23,
|
| 400 |
+
"false_alarm": 0.0,
|
| 401 |
+
"miss": 0.45454545454545453,
|
| 402 |
+
"flagged_share": 0.5217391304347826
|
| 403 |
+
},
|
| 404 |
+
"Cuba": {
|
| 405 |
+
"n": 18,
|
| 406 |
+
"false_alarm": 0.0,
|
| 407 |
+
"miss": 0.7857142857142857,
|
| 408 |
+
"flagged_share": 0.16666666666666666
|
| 409 |
+
},
|
| 410 |
+
"China": {
|
| 411 |
+
"n": 21,
|
| 412 |
+
"false_alarm": 0.0,
|
| 413 |
+
"miss": 0.9333333333333333,
|
| 414 |
+
"flagged_share": 0.047619047619047616
|
| 415 |
+
},
|
| 416 |
+
"India": {
|
| 417 |
+
"n": 26,
|
| 418 |
+
"false_alarm": 0.0,
|
| 419 |
+
"miss": 0.6875,
|
| 420 |
+
"flagged_share": 0.19230769230769232
|
| 421 |
+
},
|
| 422 |
+
"England": {
|
| 423 |
+
"n": 22,
|
| 424 |
+
"false_alarm": 0.0,
|
| 425 |
+
"miss": 0.8333333333333334,
|
| 426 |
+
"flagged_share": 0.09090909090909091
|
| 427 |
+
},
|
| 428 |
+
"South": {
|
| 429 |
+
"n": 19,
|
| 430 |
+
"false_alarm": 0.0,
|
| 431 |
+
"miss": 0.8666666666666667,
|
| 432 |
+
"flagged_share": 0.10526315789473684
|
| 433 |
+
},
|
| 434 |
+
"El-Salvador": {
|
| 435 |
+
"n": 33,
|
| 436 |
+
"false_alarm": 0.0,
|
| 437 |
+
"miss": 0.5,
|
| 438 |
+
"flagged_share": 0.48484848484848486
|
| 439 |
+
}
|
| 440 |
+
}
|
| 441 |
+
}
|
| 442 |
+
}
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio==6.31.0
|
| 2 |
+
scikit-learn==1.9.1
|
| 3 |
+
fairlearn==0.15.0
|
| 4 |
+
pandas>=2.2
|
| 5 |
+
numpy>=1.26
|
| 6 |
+
scipy>=1.11
|
| 7 |
+
matplotlib>=3.8
|
sample_month.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
space_config.json
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"org": "Crosswind Workforce Partnership",
|
| 3 |
+
"system": "ReachFirst",
|
| 4 |
+
"version": "v1",
|
| 5 |
+
"short": "reachfirst",
|
| 6 |
+
"emoji": "\ud83d\udcec",
|
| 7 |
+
"model_file": "reachfirst_v1.pkl",
|
| 8 |
+
"recal_file": null,
|
| 9 |
+
"odds_factor": null,
|
| 10 |
+
"reasons_file": null,
|
| 11 |
+
"data_file": "crosswind_pilot_extract_remediated.csv",
|
| 12 |
+
"md5": "ca9ed6d4b9dfd59f3f586b09da05b31f",
|
| 13 |
+
"id_col": null,
|
| 14 |
+
"outcome": "income",
|
| 15 |
+
"positive": "<=50K",
|
| 16 |
+
"positive_label": "income at or below the line",
|
| 17 |
+
"negative_label": "income above the line",
|
| 18 |
+
"unit": "record",
|
| 19 |
+
"units": "records",
|
| 20 |
+
"action": "a place on the first mailer list for the measured first cycle",
|
| 21 |
+
"flagged_word": "ranked in",
|
| 22 |
+
"person": "household",
|
| 23 |
+
"share": 0.2,
|
| 24 |
+
"book_size": 15000,
|
| 25 |
+
"capacity": 3000,
|
| 26 |
+
"sample_rows": 4000,
|
| 27 |
+
"groups": {
|
| 28 |
+
"sex": {
|
| 29 |
+
"col": "sex"
|
| 30 |
+
},
|
| 31 |
+
"race": {
|
| 32 |
+
"col": "race"
|
| 33 |
+
},
|
| 34 |
+
"age band": {
|
| 35 |
+
"col": "age",
|
| 36 |
+
"bands": [
|
| 37 |
+
[
|
| 38 |
+
0,
|
| 39 |
+
24,
|
| 40 |
+
"under 25"
|
| 41 |
+
],
|
| 42 |
+
[
|
| 43 |
+
25,
|
| 44 |
+
34,
|
| 45 |
+
"25 to 34"
|
| 46 |
+
],
|
| 47 |
+
[
|
| 48 |
+
35,
|
| 49 |
+
44,
|
| 50 |
+
"35 to 44"
|
| 51 |
+
],
|
| 52 |
+
[
|
| 53 |
+
45,
|
| 54 |
+
54,
|
| 55 |
+
"45 to 54"
|
| 56 |
+
],
|
| 57 |
+
[
|
| 58 |
+
55,
|
| 59 |
+
64,
|
| 60 |
+
"55 to 64"
|
| 61 |
+
],
|
| 62 |
+
[
|
| 63 |
+
65,
|
| 64 |
+
200,
|
| 65 |
+
"65 and over"
|
| 66 |
+
]
|
| 67 |
+
]
|
| 68 |
+
},
|
| 69 |
+
"marital status": {
|
| 70 |
+
"col": "marital-status"
|
| 71 |
+
},
|
| 72 |
+
"country of origin": {
|
| 73 |
+
"col": "native_country_report",
|
| 74 |
+
"map": {
|
| 75 |
+
"?": "unrecorded"
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
},
|
| 79 |
+
"min_group": 500,
|
| 80 |
+
"group_check": "miss",
|
| 81 |
+
"group_tripwire": 0.2,
|
| 82 |
+
"watch_groups": [
|
| 83 |
+
"Married-civ-spouse",
|
| 84 |
+
"35 to 44",
|
| 85 |
+
"45 to 54",
|
| 86 |
+
"55 to 64"
|
| 87 |
+
],
|
| 88 |
+
"calibration": null,
|
| 89 |
+
"watch_fields": [
|
| 90 |
+
"marital-status",
|
| 91 |
+
"age",
|
| 92 |
+
"relationship_model",
|
| 93 |
+
"occupation"
|
| 94 |
+
],
|
| 95 |
+
"watch_fields_label": "marital status, age, household role, and occupation (Week 6 memo, rulings 1 and 4)",
|
| 96 |
+
"week6": {
|
| 97 |
+
"roc_auc": 0.905,
|
| 98 |
+
"flagged": 1952,
|
| 99 |
+
"caught": 1945,
|
| 100 |
+
"test_rows": 9758,
|
| 101 |
+
"test_positives": 7422
|
| 102 |
+
},
|
| 103 |
+
"lead": "Lauren Chen, AI Governance Lead",
|
| 104 |
+
"caio": "Denise Whitfield, Chief AI Officer",
|
| 105 |
+
"memo_ref": "Week 6 memo",
|
| 106 |
+
"monitoring_lines": [
|
| 107 |
+
"The share of at-or-below records left off the list, by age band and marital status, against the file's (ruling 1).",
|
| 108 |
+
"The measured first cycle: the list half against the current-practice half, married at-or-below households as the comparison group (ruling 3).",
|
| 109 |
+
"The sex-and-race recovery check, rerun at every retrain (ruling 4)."
|
| 110 |
+
],
|
| 111 |
+
"inputs": [
|
| 112 |
+
"age",
|
| 113 |
+
"workclass",
|
| 114 |
+
"education",
|
| 115 |
+
"marital-status",
|
| 116 |
+
"occupation",
|
| 117 |
+
"capital-gain",
|
| 118 |
+
"capital-loss",
|
| 119 |
+
"hours-per-week",
|
| 120 |
+
"relationship_model",
|
| 121 |
+
"capital_gain_topcoded"
|
| 122 |
+
],
|
| 123 |
+
"categorical": [
|
| 124 |
+
"workclass",
|
| 125 |
+
"education",
|
| 126 |
+
"marital-status",
|
| 127 |
+
"occupation",
|
| 128 |
+
"relationship_model",
|
| 129 |
+
"capital_gain_topcoded"
|
| 130 |
+
],
|
| 131 |
+
"numeric": [
|
| 132 |
+
"age",
|
| 133 |
+
"capital-gain",
|
| 134 |
+
"capital-loss",
|
| 135 |
+
"hours-per-week"
|
| 136 |
+
],
|
| 137 |
+
"kept": [
|
| 138 |
+
"age",
|
| 139 |
+
"capital-gain",
|
| 140 |
+
"capital-loss",
|
| 141 |
+
"hours-per-week",
|
| 142 |
+
"workclass_?",
|
| 143 |
+
"workclass_Federal-gov",
|
| 144 |
+
"workclass_Local-gov",
|
| 145 |
+
"workclass_Never-worked",
|
| 146 |
+
"workclass_Private",
|
| 147 |
+
"workclass_Self-emp-inc",
|
| 148 |
+
"workclass_Self-emp-not-inc",
|
| 149 |
+
"workclass_State-gov",
|
| 150 |
+
"workclass_Without-pay",
|
| 151 |
+
"education_10th",
|
| 152 |
+
"education_11th",
|
| 153 |
+
"education_12th",
|
| 154 |
+
"education_1st-4th",
|
| 155 |
+
"education_5th-6th",
|
| 156 |
+
"education_7th-8th",
|
| 157 |
+
"education_9th",
|
| 158 |
+
"education_Assoc-acdm",
|
| 159 |
+
"education_Assoc-voc",
|
| 160 |
+
"education_Bachelors",
|
| 161 |
+
"education_Doctorate",
|
| 162 |
+
"education_HS-grad",
|
| 163 |
+
"education_Masters",
|
| 164 |
+
"education_Preschool",
|
| 165 |
+
"education_Prof-school",
|
| 166 |
+
"education_Some-college",
|
| 167 |
+
"marital-status_Divorced",
|
| 168 |
+
"marital-status_Married-AF-spouse",
|
| 169 |
+
"marital-status_Married-civ-spouse",
|
| 170 |
+
"marital-status_Married-spouse-absent",
|
| 171 |
+
"marital-status_Never-married",
|
| 172 |
+
"marital-status_Separated",
|
| 173 |
+
"marital-status_Widowed",
|
| 174 |
+
"occupation_?",
|
| 175 |
+
"occupation_Adm-clerical",
|
| 176 |
+
"occupation_Armed-Forces",
|
| 177 |
+
"occupation_Craft-repair",
|
| 178 |
+
"occupation_Exec-managerial",
|
| 179 |
+
"occupation_Farming-fishing",
|
| 180 |
+
"occupation_Handlers-cleaners",
|
| 181 |
+
"occupation_Machine-op-inspct",
|
| 182 |
+
"occupation_Other-service",
|
| 183 |
+
"occupation_Priv-house-serv",
|
| 184 |
+
"occupation_Prof-specialty",
|
| 185 |
+
"occupation_Protective-serv",
|
| 186 |
+
"occupation_Sales",
|
| 187 |
+
"occupation_Tech-support",
|
| 188 |
+
"occupation_Transport-moving",
|
| 189 |
+
"relationship_model_Not-in-family",
|
| 190 |
+
"relationship_model_Other-relative",
|
| 191 |
+
"relationship_model_Own-child",
|
| 192 |
+
"relationship_model_Spouse",
|
| 193 |
+
"relationship_model_Unmarried",
|
| 194 |
+
"capital_gain_topcoded_0",
|
| 195 |
+
"capital_gain_topcoded_1"
|
| 196 |
+
],
|
| 197 |
+
"artifacts": {
|
| 198 |
+
"reachfirst_v1.pkl": {
|
| 199 |
+
"bytes": 4300,
|
| 200 |
+
"sha256": "120234d9f9a111028a2d605d2779a9d8e151ff8d6f85df4ec0497f651595b953"
|
| 201 |
+
}
|
| 202 |
+
},
|
| 203 |
+
"weights": [
|
| 204 |
+
[
|
| 205 |
+
"capital-gain",
|
| 206 |
+
-2.2417872489881026
|
| 207 |
+
],
|
| 208 |
+
[
|
| 209 |
+
"education_Doctorate",
|
| 210 |
+
-1.6366401222699463
|
| 211 |
+
],
|
| 212 |
+
[
|
| 213 |
+
"education_Prof-school",
|
| 214 |
+
-1.5886947281443564
|
| 215 |
+
],
|
| 216 |
+
[
|
| 217 |
+
"marital-status_Married-civ-spouse",
|
| 218 |
+
-1.3318312733718085
|
| 219 |
+
],
|
| 220 |
+
[
|
| 221 |
+
"education_Masters",
|
| 222 |
+
-1.226998809000688
|
| 223 |
+
],
|
| 224 |
+
[
|
| 225 |
+
"education_7th-8th",
|
| 226 |
+
1.1948745792414959
|
| 227 |
+
],
|
| 228 |
+
[
|
| 229 |
+
"education_9th",
|
| 230 |
+
1.0117126998478085
|
| 231 |
+
],
|
| 232 |
+
[
|
| 233 |
+
"education_Bachelors",
|
| 234 |
+
-0.9637259660175791
|
| 235 |
+
],
|
| 236 |
+
[
|
| 237 |
+
"education_5th-6th",
|
| 238 |
+
0.9516051530601645
|
| 239 |
+
],
|
| 240 |
+
[
|
| 241 |
+
"occupation_Farming-fishing",
|
| 242 |
+
0.8772839801447048
|
| 243 |
+
],
|
| 244 |
+
[
|
| 245 |
+
"occupation_Exec-managerial",
|
| 246 |
+
-0.8541365785148912
|
| 247 |
+
],
|
| 248 |
+
[
|
| 249 |
+
"occupation_Other-service",
|
| 250 |
+
0.781840452365622
|
| 251 |
+
],
|
| 252 |
+
[
|
| 253 |
+
"education_10th",
|
| 254 |
+
0.7805877804503274
|
| 255 |
+
],
|
| 256 |
+
[
|
| 257 |
+
"education_1st-4th",
|
| 258 |
+
0.7792674440291991
|
| 259 |
+
],
|
| 260 |
+
[
|
| 261 |
+
"education_11th",
|
| 262 |
+
0.7773197750619535
|
| 263 |
+
],
|
| 264 |
+
[
|
| 265 |
+
"marital-status_Never-married",
|
| 266 |
+
0.7576080167618042
|
| 267 |
+
],
|
| 268 |
+
[
|
| 269 |
+
"relationship_model_Spouse",
|
| 270 |
+
-0.7179494340103041
|
| 271 |
+
],
|
| 272 |
+
[
|
| 273 |
+
"occupation_Prof-specialty",
|
| 274 |
+
-0.6729447708086544
|
| 275 |
+
],
|
| 276 |
+
[
|
| 277 |
+
"occupation_Handlers-cleaners",
|
| 278 |
+
0.6242368981515822
|
| 279 |
+
],
|
| 280 |
+
[
|
| 281 |
+
"occupation_Tech-support",
|
| 282 |
+
-0.6189663047020056
|
| 283 |
+
],
|
| 284 |
+
[
|
| 285 |
+
"relationship_model_Own-child",
|
| 286 |
+
0.6110107663731764
|
| 287 |
+
],
|
| 288 |
+
[
|
| 289 |
+
"marital-status_Married-AF-spouse",
|
| 290 |
+
-0.6036891114878192
|
| 291 |
+
],
|
| 292 |
+
[
|
| 293 |
+
"workclass_Federal-gov",
|
| 294 |
+
-0.5782322983438535
|
| 295 |
+
],
|
| 296 |
+
[
|
| 297 |
+
"occupation_Priv-house-serv",
|
| 298 |
+
0.49771933984626343
|
| 299 |
+
],
|
| 300 |
+
[
|
| 301 |
+
"education_Preschool",
|
| 302 |
+
0.475000514022028
|
| 303 |
+
],
|
| 304 |
+
[
|
| 305 |
+
"occupation_Protective-serv",
|
| 306 |
+
-0.4486092827356464
|
| 307 |
+
],
|
| 308 |
+
[
|
| 309 |
+
"education_12th",
|
| 310 |
+
0.43801881119853986
|
| 311 |
+
],
|
| 312 |
+
[
|
| 313 |
+
"relationship_model_Other-relative",
|
| 314 |
+
0.4366084364105382
|
| 315 |
+
],
|
| 316 |
+
[
|
| 317 |
+
"marital-status_Widowed",
|
| 318 |
+
0.411442162972904
|
| 319 |
+
],
|
| 320 |
+
[
|
| 321 |
+
"workclass_Self-emp-not-inc",
|
| 322 |
+
0.40584831710662533
|
| 323 |
+
],
|
| 324 |
+
[
|
| 325 |
+
"education_Assoc-acdm",
|
| 326 |
+
-0.40047630749854773
|
| 327 |
+
],
|
| 328 |
+
[
|
| 329 |
+
"occupation_Sales",
|
| 330 |
+
-0.3691730492412525
|
| 331 |
+
],
|
| 332 |
+
[
|
| 333 |
+
"marital-status_Divorced",
|
| 334 |
+
0.35970764075843786
|
| 335 |
+
],
|
| 336 |
+
[
|
| 337 |
+
"education_Assoc-voc",
|
| 338 |
+
-0.35460703817389366
|
| 339 |
+
],
|
| 340 |
+
[
|
| 341 |
+
"relationship_model_Not-in-family",
|
| 342 |
+
-0.3468235390014372
|
| 343 |
+
],
|
| 344 |
+
[
|
| 345 |
+
"hours-per-week",
|
| 346 |
+
-0.3376055865841321
|
| 347 |
+
],
|
| 348 |
+
[
|
| 349 |
+
"workclass_Self-emp-inc",
|
| 350 |
+
-0.3133450413850334
|
| 351 |
+
],
|
| 352 |
+
[
|
| 353 |
+
"age",
|
| 354 |
+
-0.3079133863771645
|
| 355 |
+
],
|
| 356 |
+
[
|
| 357 |
+
"marital-status_Separated",
|
| 358 |
+
0.2891974899880865
|
| 359 |
+
],
|
| 360 |
+
[
|
| 361 |
+
"occupation_?",
|
| 362 |
+
0.27540443434911954
|
| 363 |
+
],
|
| 364 |
+
[
|
| 365 |
+
"workclass_?",
|
| 366 |
+
0.27236425493903366
|
| 367 |
+
],
|
| 368 |
+
[
|
| 369 |
+
"occupation_Machine-op-inspct",
|
| 370 |
+
0.26824061777393843
|
| 371 |
+
],
|
| 372 |
+
[
|
| 373 |
+
"education_Some-college",
|
| 374 |
+
-0.25756126820826947
|
| 375 |
+
],
|
| 376 |
+
[
|
| 377 |
+
"capital-loss",
|
| 378 |
+
-0.24456817976716777
|
| 379 |
+
],
|
| 380 |
+
[
|
| 381 |
+
"workclass_State-gov",
|
| 382 |
+
0.22032596360113468
|
| 383 |
+
],
|
| 384 |
+
[
|
| 385 |
+
"marital-status_Married-spouse-absent",
|
| 386 |
+
0.19106420631129978
|
| 387 |
+
],
|
| 388 |
+
[
|
| 389 |
+
"occupation_Craft-repair",
|
| 390 |
+
-0.12003826217984946
|
| 391 |
+
],
|
| 392 |
+
[
|
| 393 |
+
"workclass_Without-pay",
|
| 394 |
+
0.10573384913493386
|
| 395 |
+
],
|
| 396 |
+
[
|
| 397 |
+
"occupation_Armed-Forces",
|
| 398 |
+
-0.10136306490673276
|
| 399 |
+
],
|
| 400 |
+
[
|
| 401 |
+
"education_HS-grad",
|
| 402 |
+
0.09381661433467584
|
| 403 |
+
],
|
| 404 |
+
[
|
| 405 |
+
"relationship_model_Unmarried",
|
| 406 |
+
0.09065290216094356
|
| 407 |
+
],
|
| 408 |
+
[
|
| 409 |
+
"workclass_Private",
|
| 410 |
+
-0.08277029477532862
|
| 411 |
+
],
|
| 412 |
+
[
|
| 413 |
+
"occupation_Adm-clerical",
|
| 414 |
+
-0.0779884657765726
|
| 415 |
+
],
|
| 416 |
+
[
|
| 417 |
+
"capital_gain_topcoded_0",
|
| 418 |
+
0.06912153062371537
|
| 419 |
+
],
|
| 420 |
+
[
|
| 421 |
+
"workclass_Local-gov",
|
| 422 |
+
0.04053420224531096
|
| 423 |
+
],
|
| 424 |
+
[
|
| 425 |
+
"occupation_Transport-moving",
|
| 426 |
+
0.011993188167275508
|
| 427 |
+
],
|
| 428 |
+
[
|
| 429 |
+
"capital_gain_topcoded_1",
|
| 430 |
+
0.004377601309201683
|
| 431 |
+
],
|
| 432 |
+
[
|
| 433 |
+
"workclass_Never-worked",
|
| 434 |
+
0.003040179410085815
|
| 435 |
+
]
|
| 436 |
+
],
|
| 437 |
+
"intercept": 2.818318687777577,
|
| 438 |
+
"data_url": "https://huggingface.co/datasets/drdavidprivacy/practicum-case-packs/resolve/main/crosswind_pilot_extract_remediated.csv",
|
| 439 |
+
"dataset_repo": "https://huggingface.co/datasets/drdavidprivacy/practicum-case-packs",
|
| 440 |
+
"versions": {
|
| 441 |
+
"sklearn": "1.9.1",
|
| 442 |
+
"fairlearn": "0.15.0",
|
| 443 |
+
"pandas": "3.0.5",
|
| 444 |
+
"numpy": "2.5.3"
|
| 445 |
+
},
|
| 446 |
+
"docs": [
|
| 447 |
+
[
|
| 448 |
+
"01_Use-Case-Assessment.pdf",
|
| 449 |
+
"Use Case Assessment (Week 1)"
|
| 450 |
+
],
|
| 451 |
+
[
|
| 452 |
+
"02_EDA-Observation-Log.pdf",
|
| 453 |
+
"EDA Observation Log (Week 2)"
|
| 454 |
+
],
|
| 455 |
+
[
|
| 456 |
+
"03_Dataset-Datasheet.pdf",
|
| 457 |
+
"Dataset Datasheet (Week 3)"
|
| 458 |
+
],
|
| 459 |
+
[
|
| 460 |
+
"04_Model-Selection-Rationale.pdf",
|
| 461 |
+
"Model Selection Rationale (Week 4)"
|
| 462 |
+
],
|
| 463 |
+
[
|
| 464 |
+
"05_Model-Card.pdf",
|
| 465 |
+
"Model Card (Week 6)"
|
| 466 |
+
],
|
| 467 |
+
[
|
| 468 |
+
"06_Go-No-Go-Decision-Record.pdf",
|
| 469 |
+
"Go/No-Go Decision Record (Week 7)"
|
| 470 |
+
]
|
| 471 |
+
]
|
| 472 |
+
}
|