Design decisions and fidelity trade-offs¶
Every benchmark that consolidates published methods makes choices the original papers never had to make. This page records those choices for PGVL-Gym: what was decided, what the alternative was, and — where a decision costs fidelity — what a reader must not conclude from the resulting number.
It is deliberately written as a ledger rather than a rationale. A reader comparing our numbers to a paper's needs to know exactly where the two diverge.
1. Provenance is recorded, never inferred¶
The framework's central commitment: a number carries the conditions that
produced it. Provenance fields travel from the protocol into the
generated config, the run matrix, and aggregate_results.csv.
| Field | Values | Answers |
|---|---|---|
encoder_provenance |
native, adapted |
Did the method's own code support this encoder, or does a trainable projection bridge it? |
prompt_provenance |
upstream, generated, classname_template, or a role-qualified mixed condition such as upstream_instance_with_random_classname_bag |
Where did the embedded text for every prompt role come from? |
prompt_source |
per-method, e.g. cod_chain_runtime_clip_rn50 |
Which asset and encoding path? |
implementation_provenance |
vendored, mixed, reimplemented, or a precise partial variant |
Which method implementation actually ran? |
upstream_fidelity |
upstream, partial, local_baseline |
May this number be described as an upstream reproduction? |
All provenance fields are derived from the declared contract and the files on disk, not set by hand, so they cannot drift from what the run actually does.
FOCUS prompt origins and native schema¶
FOCUS reads a headerless one-column CSV positionally: all low-resolution class prompts, followed by all high-resolution prompts. The earlier PGVL three-column table was a local conversion, not the released schema. The shared loader, runtime, generator validator, and doctor now enforce the native format, explicit file-class binding, provenance, file hash, and ordered class-bound bank hash.
| Local bank | Origin | Upstream status |
|---|---|---|
| CAMELYON16 | upstream copy | Byte-exact released CAMELYON bank |
| TCGA-NSCLC | upstream copy | Byte-exact released TCGA-Lung bank |
| UBC-OCEAN | upstream copy | Byte-exact released bank; file order CC, HGSC, LGSC, EC, MC is explicitly reordered to benchmark order |
| TCGA-BRCA | generated | FOCUS publishes no BRCA prompt CSV |
| TCGA-RCC | generated | FOCUS publishes no RCC prompt CSV |
The three copies are pinned to commit
66c4015d5ba09657f4c8183bc06947faecd5b01f. The released UBC clear-cell
high-resolution row contains unescaped quotes around hobnail; upstream pandas
therefore preserves a trailing quote in the parsed text. PGVL preserves the
file and parse exactly instead of silently creating a corrected prompt
condition. BRCA/RCC extensions use the same native positional format but remain
reported as generated.
MSCPT prompt origins¶
MSCPT prompt provenance follows the embedded text, not whether the protocol
selected its path through a legacy field or an explicit prompts: mapping:
| Benchmark bank | Origin | Fidelity note |
|---|---|---|
TCGA-NSCLC Lung.json |
upstream copy | Preserved verbatim, including the released LUSC-content issue described below |
TCGA-RCC RCC.json |
upstream copy | Task-matched released bank, 10 small_mag and 30 big_mag prompts per class |
UBC-OCEAN UBC-OCEAN.json |
upstream copy | Task-matched released bank, 10 small_mag and 30 big_mag prompts per class |
| TCGA-BRCA IDC/ILC | generated | MSCPT's released BRCA.json is a different High/Low recurrence/grade task; the local bank has 10 prompts at each scale |
| CAMELYON16 | generated | MSCPT releases no CAMELYON16 bank; this one is compiled from the local canonical prompt profile |
MSCPT also releases a separate *_select_pic.json ensemble for offline
low-magnification patch selection. The Lung, RCC, and UBC-OCEAN selector files
are byte-exact upstream copies, contain 50 independently worded prompt sets,
and are not interchangeable with the small_mag descriptions above. The
feature-only runtime encodes those sets with the paired text tower, normalizes
and averages templates within each set, then normalizes and averages across
sets exactly as intended by select_5X_pic.py. The released script indexes 100
sets even though the published JSON assets contain 50; PGVL-Gym consumes the
complete available 50-set bank instead of reproducing that out-of-range defect.
BRCA IDC/ILC and CAMELYON16 have no task-matched selector bank, so their local
extensions retain the generated multiscale-description fallback and do not
claim upstream selector fidelity.
The upstream Lung.json places nine adenocarcinoma-associated descriptions in
the LUSC block: small_mag indices 0 and 2, and big_mag indices 0, 1, 3,
8, 9, 28, and 29 (zero-based). They mention glandular/acinar architecture,
mucin, lepidic growth, signet-ring cells, bronchioloalveolar carcinoma, or
micropapillary morphology. MSCPT embeds these descriptions into the LUSC text
representation, so this can affect NSCLC results. The upstream file remains
unchanged: silently correcting it would create a new prompt condition while
still appearing to be an upstream reproduction. The exact indices and policy
are machine-readable in text_prompts/PROVENANCE.json.
Generated configs therefore report upstream for NSCLC, RCC, and UBC-OCEAN,
and generated for the task-extended BRCA and CAMELYON16 banks. The separate
upstream_fidelity: partial implementation label still applies. The
feature-only integration now preserves the released branch roles: it sends the
complete 20x bag to the full-bag graph and uses the dedicated selector ensemble
for class-major, per-class ranking of the precomputed low-magnification bag
before the sparse graph. The selection count is 30 patches per class for TCGA
and 10 per class for UBC-OCEAN, as in the released task scripts; a short bag is
retained with the same class-major duplication behavior. What remains bypassed
is the deep visual-prompt image encoder applied upstream to selected RGB
patches, because PGVL-Gym starts at final frozen feature files. This is a
disclosed feature-only adaptation, not an upstream raw-tile reproduction.
ViLa-MIL prompt format and origins¶
ViLa-MIL's released prompt loader reads a headerless one-column CSV and splits
exactly 2 * n_classes rows into all low-resolution prompts followed by all
high-resolution prompts. The earlier PGVL integration incorrectly shared its
local three-column FOCUS conversion, so header and class-name cells became
prompt text and did not reproduce either upstream method. PGVL now keeps
distinct method-owned native assets for ViLa-MIL and FOCUS, even though their
released loaders use the same positional layout, and records each asset's
file-class binding explicitly.
The TCGA-Lung and TCGA-RCC banks are byte-exact copies from ViLa-MIL commit
68a11cf0d5cf092dd980f0da1cb38ccac8747a82. ViLa-MIL publishes no BRCA,
UBC-OCEAN, or CAMELYON16 prompt bank, so those files are generated task
extensions and are never reported as upstream. The upstream RCC text spells the
third class CRCC at both scales. That wording remains unchanged for fidelity;
the provenance record and loader bind its third positional slot to the
classifier's CHRCC label. File hashes protect exact copies, while an ordered
prompt-bank hash protects the final classifier binding after any declared
reordering.
The released PromptLearner has an executable indexing defect. It tokenizes
the description alone, inserts 16 learned context embeddings before the
description, but lets TextEncoder pool at the description's original
end-of-text index. After insertion that position lies inside the learned
context rather than at the shifted end-of-text token. PGVL-Gym uses the
standard CoOp layout: it tokenizes 16 placeholder tokens plus the description,
replaces only those placeholder embeddings with the trainable context, and
pools at the resulting real end-of-text index. This corrective deviation is
pinned as vila_prompt_layout: coop_16_context_eot_aligned_v1 and reported as
partial implementation fidelity.
ViLa-MIL's paper explicitly defines the low-scale slide at 5x and high-scale
slide at 10x. The former 5x/20x registration was a local configuration error.
All current ViLa-MIL configs require vila_scale_recipe: upstream_5x_10x; the
doctor rejects a different resolution binding instead of silently changing the
method condition.
MAPLE prompt origins and ordering¶
MAPLE releases complete two-scale attribute graphs for TCGA-Lung, TCGA-RCC,
and TCGA-BRCA only. The checked-in LUNG_attributes.json,
RCC_attributes.json, and BRCA_attributes.json files are byte-exact copies
from commit c38d5d5d55deba3a44e9384c0efeee98e1aec36b, with file hashes recorded in
the provenance manifest. MAPLE publishes no UBC-OCEAN or CAMELYON16 bank:
those are explicitly generated task extensions. The standalone UBC example
now has a real generated asset instead of pointing to a nonexistent file.
Class-key order is semantic, not cosmetic. MAPLE iterates global_info and
every entity's attributes mapping to build its class logits. The earlier
doctor compared only key sets, so a JSON reordering could silently permute
predictions relative to numeric labels. The shared loader, doctor, benchmark
validator, and runtime now require every mapping to match classifier order
exactly and verify registered upstream file hashes.
The registered NSCLC PLIP stores expose the 768-wide pooled vision output,
whereas released MAPLE consumes already projected 512-wide patch features. The
runtime therefore applies the pinned PLIP checkpoint's own frozen
visual_projection before any MAPLE similarity or graph operation. Configs
bind the source as hf:vinid/plip#vision-preprojection, the prompt tower as
hf:vinid/plip, and the bridge as native_visual_projection; arbitrary or
learned cross-encoder projections remain disallowed.
The paper and released executable disagree on training details. Section 5 of
the NeurIPS paper specifies 5x/10x inputs, AdamW at 1e-4, and at most 80
epochs, while released run.sh/main.py use Adam at 2e-4 for 200 epochs.
PGVL-Gym therefore keeps maple_paper_5x10x separate from the release-code
variants. Its config records the local 224px cached-patch and patient-grouped
split deviations rather than presenting the condition as an exact replication.
The released runtime also has an attribute-alignment defect. PromptLearner
appends prompts entity-major—every class for entity 0, then every class for
entity 1—but obtain_entities_attr reshapes that sequence as class-major.
Most entity/class scores therefore consume another pair's description. PGVL
restores the emitted entity-major shape directly. This is a disclosed upstream
bug fix: the prompt files remain unchanged, but corrected runs are not claimed
to reproduce that accidental permutation.
TOP prompt origins¶
TOP has two distinct prompt roles. Its instance learner uses 26 task-agnostic tissue prototypes; its bag learner uses task-specific class initializers. The standard assets now follow the active literals in the authors' released code:
| Cohort/asset | Instance prototypes | Bag initializer | Reported condition |
|---|---|---|---|
| TCGA-NSCLC | 26 ordered entries copied from knowledge_from_chatGPT |
Exact two bagPrompt_ctx_init strings from train_TCGAFeat_MIL_CLIP.py |
upstream |
| CAMELYON16 | Same released 26-entry bank | Exact active normal/tumor initializers from train_CAMELYONFeat_MIL_CLIP.py |
upstream when TOP is enabled |
| TCGA-BRCA | Same released 26-entry bank | No upstream BRCA initializer; random learned context plus IDC/ILC classnames | upstream_instance_with_random_classname_bag |
| TCGA-RCC / UBC-OCEAN examples | Same released 26-entry bank | No upstream task initializer; random learned context plus task classnames | upstream_instance_with_random_classname_bag |
The longer NSCLC class descriptions in supplementary Figure 4 are also copied
and retained as top/tcga_nsclc_bag_prompts.json, but are marked
alternative_unwired. They are a legitimate ablation condition, not the
released training-script condition. The adapter accepts either complete
code-faithful ctx_init literals or base prompts, checks class-index order and
ten-slot placement, and no longer inserts a second period between an instance
description and its learnable slots. It also preserves the release's tiny
recipe difference: TCGA concatenates the first instance slot directly, while
CAMELYON inserts a space. The instance asset records the pinned upstream commit
and a digest over all 26 ordered rendered prompts. Every TOP asset is also
bound to a manifest file hash and a semantic bank hash; the bag hash includes
mode, classifier-label order, initializer text, and the class suffixes actually
passed to PromptLearner. Checked-in configs repeat those trusted bindings.
One shared loader enforces them in runtime, doctor, and benchmark generation
and derives the reportable condition from the selected roles. Consequently,
selecting the supplementary bank produces upstream_supplementary_condition,
while omitting a published bag bank produces
upstream_instance_with_random_classname_bag; neither can be mislabeled as the
standard upstream condition.
The upstream trainer passes all_ctx_trainable=False to both prompt learners.
PGVL-Gym therefore freezes every initialized description prefix and optimizes
only its ten * embeddings. An earlier adapter omission inherited the
constructor default True and inflated the trainable set to 2,170,912
parameters. Runtime, compiler, and doctor now enforce the released false
setting.
TOP's paper defines the image/text comparisons as cosine similarities. Its released runtime normalizes text embeddings but relies on the private precomputed image-feature arrays to carry the corresponding image-side normalization. PGVL-Gym normalizes each external CLIP-RN50 patch row at model entry, making that mathematical contract explicit for Trident HDF5 bags. This prevents feature norms from saturating TOP's temperature-scaled routing and classification softmaxes. Optimizer liveness is checked across the complete first epoch because an isolated saturated slide can have a finite gradient whose FP32 SGD update rounds to zero; a wholly inert epoch or any non-finite gradient/update remains fatal. Results from the failed zero-update jobs are invalid and must not be reported.
SLIP prompt origins¶
SLIP assigns three separate roles to its released prompt bank: format
templates, slide-class prompts, and tissue-routing prompts. A tissue is itself
a text ensemble. The authors encode its short name and its description as two
independent prompts, normalize both embeddings, average them, and normalize
again. Consequently, joining the pair into one Name: description sentence
does not reproduce the released routing vector even though it preserves every
word.
| Benchmark bank | Origin | Selected condition |
|---|---|---|
| TCGA-NSCLC | upstream copy | Exact TCGA template ({}), two nested slide-class groups, and all 17 ordered two-text tissue groups |
| CAMELYON16 | generated | Local tissue extension, expanded to the native two-text runtime shape |
| TCGA-BRCA | generated | Local tissue extension, expanded to the native two-text runtime shape |
| TCGA-RCC | generated | Local tissue extension, expanded to the native two-text runtime shape |
| UBC-OCEAN | generated | Local tissue extension, expanded to the native two-text runtime shape |
The complete released DHMC and PatchGastricADC22 banks are also copied for
their original datasets, including the gastric-specific template. The old
*_tissues.json conversions of those banks and TCGA are retained only as
derived, unwired audit artifacts. Generated configs and the runtime load a
complete bank, while the doctor verifies template arity, slide-class order,
the nested tissue structure, and the digest of upstream banks. The importer
preserves the complete source structure, so refreshing from upstream cannot
silently recreate the flattening bug.
The released repository exposes TCGA in its CLI and includes this lung
prompt bank, but imports a datasets/tcga.py file that is not present. Its
paper reports CLIP ViT-B/16 results only for PatchGastric and DHMC. Therefore
the registered TCGA-NSCLC rows are explicitly local task/protocol extensions,
not paper reproductions. The paper states SGD at 2e-4, while the released
CLI defaults to 2e-3; PGVL-Gym uses the paper value and records this choice.
The separately named slip_plip condition replaces RN50 with paired PLIP: its
768-wide cached vision-preprojection vectors pass through the same frozen
PLIP checkpoint's native visual projection before any tissue/text comparison.
The upstream PLIP prompt encoder also hardcodes EOT ID 46810, whereas the
released vinid/plip tokenizer snapshot used here assigns EOT/padding ID
49407. The hard-coded value is absent and would select token position zero;
PGVL-Gym therefore binds EOT and padding to the loaded tokenizer and records
this as an upstream-code repair.
Why native and adapted must not share a results table¶
pathpt_keep and muse_musk can report identical accuracy and mean different
things. PathPT ships PathPT_model_KEEP.py, so its number measures KEEP under
the published code. MUSE with MUSK features keeps CONCH as the text tower and
learns a projection between them, so its number measures MUSE plus that
projection — the encoder cannot be credited alone.
The separately named muse_paired_* rows answer a different question again:
the cached patch producer and frozen text tower come from one exact checkpoint,
but MUSE still retains its trainable visual adapter and replaces the native
CONCH token learner with the disclosed final-feature context fallback. These
rows are explicit architecture extensions; they do not retroactively change
the cross-space muse_keep or muse_musk result identities.
The released KEEP remote module replaces timm's LayerScale with a compatible
name but an older constructor. Current supported timm passes device and
dtype while creating ViT blocks, so PGVL-Gym locally extends that constructor
with those factory arguments without changing its parameterization or forward
rule. This is a runtime compatibility repair, not a model alteration.
The generated run matrix records this distinction per row. Counts are derived from the current protocols rather than repeated here because adding an explicit encoder condition changes them.
Trade-off accepted¶
encoder_provenance has two values, not four. Prompt provenance is a separate
axis already carried by prompt_source and prompt_provenance; folding it in
would duplicate state and let the two drift.
2. Implementation provenance¶
The adapter registry is the source of truth for implementation fidelity. The compiler writes its values into every config, matrix row, fold result, and aggregate grouping; the doctor rejects contradictory declarations.
| Method | Upstream LOC used | Local model LOC | Status |
|---|---|---|---|
cod_mil |
vendored model and objective | scale/slice/scheduler fidelity guards | partial: preserves the released encoder-specific prompt scales and inert scheduler, while correcting the released final-background-row omission |
top |
1,195–6,301 | 0 | fully vendored |
maple |
vendored model and objective | native PLIP visual-boundary restoration plus attribute-order correction | partial: restores cached preprojection features with PLIP's own frozen head and fixes the released entity-major/class-major reshape defect |
mscpt |
vendored model | adapter plus feature-only selection bridge | partial: the exact selector-prompt ensemble, branch roles, and classwise top-k are restored, but deep visual prompting of raw RGB patches is bypassed |
pathpt |
vendored model, loss, and prompt banks | lifecycle adapter | upstream in upstream_patch_ssl subtype mode; legacy slide-CE and CAMELYON adaptation are partial |
focus |
vendored model | lifecycle adapter | upstream architecture with method-specific asset provenance |
vila_mil |
vendored model | lifecycle adapter plus prompt-index correction | partial: released EOT indexing defect corrected and paper 5x/10x scales enforced |
slip |
4,411 | 114 | mixed, mostly vendored |
wsi_five |
~1,000 used of 4,071 | 175 | rebuilt from vendored components; FiVE.py orchestrator is unusable |
muse |
prompt learner, text path, MoE/SFSE/SMMO behavior reconstructed from pinned source and Algorithm 1 | adapter plus dependency-light reconstruction | partial: released 16-token CONCH prompting and paper full-queue semantic-view training restored; unified orchestration retained |
convlm |
0 | 124 | reimplemented (self-declared) |
sldpc |
0 | 246 | reimplemented (CPI/DHNO/SICL written here) |
dyko |
0 | clean equation-level implementation | partial: released TITAN prompts/concepts retained; deterministic PyTorch K-means replaces FAISS, paper retrieval corrections are applied, and cached 512px tiles differ from paper 448px tiles |
mgpath |
0 | clean equation-level implementation | partial: final-paper 5x/10x, 9e-6, 200-epoch recipe is authoritative over the conflicting release command; the missing PLIP-only ImageMLP, index-zero graph neighbour, and current Transformers signature are corrected; cached tiles remain 224px without upstream augmentation and the primary PLIP-G path is not claimed |
hipss |
0 | clean equation-level implementation | partial: complete GPT-5.6 replacement prompts and coordinate-grouped cached geometry replace unavailable upstream assets; layerwise SSF matches the paper parameter budget |
SLDPC prompt provenance is intentionally split at the consumer boundary. At
upstream commit 3c9580a1f3602a140d7e6bcc75ad93d7554e4e85, the two-stage
TitanPromptLearner receives dataset class_names codes. The YAML synonym
banks and 23-template ensemble enter only the independently evaluated TITAN
zero-shot baseline. Four local YAMLs (NSCLC, RCC, TCGA-OT, and UBC-OCEAN) are
byte-exact upstream copies; BRCA and CAMELYON16 are generated task extensions.
The complete file hashes, token origins, and pinned source links are recorded
in text_prompts/PROVENANCE.json. The unified adapter currently retains the
zero-shot assets only as audited, explicitly unwired references and does not
report a zero-shot metric.
SLDPC's runtime interface now separates that native TITAN condition from
architecture extensions. An exact TITAN slide vector can still use TITAN's
frozen native slide projection. A different registered promptable text tower
must instead declare slide_projection: linear or mlp; that adapter is
trained only on the fold's training slides and the compiler derives an
encoder_extension record from the independent slide_encoder and
prompt_encoder identities. OpenAI CLIP-RN50 and ViT-B/16 are the first
built-in alternate towers with a complete differentiable embedded-prompt
wrapper. This makes the swap executable, but it does not make the resulting
learned alignment an upstream SLDPC condition.
wsi_five was the most misleading case and has since been rebuilt: the adapter
now drives the vendored PatchFusionTransformer, MedCLIPTextModel and
LoraWrap, restores the released answer-candidate objective, and reserves the
released diagnostic descriptions for evaluation. What remains unused is
FiVE.py (500 lines) and
_datasets/pipeline.py (1,950 lines) — and FiVE.py is not merely unused but
unrunnable, failing both import and construction (see §7). The remaining
limitations are the rebuilt orchestration and feature provenance, not a
missing prompt pipeline.
Partial adapters emit doctor warnings. A publication-oriented protocol can set
require_upstream_fidelity: true to turn those warnings into a hard gate.
3. Vision-language only, by construction¶
Every registered encoder is a dual-tower vision-language model. Vision-only pathology foundation models — UNI, GigaPath, Virchow, Phikon, CTransPath, H-optimus, ResNet50 — are deliberately absent, even though features for several are extracted and available.
A method that learns or injects text prompts has no text tower to attach to. Including them would produce cells that cannot run, not cells that are blocked for an interesting reason.
Of 130 method × encoder combinations: 48 native, 40 adaptable, 42 blocked. See Compatibility analysis for the cause of every blocked cell.
4. Skip visibly, never silently degrade¶
A benchmark matrix always contains configurations whose assets do not exist yet. Three mechanisms keep those from producing numbers:
- Config generation records unbuildable experiments in
skipped_configs.csvwith the specific missing asset, and does not emit a config. common/preflight.pychecks one resolved config against the filesystem before any model is built. Failure writesskipped.jsonand exits 3 — distinct from 0 (completed) and 78 (environment).train.pyfails on the first sample error by default (max_batch_failure_rate: 0). A run may explicitly opt into a non-zero sample-failure ceiling, but past that fraction it fails rather than reporting a number computed on a larger accidental subset. Counts land inmetrics.jsonas sample counts undersample_failures, with the exact identities underfailed_slide_ids.
Trade-off accepted¶
Any non-zero ceiling changes the evaluated population and is therefore an explicit protocol decision, not a hidden resilience default. Comparable benchmark protocols keep the fail-fast value.
Stale artifacts are pruned¶
Generated configs the protocol no longer produces are deleted after each generation pass. A config left behind still names a results directory and still looks valid to anything walking the config tree, so the protocol is treated as the sole source of truth.
5. Encoder loading: pinned provenance over convenience¶
feature_space_id identifies the exact producer of a feature tensor, and
equal widths never establish compatibility. No adapter is inserted implicitly.
PLIP below torch 2.6¶
transformers refuses torch.load on a .bin checkpoint under torch 2.6
(CVE-2025-32434), and vinid/plip's default revision publishes only
pytorch_model.bin.
Rejected: pinning the repository's safetensors-only revision. That revision
carries no config.json and no tokenizer files, so the load fails on the
missing config instead — and offline compute nodes cannot fetch them.
Chosen: assemble one complete directory (config + tokenizer from the
default revision, model.safetensors from the other) and point PLIP_CKPT at
it. Verified first that all 400 tensors are bit-identical between the two
revisions. transformers prefers safetensors and that path never calls
torch.load. scripts/pgvl_job.sh exports it, guarded on the file existing so
an unprepared site degrades to the HF cache with a warning.
6. Per-cohort benchmark directories¶
Each cohort owns benchmarks/<cohort>/ holding its protocol.yaml and
everything generated from it. Cohorts are independent so one whose data is not
ready cannot hold back the others.
Trade-off: shared feature sources are declared repeatedly across protocols. Accepted, because a single protocol would couple every cohort's readiness.
7. Method-specific fidelity notes¶
CoD-MIL — cross-magnification maps are reconstructed¶
The released code loads map_10x_20x_files/<slide>.pt but the repository ships
neither the maps nor a generator for them. create_patches_fp.py is stock
CLAM at a single magnification; datasets/ is stock CLAM; scripts/ holds only
split creation.
scripts/generate_cross_magnification_maps.py reconstructs them from patch
coordinates.
| Decision | Basis |
|---|---|
| 10x → 20x | Confirmed — Table I reports 10x and 20x patches for all three of the paper's datasets, and matches the hardcoded map_10x_20x_files |
| Centre containment | Inferred. The paper introduces an alignment matrix but does not state the geometric rule. Robust to tissue filtering in a way index arithmetic is not |
| Per-slide patch size | patch_size_level0 is read from each slide's H5 attributes, not a global constant |
| Built from feature files, not the patch store | The map's indices must address the bag the model loads; building from the feature files' own coords makes that true by construction |
The per-slide sizing is not a refinement — BRCA spans three scanner base magnifications:
| base | 10x | 20x | slides |
|---|---|---|---|
| 40x | 896 | 448 | 913 |
| 30x | 1344 | 672 | 8 |
| 20x | 448 | 224 | 39 |
A single global size would have bound roughly four times too many high-power patches per row for 47 of 960 slides — silently, with no error.
Validation: all 960 maps are (N_low, 4), zero empty rows, mean 3.90–3.94
matches per low patch, each high patch in exactly one parent. The 4-way nesting
also reconciles the code's topk(A, 16) with the paper's sampling sweep:
16 low-power regions × 4 children ≈ 64 high-power instances, landing on the
K≈64 the paper's Fig. 6 favours. The code's 16 and the paper's K are different
quantities.
Not comparable to the paper's numbers
Upstream create_patches_fp.py defaults to 256 px patches at stride 256;
this benchmark's store holds 224 px patches. The grids differ, so a 10x tile
covers a different tissue area and instance counts do not match Table I. The
method is reproduced; the numbers are not directly comparable.
CoD-MIL — prompt banks¶
The published bank is C low-power class prompts + C high-power class prompts
+ a normal-tissue corpus (21 rows for kidney: 6 organ structures + 15
organ-independent phenotypes). The auxiliary contrastive branch masks the most
discriminative low-power instances and contrasts them against normal tissue —
so the corpus is the objective, not padding.
The 15 organ-independent rows are reused verbatim across cohorts, including
upstream's "tpithelial" typo, because correcting it would change the embedding
and break correspondence with the released bank.
Upstream publishes a normal-tissue bank for kidney only. BRCA's six normal
breast structures are authored for this benchmark and marked
_provenance: generated; the config reports
prompt_provenance: upstream_chain_with_generated_normal_tissue so the mixed
bank is never reported as fully upstream.
The released CLIP RN50 prompt tensor does not match the published CSV
text_prompt_kidney_v2.csv has 27 rows. ..._plip.pt and ..._quiltnet.pt
are exact 27-row encodings of it. ..._clip_rn50.pt has 30 rows.
Cosine alignment shows csv[i] → released[i+3]: the three extra rows are at
the front, and released rows 3–9 match the CSV only at 0.92–0.97 (the
class prompts were reworded), while rows 10–29 match at exactly 1.0000.
So the CSV is not the source of the released CLIP tensor. Truncating the last three rows — the intuitive fix — would feed unknown text into the low-power branch and low-power text into the high-power branch, misaligning both class branches with no error raised.
The original file remains unchanged as an audit-only upstream artifact.
RCC configs instead select
rcc_text_prompt_features_clip_rn50_verified.pt, an exact ordered
re-encoding of all 27 upstream CSV rows with the official CLIP RN50
checkpoint. The derived payload embeds the prompts, source/checkpoint
hashes, feature-space ID, half-open row-role spans, and the explicit
encoder_native scale convention. Compiler, doctor, and runtime checks
reject a bare, reordered, or incorrectly normalized tensor.
The CSV—not CLIP—is the canonical bank. The local model width now follows
feature_dim, and scripts/build_cod_mil_prompt_features.py accepts the three
families for which upstream released RCC prompt artifacts: clip-rn50, plip,
and QuiltNet. The encoder-sweep name quiltnet is pinned to
wisdomik/QuiltNet-B-16. The released QuiltNet prompt tensor retains the
separate quiltnet-b32 / hf:wisdomik/QuiltNet-B-32 identity and is never
relabelled or paired with B-16 patch features. A B-16 prompt tensor must be
re-encoded from the canonical CSV with the B-16 text tower. Upstream's model
code itself hardcodes 1024 dimensions, so a
PLIP/QuiltNet run is honestly labelled a width-parameterized implementation
extension (upstream_fidelity: partial), not an upstream reproduction. It must
use patch bags and a verified prompt tensor from the same feature space. This
is not a width projection: vectors from unrelated encoders are never compared
merely because their dimensions match. Runtime-cached encoding can consume the
same CSV directly when the matching text checkpoint is available.
The released artifacts do not share one normalization convention. Direct inspection gives CLIP-RN50 row norms of 9.04–10.42 (mean 9.67), while every PLIP and QuiltNet row has unit norm. The released model does not normalize the tensor again. Runtime encoding and derived caches therefore select the published convention by encoder; the former blanket unit normalization made the BRCA CLIP path roughly ten times smaller than its upstream input.
Upstream's model also slices normal prompts as text_feature[2C:-1], dropping
the final row — an ordinary tissue prompt, not a sentinel. PGVL-Gym corrects
that off-by-one to [2C:], records the correction as partial fidelity, and
tests that the last background row reaches the auxiliary branch. The released
training loop constructs a plateau scheduler but never calls step; the
adapter now returns no scheduler so the unified trainer cannot silently add a
different learning-rate recipe.
The benchmark's 4-shot BRCA fold contains eight training slides, whereas the released CoD-MIL recipe is full-data and learns a randomly initialized 1024-wide two-layer text projection (about 2.10 million parameters) in addition to its attention path. Consequently a corrected few-shot score is not expected to reproduce the paper's full-data result; 8/16-shot and full-data runs are the appropriate capacity/data controls.
WSI-FiVE — the vision tower is not method-owned¶
The compatibility analysis originally attributed 18 blocked cells to "the method
owns its vision tower (wsi_five, convlm)". That framing was wrong for
WSI-FiVE and conflated PGVL's local ConVLM adapter with ConVLM's released
training path. For WSI-FiVE specifically,
with the shipped default IS_IMG_PTH: True, upstream sets
self.visual = nn.Identity() (MedCLIP vision is commented out), hardcodes
embed_dim = 512, never parses the CLIP state dict, and reads precomputed
features from CSV. The paper confirms it: "we employed ResNet following [15] as
image encoder… while pre-trained BioClinicalBERT as text encoder" — [15] is
DSMIL.
No MedCLIP weights load on any path. MedCLIPTextModel, the only MedCLIP
class instantiated, calls AutoModel.from_pretrained('./Bio_ClinicalBERT').
Every torch.load in MedCLIPModel.py belongs to a vision class that is never
constructed, so checkpoints/wsi_five/medclip_vit.bin is unreachable and is not
a blocker. The name is code provenance — upstream's README says "parts of the
codes are borrowed from X-CLIP, MedCLIP" — which this project's documentation
had turned into a model claim.
The vendored orchestrator does not run¶
FiVE.py cannot be imported (it wants VisionTransformer; canonical CLIP
defines VisualTransformer) and cannot be constructed (CLIP.__init__ raises
Trying to create tensor with negative dimension -1 on the vocab_size=-1
arguments build_model passes). Reusing it was never an option, so the model is
rebuilt from the vendored components that do work.
What is reproduced¶
| Mechanism | Source |
|---|---|
| Bag aggregation, self-attention + cross-attention branches, concat fusion | vendored PatchFusionTransformer |
| Six clinical questions as cross-attention queries | release PROMPT_LIST |
| BioClinicalBERT text tower with LoRA (r=8, α=32) | vendored MedCLIPTextModel + LoraWrap |
| 16 learnable soft prompts injected into BERT embeddings | encode_prompt_embed |
Positions from patch index within slide; sample_range padding masks |
vendored get_pos_embed |
logit_scale = 300 |
hardcoded upstream, not learned |
Verified: BioClinicalBERT weights load identically to the original checkpoint, LoRA leaves 1.34M of 117.9M parameters trainable with the base frozen, a forward pass over a 137-patch bag returns finite logits, and gradients reach both the soft prompts and the fusion transformer.
Native text supervision and evaluation¶
FiVE does not train against class names and a slide's answers do not condition its fusion transformer. The official release assigns three separate roles to text:
| Text asset | Role | Local provenance |
|---|---|---|
| Six clinical questions | Cross-attention queries that condition patch aggregation | Derived JSON container preserving upstream configs/wsi/fix_pth.yaml:PROMPT_LIST verbatim |
| Six answers per case | Training answer candidates and targets | Generated complete CSV: 912 upstream GPT answers are preserved, 27 blank upstream cells receive disclosed conservative local completions, and 82 benchmark-only cases receive the same conservative template from openai:gpt-5.6 |
| LUAD/LUSC diagnostic descriptions | Validation/test comparison bank | Derived JSON container preserving upstream LUAD_LUSC_labels_{train,val}_reid.csv text verbatim |
These assets are pinned to WSI-FiVE commit
07344c9ac6eef919fcd1440877ea796feef7445a. None is a byte-for-byte upstream
file: JSON containers were introduced for questions and evaluation text, and
the two answer workbooks were normalized into one CSV. The reproducible answer
derivation merges 471 LUAD and 468 LUSC rows, splits the 912 nonblank upstream
answers into exactly six stripped fields, fills the 27 blank upstream cells
with six deterministic, conservative “not documented/cannot determine” answers,
then appends the 82 cases present in PGVL-Gym's NSCLC cohort but absent from the
released workbooks using the same conservative template generated by
openai:gpt-5.6, and sorts all 1,021 records by case_id. These generated rows
do not infer positive clinical findings from unavailable text. The exact fill
text, generator, source-cohort hash, and affected case IDs are listed in
text_prompts/PROVENANCE.json.
scripts/build_wsi_five_prompt_assets.py --check verifies the source workbook
hashes, counts, and byte-exact generated CSV.
The NSCLC answer asset covers every one of the benchmark's 946 cases while
retaining 75 released-workbook cases outside the local cohort. All six fields
are present. Because 109 records contain generated completions (27 blank
upstream cells plus 82 cohort extensions), the answer asset and aggregate native
condition explicitly report generated answer provenance; they must not be
described as a purely upstream answer bank. For each benchmark fold, the adapter
reads answers only for training rows, constructs
and hashes a unique candidate bank from that fold, randomly drops zero to five
aligned question/answer fields, removes Unknown answers, and shuffles retained
answer segments. This restores the released
aug_question and label-hashing semantics without admitting validation/test
answers into the bank. The saved fold trace records the candidate count, asset
sources, and a SHA-256 digest, but deliberately does not duplicate patient text.
At validation and test time the dataset does not require or return an answer for inference. The slide is aggregated from patch features, the six questions, and the learned soft prompts, then compared only with the two released diagnostic descriptions in label-index order. This closes the former privileged-text path and makes missing answers on held-out cases harmless.
The released loss retrieves one case-specific answer record from the training
bank; it never optimizes the LUAD/LUSC comparison logits used at evaluation.
That is workable with the authors' full-cohort bank, but under the frozen
4/8/16/32/64-shot protocol the bank contains 8/16/32/64/128 cases. An audit of the
4-shot fold found useful slide ranking but complete one-class prediction in the
native DSMIL, CLIP-R50, KEEP, and QuiltNet conditions. PGVL-Gym therefore keeps
the answer-retrieval loss and adds a weight-1 cross-entropy class-boundary
anchor against the same released LUAD/LUSC descriptions. The anchor consumes
only training-fold slide labels; validation and test data remain absent from
both losses. few_shot_class_anchor_weight: 1.0 records this local adaptation,
and setting it to 0 recovers the pure released answer objective. Result
provenance marks the anchored condition as partial and does not attribute the
extra term to the paper.
The answer-bank native mode is declared only for TCGA-NSCLC. CAMELYON16 is a
different released condition: fix_pth_cam.yaml supplies the literal
normal/tumor class CSVs, 22,528 frames at a 0.50 sampling fraction, and the
same six questions. Those questions visibly mention spread through air spaces,
pleural invasion, and the current lung organ even in the authors' CAMELYON
config. The upstream_classname_bank runtime preserves and hash-binds that
exact condition without loading report answers, and provenance explicitly
records the upstream content defect. RCC and UBC example configs instead use
generated task questions with simplified_classnames; WSI-FiVE published no
native assets for those tasks.
The CAMELYON condition is a downstream transfer experiment, not a from-scratch
eight-slide learner. Section 4.4 of the paper states that downstream networks
are initialized from FiVE weights pretrained on TCGA image-report pairs. The
authors' released five_fix_pth_95.4.pth is 648,822,747 bytes with SHA-256
5891c7cf02a8232879d9cad8f023a59536c9947e4efb78e46570bdcf7a62c1c9;
registered CAMELYON configs bind both values and the doctor rejects a missing
or altered file. A strict namespace translator maps upstream transformer.*
weights into the rebuilt text.* module and requires exact target coverage and
shapes. The only omitted source entries are the unused learned logit_scale
(upstream's executable forward path hardcodes 300) and BERT's deterministic
position_ids range buffer (the installed Transformers release represents it
as non-persistent). This is initialization, not a resume operation; optimizer,
epoch, and scheduler state are deliberately not loaded.
The TCGA checkpoint allocates both MIT positional_embedding parameters for
16,384 patches, whereas fix_pth_cam.yaml constructs the downstream model for
22,528. PyTorch cannot load that shape mismatch even with strict=False.
Those two parameters are non-executable in the released code: their addition
is commented out and get_pos_embed supplies sinusoidal encodings from each
patch index instead. The translator therefore initializes just those dead
parameters at the CAMELYON shape and records
wsi_checkpoint_position_transfer: reinitialize_unused_mit_position_parameters_v1;
all active fusion weights remain strict checkpoint copies.
The same audit fixed two smaller orchestration differences. Soft-prompt encoding now averages BERT hidden layers 1, 2, and the last layer before its projection, matching upstream instead of pooling only the final layer. During CAMELYON training the two class strings are treated as one answer segment while zero to five questions are dropped, preserving the released augmentation even when dropping field zero deduplicates both strings and yields a zero-loss update. Full two-class logits are still emitted for unified training diagnostics, but they do not replace that upstream loss.
The sampling fraction is executable, not descriptive metadata. Upstream
SampleWSIData chooses
min(int(total_patches * NUM_FRAMES_PERCENT), NUM_FRAMES) positions, drawing
one random position from each integer interval during training and each
floating interval midpoint during evaluation. The earlier unified loader
ignored num_frames_percent and used a random subset/endpoint linspace up to
the absolute cap. On the 399 imported CAMELYON16 bags, 397 fall below the cap
after halving; consequently that defect used roughly twice the requested
patches for almost every slide (median 10,853 instead of 5,426). The runtime
now restores the interval sampler and generated configs pin
wsi_sampling_policy: upstream_stratified_percent_v1, which also makes those
pre-fix result identities stale.
Runtime, config compilation, and the doctor load all three roles through the same strict contract. Each config binds the asset byte hash, a semantic ordered bank hash, and role provenance; edited, reordered, relabelled, or substituted text fails before training.
The fixed-feature launch recipe now also follows the released executable
NSCLC configuration: 100 epochs, 16,384 frames, batch size 1 with eight-step gradient
accumulation, AdamW (betas=(0.9, 0.98), eps=1e-8), base LR 3e-6, 10x LR
for the released fusion/message/prompt parameter-name groups, weight decay
0.001, five warmup epochs, and per-update cosine decay. The doctor rejects a
native config that silently falls back to the former 30-epoch/2,048-frame local
defaults.
Remaining deviations
- Rebuilt orchestration. The released
FiVE.pycannot be imported or constructed, so the lifecycle is rebuilt around its usable vendored components and remains marked partial. - Fold scope. The release publishes a fixed full training candidate bank. PGVL-Gym rebuilds it from each benchmark training fold to prevent answer leakage across few-shot folds.
- Few-shot class anchor. Registered NSCLC benchmark configs add a
weight-1 task-class loss on training-fold labels because answer-only
4-shot training left the evaluation boundary unconstrained and caused
one-class collapse. This term is local and can be disabled with
few_shot_class_anchor_weight: 0for a pure-objective ablation. - Generated cohort completion. Eighty-two benchmark cases are absent from the released answer workbooks. Their GPT-5.6 conservative “not documented/cannot determine” rows make the shared benchmark folds executable but are not the paper's supervision.
- Scheduler integration. The released timm cosine schedule is reproduced directly in the adapter at optimizer-update boundaries because the unified trainer exposes epoch-level scheduler hooks. This changes orchestration, not the declared LR curve.
- Incomplete accumulation groups. The release silently drops a final group containing fewer than eight batches. PGVL-Gym flushes that group so a nonstandard split cannot discard examples. The registered two-class 4/8/16/32/64-shot training folds contain 8/16/32/64/128 batches, so this safeguard does not change the benchmark recipe.
- Feature provenance. The paper uses DSMIL SimCLR-ResNet18 512-d features. A run using a different 512-d feature space is dimensionally valid but not the paper's encoder condition.
Registered WSI-FiVE encoder extensions¶
The native wsi_five experiment remains pinned to the paper's offline DSMIL
SimCLR-ResNet18 512-wide bags. The TCGA-NSCLC protocol additionally registers
seven separately named 20x feature conditions: CONCH v1 and QuiltNet-B-16
(512), PLIP, KEEP, and CONCH v1.5 vision-preprojection (768), plus CLIP-RN50 and
MUSK (1024). The model already projects BioClinicalBERT into feature_dim and
constructs patch fusion at that same width, so these are executable
architecture extensions rather than width-only relabellings.
They are not same-VLM semantic swaps. WSI-FiVE never invokes the selected
VLM's text tower: its six questions, answer candidates, and evaluation texts
continue through LoRA-adapted BioClinicalBERT. The text output projection and
patch-fusion module learn alignment to the selected cached patch space during
training. Every generated extension config therefore records
feature_encoder, feature_space_id, BioClinicalBERT as prompt_encoder, and
alignment_mode: learned_projection; result rows are extended / partial
with encoder_provenance: adapted and cannot share the native DSMIL label.
Six additional NSCLC paired-tower ablations are registered for CONCH v1,
QuiltNet-B-16, CLIP-RN50, PLIP, KEEP, and MUSK. In these rows every fixed text
role (questions, answer candidates, and evaluation descriptions) is encoded by
the exact frozen text tower paired with the cached visual checkpoint. Sixteen
native-width, native-context soft prompts and WSI-FiVE's patch-fusion module
are trained per fold; the VLM tower and cached patch features remain frozen.
PLIP's stored 768-wide preprojection vectors pass through that same frozen
checkpoint's native 768-to-512 visual projection before normalization and
fusion. KEEP uses its 256-token BERT inputs_embeds path, while MUSK uses its
100-token BEiT3 embedded-token path and language head. These are explicitly
extended / partial ablations: replacing BioClinicalBERT/LoRA changes the
published WSI-FiVE architecture even though visual and text spaces now match.
CONCH v1.5 is excluded because this registry does not expose an exact matching
promptable text tower for the cached v1.5 preprojection space.
The paired CLIP-RN50 condition has an additional fixed-tower boundary. Its
tokenizer cannot represent more than 77 positions, while 183 of the 1,021 full
NSCLC answer candidates exceed that limit (maximum 144 CLIP BPE tokens). Rather
than dropping report rows, altering the answer bank, or silently substituting a
long-context tower, this condition calls OpenAI CLIP's own truncate=True
tokenizer path. That path retains the start token and replaces position 76 with
EOT. The behavior is serialized as clip_eot_truncate_77_v1, applies only to
overlength paired-CLIP strings, and remains an extension rather than upstream
WSI-FiVE behavior. The BioClinicalBERT path and all non-CLIP paired towers are
untouched.
Native DSMIL high-score audit¶
The NSCLC fold-0 4-shot native result was checked for an accidentally easier split. It predicts all 208 canonical test slides (109 LUAD, 99 LUSC; 190 patients), has zero failed samples and zero missing DSMIL files, and uses the same exact test slide-ID set as every other completed fold-0 method. Train, validation, and test contain 8, 8, and 208 slides respectively, with no case or slide overlap. No duplicate HDF5 inode or sampled feature fingerprint was found across partitions.
The feature space itself is unusually separable: a text-free nearest-centroid
classifier fitted to only the eight training-slide mean vectors reaches 0.908
slide balanced accuracy and 0.982 AUROC, compared with WSI-FiVE's 0.917 and
0.983. The high WSI-FiVE score is therefore consistent with the released DSMIL
representation rather than observed split leakage or a hidden WSI-FiVE
checkpoint. The upstream representation recipe is transductive relative to
our folds: DSMIL's
simclr/run.py
globs every patch under the selected TCGA-Lung dataset into all_patches.csv
before the SimCLR loader applies its independent 10% SSL validation split.
The released WSI-FiVE README identifies its downloadable TCGA features as the
DSMIL-provided artifacts. Test-slide images can therefore influence the frozen
representation without their labels. This is unlabeled representation
exposure, not supervised train/test label leakage, and must be disclosed when
comparing against a strictly inductive feature encoder.
The downloaded release archives are retained in staging and imported with
scripts/import_wsi_five_dsmil_features.py. It verifies ZIP integrity and a
pinned SHA-256, restricts installation to frozen manifest slide IDs, validates
the upstream headered 512-column CSV matrices, rejects empty/non-finite data,
and atomically writes float32 HDF5 bags with source URL, archive digest, and
member provenance. The CAMELYON16 and TCGA source archives are respectively
9d4e1ab1edc875c6b00d6af4a53969ec06177b563cbd0a6fdde65e27f2ffaad5
and 14ac4cf214874aa62a6076b1d14924c375433eb6bb8ce77030e28e4a98263463.
ConVLM — missing upstream attributes and a local feature-bag reconstruction¶
The release is pinned at commit
a399e51585eeb4c7974b274174ca9b0360a9120d.
It does not contain a reusable class prompt bank or the dataset-specific
att_splits.mat loaded by
train.py.
Its two text utilities do not fill that gap:
generate_text.pyasks Quilt-LLaVA for one description per input image. It produces image-specific JSONL, not an ordered class bank.attribute_embedding_generation.pyis hard-coded to the two NSCLC labels, contains malformed quoted input, callsquilt_model.encode_text(text)(text), and never saves an attribute matrix.
There is therefore no honest upstream bank to import. The CAMELYON16,
TCGA-NSCLC, TCGA-BRCA, TCGA-RCC, and UBC-OCEAN JSONs checked into
text_prompts/convlm/ are all generated substitutes. NSCLC deliberately
selects its bank for one explicitly partial local reconstruction; the other
four remain unwired. Their file hashes, ordered prompt-content hashes, class order, prompt
counts, and copied_from_upstream: false declarations are pinned in
text_prompts/PROVENANCE.json. Selecting one reports
prompt_provenance: generated and
prompt_source: convlm_generated_attribute_prompts regardless of whether its
path came from prompts:, a legacy cohort key, or the compiler.
The runtime preserves every prompt through loading, then performs a local aggregation: it normalizes each encoded prompt, averages within class, and normalizes the resulting class vector. Because upstream publishes no executable equivalent, this is disclosed as a reconstruction rather than described as the paper's QuiltNet attribute protocol.
Precomputed attributes use schema
pgvl.convlm.attribute_embeddings.v1. The doctor and runtime reject a bare
tensor or .npy: the artifact must carry exact ordered classnames, the source
prompt-bank SHA-256, prompt provenance, feature-space ID, and encoder metadata
including checkpoint SHA-256. This boundary is encoder-agnostic—QuiltNet is one
valid declared space, not a hard-coded requirement—but a matrix from one text
tower cannot silently be paired with another.
The registered NSCLC reconstruction uses complete QuiltNet-B-16 20x patch
bags and encodes the generated attributes at runtime with the pinned
wisdomik/QuiltNet-B-16 checkpoint
a5a588b6cec62d610bfc25f64dfe1df30fa6af98 (SHA-256
b059d20776597f0f4ab92635b24b756376fd669b580d6b266c8daa184b0f7379).
It caps each WSI at 512 sampled patches so full self-attention has an executable
memory boundary. The source JSON remains the canonical, encoder-agnostic bank;
no anonymous tensor is required.
The architecture boundary also differs from the release. PGVL's adapter reads
precomputed WSI patch bags and applies a locally written attribute-conditioned
token-pruning transformer. The released train.py instead constructs the
raw-image ViT from convlm.py, whose PatchEmbed consumes 224×224 RGB images.
The repository contains a separate UNI feature extractor and its README
discusses ROI features, but the released training script does not consume those
bags. PRECOMPUTED/PATCH_BAG consequently describes this benchmark adapter,
not an upstream-compatible data path. The active NSCLC row consequently reports
reimplemented_feature_bag_reconstruction and upstream_fidelity: partial.
MUSE — upstream and generated prompt banks¶
The release at commit 9f2ec37bad5a10bb79616900ec017830b0bdfa0a
covers camelyon_all, tcga_brca, and tcga_nsclc. All six selected CSVs are
byte-exact imports with 300 indexed descriptions per class. Their SHA-256,
classname, and class index are pinned in text_prompts/PROVENANCE.json.
Its kidney folder is IgA nephropathy grading, a different disease and
task from renal cell carcinoma subtyping; "carcinoma" appears zero times
across its six files. It is not a substitute for RCC. The release contains no
UBC-OCEAN bank either.
RCC and UBC-OCEAN MUSE banks are local conversions of description text released
for MSCPT. Reusing released text from a different method does not create an
upstream MUSE condition: all eight CSVs report prompt_provenance: generated
and prompt_source: muse_generated_task_extension_csvs. A result on either
task is not prompt-faithful to MUSE and must not be tabled as though it were.
MUSE's CSV shape is part of the runtime contract. The shared loader and doctor
require the exact ,0 header, sequential zero-based row indices, one non-empty
description per row, exact classname coverage, and audited class-to-file
binding. Registered assets additionally enforce their row counts and SHA-256.
Released duplicate descriptions are intentionally retained because changing
their multiplicity changes the authors' stochastic sampling distribution.
Registered MUSE runs no longer substitute one learned class vector for the
released prompt learner. They execute the shared 16-token CONCH context inside
the frozen differentiable text tower. Description CSVs are encoded through the
same released MUSE text path, and the training-only semantic queue contains the
ground-truth class's 20 most similar
descriptions in shuffled order. The paper's SFSE equations apply top-20% patch
filtering to both the base and auxiliary priors; PGVL-Gym follows that published
definition rather than the public forward's unfiltered base branch. Paper
Algorithm 1 exhausts that queue for every WSI, so the adapter makes
20 Adam updates per bag rather than sampling one description with replacement.
The 8-expert noisy top-2 router and Equation 12 mean of base and auxiliary
logits are active. The fixed learning rate reflects the released trainer, which
constructs a plateau scheduler but never steps it; checkpoints minimize
validation error with patience 20 and earliest stop after epoch 80.
muse_prompt_learning: token_16_conch and
muse_runtime: sfse_smmo_full_queue_token_prompt_v2 make this runtime identity
explicit. The public model sums the two logits despite Equation 12's mean and
retrieves only one semantic view in the exposed forward path; those source/paper
conflicts are recorded as corrections rather than silently inherited.
The frozen CONCH tower and deterministic description embeddings are cached
per process across folds; every fold still receives a newly initialized,
independently optimized 16-token context and trainable MUSE head. The cache
therefore removes repeated setup work without carrying learned fold state.
Two boundaries remain disclosed. The standard visual-encoder extensions map a
different offline patch producer through MUSE's learned visual adapter into
the native CONCH prompt space; they are not paired-tower swaps. A new opt-in
text-tower extension can instead select any registered black-box text encoder
with a declared shared dimension. It encodes every description and initial
class semantic with that frozen tower, then trains MUSE's visual adapter and a
class-specific delta directly in the selected shared feature space. Because
that path replaces the released 16-token CONCH learner, it must set
muse_prompt_learning: feature_space_context_fallback, carry a derived
encoder_extension record, and remain a separately named partial condition.
It is not described as the upstream MUSE architecture even when the cached
vision and selected text tower happen to share a family. Also, the public
source requests the least cosine-similar descriptions despite the paper
specifying the most similar; PGVL-Gym follows the paper and records that
correction in implementation provenance.
The current registry's 5x/10x/20x feature rows are magnification sweeps: the
paper reports 512-pixel CONCH tiles at 40x. Generated provenance and doctor
warnings retain that distinction even when the runtime itself is faithful.
PathPT — published 20x recipe and family-specific pseudo loss¶
All PathPT subtyping rows use the paper's 20x feature resolution. Optimizer,
LR, epochs, prompt length, and base loss weights are held constant across
PLIP/CONCH/KEEP/MUSK. The one intentional encoder-specific switch is the
published pseudo-label policy: it starts at epoch 10 for CONCH and KEEP, and is
disabled for PLIP and MUSK because the authors report unstable training for
those families. The adapter overrides build_optimizer and build_scheduler
to enforce the shared portion regardless of the YAML. Generator and doctor
label a non-20x run as a magnification extension and reject a contradictory
pseudo-loss setting.
The executable source is pinned at commit
0ab7f1b3bfc70ce3a85d4daaba3e018cc61fb087. Its epoch-level LambdaLR
evaluates step zero during construction, so the two warm-up epochs train at
0 and 0.5 times the configured rate before reaching the full rate. The adapter
preserves that released zero-start behavior; the generated
pathpt_scheduler field prevents results from the former shifted schedule
from being resumed or mixed with this condition.
Generated configs use training_mode: upstream_patch_ssl. After the fold's
model and training loader are built, PathPT encodes all combinations of its 22
templates and task synonyms, scores 200 sampled prompt classifiers on training slides only,
and averages the best 100. That frozen classifier creates Normal, known subtype,
and negative candidate patch labels. Training calls the vendored PatchSSLoss;
WSI inference counts patch votes, removes the synthetic Normal class, and uses
the released all-Normal/tie fallback. The selected classifier and full score
trace are persisted per fold. The old mean-patch-probability slide CE path is
retained as the explicit simplified_slide_ce compatibility mode.
Prompt selection normalizes patch rows at the adapter boundary because PathPT
defines cosine similarity while external feature writers may preserve vector
norm. Candidate ties use the released np.argsort(...)[::-1] ordering exactly;
ties are frequent in few-shot folds and changing this detail changes which 100
classifiers are averaged.
The common PGVL-Gym cohort is not the paper's direct reproduction protocol. For TCGA-BRCA, this benchmark uses the full eligible, naturally imbalanced cohort with 4/8/16/32/64-shot five-fold splits. The PathPT paper reports a balanced 150-slide IDC/ILC cohort, 1/5/10-shot settings, and ten resamples. Compare PGVL-Gym methods within the frozen common split and report slide balanced accuracy as primary; do not compare these values directly with the paper's table.
Prompt provenance is cohort-specific:
| Cohort | Bank | Fidelity note |
|---|---|---|
| TCGA-BRCA | upstream PathPT brca_names |
native subtype pipeline |
| UBC-OCEAN | upstream PathPT ubc_names |
native subtype pipeline |
| TCGA-NSCLC | generated here | native algorithm, local task bank |
| TCGA-RCC | generated here | native algorithm, local task bank |
| CAMELYON16 | upstream PathPT camelyon_names |
validation-calibrated top-1% tumour-evidence WSI adaptation; the paper evaluates CAMELYON region segmentation, so fidelity remains partial |
The old CAMELYON integration applied PathPT's hard patch-count vote directly
to a normal-versus-metastatic slide task. That vote is suitable only after the
synthetic Normal row has been removed from a tumour-subtyping decision; on a
positive lymph-node WSI, normal tissue can still occupy most patches. It thus
collapsed to Normal even when ranking was useful (the KEEP diagnostic reached
about 0.755 AUROC). The registered binary adaptation now averages the strongest
1% tumour probabilities and chooses a monotonic decision boundary using only
the fold's validation labels. The threshold is stored in the model checkpoint
and an audited fold*_pathpt_binary_calibration.json; held-out test labels are
never read by calibration.
The CAMELYON upstream list has a missing comma that concatenates
non-cancerous tissue and normal breast tissue. The upstream condition is
kept byte-for-byte and the defect is recorded in text_prompts/PROVENANCE.json.
Correcting it would be a separate derived prompt condition.
Paired-VLM ports for encoder-bound architectures¶
FOCUS, ViLa-MIL, TOP, MGPATH, Libra-MIL, DyKo, and HIPSS formerly rejected every non-native encoder. That was safer than a width-only substitution, but it also prevented controlled paired-tower ablations. PGVL-Gym now exposes opt-in ports without changing any native branch or existing protocol row.
The compiler requires an exact final shared feature_space_id, matching
vision and text encoder names/checkpoints, and encoder_extension: true.
Crossed KEEP-vision/MUSK-text conditions and same-width private tensors are
rejected. Resolved configs store distinct patch_encoder, prompt_encoder,
encoder_extension, and encoder_extension_strategy records.
The modifications are deliberately method-specific:
- Libra-MIL needs no bridge: both prompt roles are simply re-encoded in the selected paired space and all learned prototype/SOT equations are retained.
- FOCUS, ViLa-MIL, TOP, and MGPATH retain their visual aggregation and losses, but replace encoder-specific token learners with zero-initialized additive context in final text-feature space. TOP keeps separate bag and instance contexts; MGPATH keeps four independent views.
- DyKo keeps its released TITAN concept tensor. A trainable linear projection maps that fixed 768-wide bank into the selected paired space, while class token prompting becomes feature-space context. This row measures DyKo plus the concept bridge.
- HIPSS cannot apply CONCH residual-block SSF to KEEP or MUSK. Its extension encodes WSI/region roles separately, combines them in paired feature space, and applies identity-initialized feature-wise affine layers there. The hierarchy is retained, but this is not layerwise SSF.
No extension is automatically added to the campaign. An authored protocol must select the feature stores and create a separately named experiment; the doctor and provenance resolver then enforce the disclosed boundary.
8. Decisions still open¶
| Item | Question |
|---|---|
| ConVLM | Can the authors release the data-specific att_splits.mat and a working generator so a true upstream attribute condition can be added? |