Saliency-Curated Deep Learning for Predicting Receptor Status in Breast Cancer Brain Metastases.
The 12 matches
- [1] § 2. Materials and Methods › 2.2. Model Architecture and Processing Pipeline › 2.2.2. Data Augmentation and Normalization ↔ src/utils/transformations.py, lines 214–229 · score 0.96 · ElasticDeformation3D, RandomFlip3D, RandomGamma3D, RandomGaussianBlur3D, RandomRotation3D, RandomTranslation3D
- [2] § 2. Materials and Methods › 2.3. Model Development ↔ src/utils/Calibrator.py, lines 40–104 · score 0.74 · Binary Cross Entropy, Platt scaling, temperature, sigmoid, calibrated, logits
- [3] § 2. Materials and Methods › 2.1. Data Acquisition › 2.1.2. Train–Test Split ↔ src/Trainer.py, lines 261–376 · score 0.70 · cross validation, validation folds, leakage, stratified, split, augmentation
- [4] § 2. Materials and Methods › 2.3. Model Development ↔ src/utils/TemperatureCalibrator.py, lines 27–84 · score 0.69 · Binary Cross Entropy, temperature, minimizing, sigmoid, calibrated, logits
- [5] § 2. Materials and Methods › 2.2. Model Architecture and Processing Pipeline › 2.2.4. Classification Head ↔ src/model_definitions/ResNet.py, lines 80–132 · score 0.67 · Layer Normalization, ReLU, GAP, linear, Dropout, Head
- [6] § 2. Materials and Methods › 2.3. Model Development ↔ src/main.py, lines 23–87 · score 0.67 · Asymmetric Focal Loss, AdamW, optimized, Training, class, Model
- [7] § 2. Materials and Methods › 2.3. Model Development ↔ src/main.py, lines 23–87 · score 0.65 · weight decay, Optuna, Hyperparameter, dropout, shifting, optimization
- [8] § 2. Materials and Methods › 2.2. Model Architecture and Processing Pipeline › 2.2.3. Encoder Architecture ↔ src/model_definitions/ResNet.py, lines 80–132 · score 0.61 · channel dimension, ResNet, concatenated, bottleneck, resized, block
- [9] § 2. Materials and Methods › 2.2. Model Architecture and Processing Pipeline › 2.2.3. Encoder Architecture ↔ src/model_definitions/ResNet.py, lines 41–78 · score 0.56 · ResNet, doubling, downsampling, stride, encoder, block
- [10] § 2. Materials and Methods › 2.3. Model Development ↔ src/utils/losses.py, lines 39–90 · score 0.55 · Asymmetric Focal Loss, ASL, class
- [11] § 5. Limitations and Future Directions ↔ src/Trainer.py, lines 261–376 · score 0.53 · cross validation, aggregation, multilabel, pipeline, augmentation, fold
- [12] § 2. Materials and Methods › 2.2. Model Architecture and Processing Pipeline › 2.2.4. Classification Head ↔ src/model_definitions/UNet.py, lines 136–151 · score 0.51 · ReLU, GAP, linear, global, Head, classifier
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 233 lines · 8.1 KB · no license · 3 matches
- import torch
- import torch.nn as nn
- import torch.nn.functional as F
- from utils.constants import DEVICE
- # Basic 3D Residual Block
- class ResBlock3D(nn.Module):
- """
- A simple 3D residual block: Conv3D -> BN -> ReLU -> Conv3D -> BN + residual
- Input shape: [B, C_in, D, H, W]
- Output shape: [B, C_out, D, H, W]
- """
- def __init__(self, in_channels, out_channels, stride=1):
- super(ResBlock3D, self).__init__()
- self.conv1 = nn.Conv3d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
- self.bn1 = nn.InstanceNorm3d(out_channels)
- self.relu = nn.ReLU(inplace=True)
- self.conv2 = nn.Conv3d(out_channels, out_channels, kernel_size=3, padding=1)
- self.bn2 = nn.InstanceNorm3d(out_channels)
- # Residual projection if in/out channels differ
- self.proj = None
- if in_channels != out_channels or stride != 1:
- self.proj = nn.Conv3d(in_channels, out_channels, kernel_size=1, stride=stride)
- def forward(self, x):
- identity = x
- out = self.conv1(x)
- out = self.bn1(out)
- out = self.relu(out)
- out = self.conv2(out)
- out = self.bn2(out)
- if self.proj:
- identity = self.proj(identity)
- out += identity
- out = self.relu(out)
- return out
- # ResNet3D Encoder
- class ResNet3DEncoder(nn.Module):
- """
- 3D ResNet Encoder with residual blocks.
- - depth: number of residual blocks
- - base_filters: number of channels in first block (doubles at each subsequent block)
- Outputs:
- - bottleneck: final feature map
- - skips: list of intermediate features for classifier aggregation
- """
- def __init__(self, depth=3, base_filters=16):
- super(ResNet3DEncoder, self).__init__()
- self.depth = depth
- self.base_filters = base_filters
- self.blocks = nn.ModuleList()
- self.downsamples = nn.ModuleList()
- last_channels = 1 # input is 1 channel (grayscale)
- out_channels = base_filters
- for i in range(depth):
- self.blocks.append(ResBlock3D(last_channels, out_channels))
- if i < depth - 1:
- # Downsample spatial dims by 2
- self.downsamples.append(nn.Conv3d(out_channels, out_channels, kernel_size=2, stride=2))
- else:
- self.downsamples.append(None)
- last_channels = out_channels
- out_channels *= 2 # double channels each block
- def forward(self, x):
- skips = []
- for i, block in enumerate(self.blocks):
- x = block(x)
- skips.append(x) # store features for classifier
- if i < self.depth - 1:
- x = self.downsamples[i](x)
- return x, skips # x is bottleneck
- # Classifier Head with Skip Weights
- class ClassifierHead3D(nn.Module):
- """
- Combines multi-scale skip features via learnable per-skip weights,
- then performs classification via fully connected layers.
- """
- def __init__(self, skip_channels, num_classes=3, dropout=0.0):
- super().__init__()
- self.num_skips = len(skip_channels)
- self.skip_weights = nn.Parameter(torch.ones(self.num_skips)) # learnable scalar weights
- total_channels = sum(skip_channels)
- self.classifier = nn.Sequential(
- nn.AdaptiveAvgPool3d(1), # GAP → [B, C, 1, 1, 1]
- nn.Flatten(), # for a 5 layer resnet with 16 starting features = 16 + 32 + 64 + 128 + 256 = 496 features
- nn.Linear(total_channels, 256),
- nn.LayerNorm(256),
- nn.ReLU(inplace=True),
- nn.Dropout(dropout),
- nn.Linear(256, 128),
- nn.LayerNorm(128),
- nn.ReLU(inplace=True),
- nn.Dropout(dropout),
- nn.Linear(128, num_classes)
- )
- def forward(self, skips: list[torch.Tensor]):
- """
- skips: list of [B, C_i, D_i, H_i, W_i] feature maps from encoder blocks
- self.skip_weights: tensor of shape [num_skips], scalar weight per skip
- """
- # spatial size of bottleneck (last skip)
- target_shape = skips[-1].shape[2:] # (D_b, H_b, W_b)
- # resize each skip to bottleneck size if needed
- resized_skips = [
- F.adaptive_avg_pool3d(f, target_shape) if f.shape[2:] != target_shape else f
- for f in skips
- ]
- # element-wise multiplication of each skip by its scalar weight
- weighted_skips = [
- f * w.to(f.device).view(1, 1, 1, 1, 1) # broadcast scalar to [B, C_i, D, H, W]
- for f, w in zip(resized_skips, self.skip_weights)
- ]
- # concatenate along channel dimension
- concat = torch.cat(weighted_skips, dim=1) # [B, ΣC_i, D, H, W]
- # forward through classifier
- out = self.classifier(concat)
- return out
- # Full ResNet3D Classifier
- class ResNet3D(nn.Module):
- """
- ResNet for 3D Image MultiLabel Classification.
- - No decoder, residual blocks in encoder
- - Classifier head receives multi-scale skip features
- - Supports dynamic depth
- """
- def __init__(self, depth=4, base_filters=16, clf_threshold=[0.5,0.5,0.5], dropout=0.0):
- super(ResNet3D, self).__init__()
- self.name = "ResNet3D"
- self.depth = depth
- self.base_filters = base_filters
- self.clf_threshold = torch.tensor(clf_threshold).to(DEVICE)
- self.dropout = dropout
- self.encoder = ResNet3DEncoder(depth, base_filters)
- # Compute channels at each skip for classifier head
- skip_channels = []
- c = base_filters
- for i in range(depth):
- skip_channels.append(c)
- c *= 2
- self.classifier = ClassifierHead3D(skip_channels, dropout=dropout)
- def forward(self, x):
- bottleneck, skips = self.encoder(x)
- classifier_out = self.classifier(skips)
- return classifier_out
- def predict(self, x, return_raw=False, saliency=False):
- self.eval()
- if not saliency:
- with torch.no_grad():
- classifier_out = self.forward(x)
- probs = torch.sigmoid(classifier_out)
- preds = (probs > self.clf_threshold).float()
- if return_raw:
- return preds, probs, classifier_out
- return preds, probs
- # Vanilla Saliency maps
- num_labels = self.classifier.classifier[-1].out_features
- saliency_maps = {}
- # ensure input requires grad
- x_req = x.clone().detach().requires_grad_(True)
- # forward pass
- classifier_out = self.forward(x_req)
- for label_idx in range(num_labels):
- self.zero_grad()
- score = classifier_out[0, label_idx] # assuming batch size 1
- score.backward(retain_graph=True)
- grad = x_req.grad.detach().cpu()[0, 0] # [D, H, W], assuming 1 input channel
- saliency_maps[label_idx] = grad.abs().numpy() # take absolute value
- # reset gradients for next label
- x_req.grad.zero_()
- # standard prediction
- with torch.no_grad():
- probs = torch.sigmoid(classifier_out)
- preds = (probs > self.clf_threshold).float()
- if return_raw:
- return preds, probs, classifier_out, saliency_maps
- return preds, probs, saliency_maps
- def store(self, filepath):
- state = {
- 'model_state_dict': self.state_dict(),
- 'depth': self.depth,
- 'base_filters': self.base_filters,
- 'clf_threshold': self.clf_threshold,
- 'dropout': self.dropout,
- }
- torch.save(state, filepath)
- @classmethod
- def load(cls, filepath, map_location=None):
- checkpoint = torch.load(filepath, map_location=map_location)
- model = cls(
- depth=checkpoint['depth'],
- base_filters=checkpoint['base_filters'],
- clf_threshold=checkpoint.get('clf_threshold', [0.5,0.5,0.5])
- )
- model.load_state_dict(checkpoint['model_state_dict'])
- return model
- def get_config(self):
- return {
- 'depth': self.depth,
- 'base_filters': self.base_filters,
- 'clf_threshold': self.clf_threshold,
- 'dropout': self.dropout,
- }
ResNet.py at commit 1cb49ae, no license · at the source
Overview
- Department of Radiology, Stanford University School of Medicine, Stanford, CA 94305, USA
- Faculty of Electrical Engineering, Mathematics and Computer Science, Delft University of Technology, 2628 CD Delft, The Netherlands
- Department of Electrical Engineering, National Technical University of Athens, 15772 Zografou, Greece
- Bioinformatics Department, Cyprus Institute of Neurology and Genetics, Nicosia 2371, Cyprus
- Department of Surgery and Urology, Uppsala University Hospital, 75237 Uppsala, Sweden
- Endocrine and Breast Surgery, Department of Surgical Sciences, Uppsala University, 75105 Uppsala, Sweden
- Department of Internal Medicine-Hematology, University of Patras Medical School, 26500 Rion, Greece
- Department of Biological Sciences, Kean University, Union, NJ 07083, USA
- Department of Radiology, Division of Nuclear Medicine, University of Miami, Miami, FL 33136, USA
Abstract
Background: Breast cancer brain metastases (BCBMs) exhibit notable receptor discordance between primary tumors and metastases, yet obtaining intracranial biopsies is rarely practical. We created an interpretable deep learning radiogenomic model to predict estrogen receptor (ER), progesterone receptor (PR), and human epidermal growth factor receptor 2 (HER2) status from MRI scans in BCBM cases. Methods: A total of 241 post-contrast T1-weighted MRIs from 142 patients were analyzed. We developed a mask-free 3D Residual Neural Network (ResNet) ensemble trained directly on cropped, bias-corrected brain images, with comprehensive 3D geometric and intensity augmentations. The model was optimized in a multi-label setting using Asymmetric Focal Loss. Hyperparameters were fine-tuned via Bayesian optimization, and class probabilities were calibrated. Additionally, Integrated Gradients (IG) offered voxel-level saliency maps. Results: Our ResNet ensemble model achieved a micro-averaged AUROC of 0.74 and a macro-averaged AUROC of 0.67. Receptor-specific AUROCs were 0.57 for ER, 0.79 for PR, and 0.64 for HER2. The F1-scores were 0.56, 0.62, and 0.88 for ER, PR, and HER2, respectively. The held-out cohort contained only four HER2-negative patients, so threshold-dependent HER2 metrics are strongly prevalence-driven and AUROC is the more appropriate summary. Qualitatively inspected saliency maps were concentrated on enhancing metastases with limited background attribution. Conclusions: This proof-of-concept study shows that a segmentation-free, interpretable 3D Convolutional Neural Network (CNN) can be trained to capture receptor-associated patterns in post-contrast T1-weighted MRI of BCBMs. Accuracy was modest relative to published radiomics models, and the mask-free, single-sequence design is offered as a methodological contribution rather than a performance gain. These findings are preliminary, do not establish clinical utility, and require validation in larger, multi-center cohorts.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 12 matches between paragraphs and lines of code.
Const1357/BCBM-RadioGenomics-Classifier
1cb49ae9e60c5cb0a20df239a3ada88d704eb119, 30 January 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
17 files
- src/
Trainer.py , Python, 505 lines, 2 matches - src/
ensemble.py , Python, 380 lines - src/
ensemble_analysis.py , Python, 170 lines - src/
main.py , Python, 105 lines, 2 matches - src/
model_definitions/ , Python, 233 lines, 3 matchesResNet.py - src/
model_definitions/ , Python, 222 lines, 1 matchUNet.py - src/
utils/ , Python, 104 lines, 1 matchCalibrator.py - src/
utils/ , Python, 83 linesLogisticRegressionCalibr ator.py - src/
utils/ , Python, 63 linesMRIDataset.py - src/
utils/ , Python, 84 lines, 1 matchTemperatureCalibrator.py - src/
utils/ , Python, 28 linesconstants.py - src/
utils/ , Python, 60 linesdata_split.py - src/
utils/ , Python, 111 lines, 1 matchlosses.py - src/
utils/ , Python, 281 linesprocess_data.py - src/
utils/ , Python, 277 linesprocess_rest_data.py - src/
utils/ , Python, 235 lines, 1 matchtransformations.py - README.md, Text, 6 lines
3.2.5. Code Availability
All code supporting the findings of this study is openly accessible at the following GitHub repository: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 16 scripts, each with its path and the digest of its content;
- 12 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Data Availability Statement
Publicly available datasets were analyzed in this study. The imaging and clinical data are available from The Cancer Imaging Archive Breast Cancer Brain Metastases Radiogenomics dataset: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 8 authors, 8 keywords, 1 funder, 29 references.
Cite
This paper
Christodoulou, R. C., Christofi, G., Theofylaktou, C., Pitsillos, R., Aristokleous, I., Solomou, E. E., Vassiliou, E., & Georgiou, M. F. (2026). Saliency-Curated Deep Learning for Predicting Receptor Status in Breast Cancer Brain Metastases. Journal of clinical medicine, 15(17), 6501. https://
BibTeX
@article{christodoulou20
author = {Christodoulou, Rafail C. and Christofi, Giorgos and Theofylaktou, Constantinos and Pitsillos, Rafael and Aristokleous, Iliana and Solomou, Elena E. and Vassiliou, Evros and Georgiou, Michalis F.},
title = {{Saliency-Curated Deep Learning for Predicting Receptor Status in Breast Cancer Brain Metastases}},
journal = {Journal of clinical medicine},
year = {2026},
month = aug,
volume = {15},
number = {17},
pages = {6501},
publisher = {Multidisciplinary Digital Publishing Institute (MDPI)},
issn = {2077-0383},
doi = {10.3390/
url = {https://
pmid = {42739512},
pmcid = {PMC13566852}
}
RIS
TY - JOUR
AU - Christodoulou, Rafail C.
AU - Christofi, Giorgos
AU - Theofylaktou, Constantinos
AU - Pitsillos, Rafael
AU - Aristokleous, Iliana
AU - Solomou, Elena E.
AU - Vassiliou, Evros
AU - Georgiou, Michalis F.
TI - Saliency-Curated Deep Learning for Predicting Receptor Status in Breast Cancer Brain Metastases
T2 - Journal of clinical medicine
J2 - J Clin Med
PY - 2026
DA - 2026/
VL - 15
IS - 17
SP - 6501
SN - 2077-0383
PB - Multidisciplinary Digital Publishing Institute (MDPI)
DO - 10.3390/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.3390/
"type": "article-journal",
"title": "Saliency-Curated Deep Learning for Predicting Receptor Status in Breast Cancer Brain Metastases",
"container-title": "Journal of clinical medicine",
"author": [
{
"family": "Christodoulou",
"given": "Rafail C."
},
{
"family": "Christofi",
"given": "Giorgos"
},
{
"family": "Theofylaktou",
"given": "Constantinos"
},
{
"family": "Pitsillos",
"given": "Rafael"
},
{
"family": "Aristokleous",
"given": "Iliana"
},
{
"family": "Solomou",
"given": "Elena E."
},
{
"family": "Vassiliou",
"given": "Evros"
},
{
"family": "Georgiou",
"given": "Michalis F."
}
],
"container-title-short":
"volume": "15",
"issue": "17",
"page": "6501",
"DOI": "10.3390/
"PMID": "42739512",
"PMCID": "PMC13566852",
"ISSN": "2077-0383",
"publisher": "Multidisciplinary Digital Publishing Institute (MDPI)",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
22
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.3389/fonc.2026.1816015 [code]
- Modality-level attribution and redundancy-aware radiomics for MRI-based differentiation of melanoma and NSCLC brain metastases.Journal: Frontiers in oncologyIn common: SimpleITK, NiBabel, seaborn, 5 other tools, structural MRI / diffusion, other condition, 2 references
- [2] doi:10.1186/s12880-026-02335-x [code]
- Automatic lateral ventricle and choroid plexus segmentation method in infant brain MR images.Journal: BMC medical imagingIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion, 1 reference
- [3] doi:10.3389/frai.2026.1771088 [code]
- Few-shot deployment of pretrained MRI transformers in brain imaging tasks.Journal: Frontiers in artificial intelligenceIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion, 1 reference
- [4] doi:10.1002/alz.71649 [code]
- Postmortem brain MRI reveals differential associations of subcortical and limbic volumes with cortical thinning and neurodegenerative pathologies.Journal: Alzheimer's & dementia : the journal of the Alzheimer's AssociationIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion, other condition, cellular / molecular
- [5] doi:10.21037/qims-2026-0792 [code]
- An nnU-Net-based framework with adaptive feature representation for 3D brain tumor segmentation.Journal: Quantitative imaging in medicine and surgeryIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion, other condition
- [6] doi:10.1002/hipo.70124 [code]
- Association Between Anterior Hippocampal Gyrification and Episodic Memory Performance in Neurotypical Young Adults.Journal: HippocampusIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion
- [7] doi:10.1371/journal.pcbi.1014555 [code]
- Body surface potential driven personalisation of electrophysiological digital twins in hypertrophic cardiomyopathy.Journal: PLoS computational biologyIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion
- [8] doi:10.64898/2026.07.15.26357954 [code]
- Portable Ultra-Low Field MRI Deep-Learning Algorithms for White Matter Lesion Segmentation Improve Accuracy and Reflect Clinical Disability in Multiple SclerosisJournal: medRxiv (preprint)In common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion
- [9] doi:10.1136/jnnp-2025-335884 [code]
- Diffusivity anisotropy signature of slowly expanding lesions predicts progression independent of relapse activity in multiple sclerosis.Journal: Journal of neurology, neurosurgery, and psychiatryIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion
- [10] doi:10.3389/fmed.2026.1875760 [code]
- Adaptive multi-stage domain unlearning for white-matter lesion segmentation.Journal: Frontiers in medicineIn common: SimpleITK, NiBabel, PyTorch, 6 other tools, structural MRI / diffusion
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 16 scripts, and 12 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:13a70f1ea4f51113…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
