Download code/mr/implications.py from odurugol/vlm3d-beyond-normals: direct link, hf CLI and curl.
- Browser
- Download file 3.13 kB
-
https://huggingface.co/odurugol/vlm3d-beyond-normals/resolve/main/code/mr/implications.py
- Command line
-
hf download hf://odurugol/vlm3d-beyond-normals/code/mr/implications.py
-
curl -L -o implications.py https://huggingface.co/odurugol/vlm3d-beyond-normals/resolve/main/code/mr/implications.py
3.13 kB
| """Labels the challenge's Gemma extractor reads back in addition to the one a bullet names. | |
| We ran 32 single-diagnosis reports through the extractor (google/gemma-4-31B-it, | |
| temperature 0) and kept the extra labels that came back. Each link was checked | |
| again inside a seven-bullet report; the one that did not hold there was dropped. | |
| A report is therefore read as the closure of its bullets under these links. | |
| When the number of bullets is limited, bullets that imply other predicted labels | |
| are preferred. | |
| """ | |
| import numpy as np | |
| IMPLIES = { | |
| "chronic_ischemic_stroke": ["encephalomalacia_gliosis"], | |
| # lacunar_stroke -> chronic_ischemic_stroke + small_vessel_ischemic_disease held in a | |
| # single-diagnosis report but only 2 times in 6 inside a seven-bullet report, so it is not used. | |
| "intraparenchymal_hemorrhage": ["intracranial_hemorrhage"], | |
| "glioma": ["brain_tumor"], | |
| "brain_metastasis": ["brain_tumor"], | |
| "meningioma": ["brain_tumor"], | |
| "intraventricular_tumor": ["brain_tumor"], | |
| "pituitary_tumor": ["brain_tumor"], | |
| "hydrocephalus_ex_vacuo": ["cerebral_atrophy", "ventriculomegaly"], | |
| "craniotomy_craniectomy": ["postsurgical_changes"], | |
| "tumor_resection_cavity": ["postsurgical_changes"], | |
| } | |
| def closure_matrix(names): | |
| """C[p, c] = 1 if asserting p makes the extractor also report c (transitively).""" | |
| idx = {n: i for i, n in enumerate(names)} | |
| L = len(names) | |
| C = np.eye(L, dtype=bool) | |
| for p, cs in IMPLIES.items(): | |
| if p not in idx: | |
| continue | |
| for c in cs: | |
| if c in idx: | |
| C[idx[p], idx[c]] = True | |
| for _ in range(L): # transitive closure (Floyd-Warshall style) | |
| new = C | (C @ C) | |
| if (new == C).all(): | |
| break | |
| C = new | |
| return C | |
| def apply_closure(asserted, C): | |
| """asserted: bool[n, L] of what we write; returns what the extractor reads.""" | |
| return (asserted.astype(np.uint8) @ C.astype(np.uint8)) > 0 | |
| def select_with_implications(P, thr, cap, C): | |
| """Greedy choice of at most `cap` bullets, valued over the implication closure. | |
| A label's value is its margin over its threshold, `P/thr - 1`. A bullet is worth | |
| the total value of the labels it adds to the closure, so a parent whose children | |
| are also predicted is chosen first, and a parent that would add unpredicted | |
| children is penalised by their negative margin. | |
| """ | |
| n, L = P.shape | |
| val = P / np.maximum(thr, 1e-9) - 1.0 | |
| Cf = C.astype(np.float64) | |
| if not cap: | |
| return apply_closure(val > 0, C) | |
| have = np.zeros((n, L), dtype=bool) | |
| picked = np.zeros((n, L), dtype=bool) | |
| rows = np.arange(n) | |
| for _ in range(cap): | |
| gain = (val * ~have) @ Cf.T # gain[i, d] = value d adds for study i | |
| gain[picked] = -np.inf | |
| d = gain.argmax(1) | |
| g = gain[rows, d] | |
| take = g > 1e-12 | |
| picked[rows[take], d[take]] = True | |
| have[take] |= C[d[take]] | |
| if not take.any(): | |
| break | |
| return picked | |