# Breast Ultrasound Lesion Analysis

Alonso Jiménez Flores

A pipeline for **benign/malignant classification and index-lesion segmentation** in breast ultrasound. Two independently trained networks accept a complete image: a ResNet18 classifier returns a malignancy probability, and a U-Net with a ResNet34 encoder returns a native-resolution mask and its largest-component box. A static website presents methods, results and an image explorer. This is a research and educational project.

[Project website](https://chuckinvictus.github.io/breast-ultrasound-analysis/) · [Results](https://chuckinvictus.github.io/breast-ultrasound-analysis/results.html) · [Image explorer](https://chuckinvictus.github.io/breast-ultrasound-analysis/explorer.html)

## Data and experimental design

BUS-BRA supplies 1,875 images from 1,064 patient cases, with diagnosis and expert masks. The diagnosis-stratified split is patient-grouped: 744 training, 160 validation and 160 test cases, seed 2026. Original validation columns share patient views with training; this project uses its own audited split. Complete images are inputs. Labels, expert masks, BI-RADS and filenames are not predictor channels.

Five candidate configurations compare 224/384-pixel ResNet18 classification, 224/384-pixel ResNet18 U-Net segmentation and 384-pixel ResNet34 U-Net segmentation. Selection uses validation case AP for classification and native-resolution case Dice for segmentation. Both selected configurations are repeated with seeds 29 and 43 in addition to 17, giving nine neural fits. Baselines are training prevalence, a mean spatial mask, and frozen ImageNet features with logistic regression. BrEaST contributes 252 lesions for a second-cohort comparison and four normal images analyzed individually.

## Installation

Run from the repository root with **Python 3.12** on Linux:

```bash
bash scripts/bootstrap.sh
source .venv/bin/activate
```

The executed environment uses PyTorch 2.10.0+cu128, TorchVision 0.25.0+cu128 and an RTX 3070 Laptop with 8 GB VRAM. CUDA wheels include the runtime; a working NVIDIA driver is required for GPU training. `requirements.lock` pins the tested direct and transitive versions. The editable installation connects the commands to `src`.

For CPU inference or development tests:

```bash
python3 -m venv .venv
.venv/bin/python -m pip install torch==2.10.0 torchvision==0.25.0 \
  --index-url https://download.pytorch.org/whl/cpu
.venv/bin/python -m pip install -e '.[dev]'
source .venv/bin/activate
```

Use `predict --device cpu` for inference. To train on CPU, copy the YAML and set `device: cpu`. The CUDA lock describes the reported training environment; the CPU installation keeps direct versions fixed but resolves its own transitive dependencies.

## Reproduce the pipeline

```bash
breast-us download
breast-us prepare
breast-us audit
breast-us split
breast-us pilot
breast-us reproduce --skip-data
breast-us export-web
python3 -m http.server 8773 --bind 127.0.0.1 --directory web
```

Open [the project website](http://127.0.0.1:8773/index.html). `reproduce` also performs the data stages when `--skip-data` is omitted. Downloads are pinned and checksum-verified. The split command refuses pending duplicate reviews; the supplied audit has no candidates at its documented threshold. The pilot overfits eight training images to check both optimization paths. Data and ImageNet weight downloads require Internet access.

`reproduce` fits all five candidates, saves a validation-only `artifacts/selection.json`, repeats the selected models, fits baselines, evaluates the selected runs, and generates the numerical report and static article. It never selects a model by test performance. Generated weights, native masks and full image collections are excluded from Git; reproducible numerical summaries and case predictions are retained under `reports`.

To resume an existing run:

```bash
breast-us reproduce --skip-data --resume
```

Resume restores optimizer, cosine scheduler, AMP scaler, RNGs, loader generators and early-stop state at an epoch boundary. Configurations and manifest/split hashes must match. Completed runs are reused. Baselines, evaluation and reports are regenerated. Without `--resume`, existing neural training artifacts are rejected rather than overwritten. For a separate repetition, copy the YAML, change `artifacts_dir` and `reports_dir`, and pass `--config` before the subcommand.

## Training and image-only inference

```bash
breast-us train --model classification_384 --seed 17
breast-us train --model segmentation_resnet34_384 --seed 17
breast-us baselines
breast-us report

# Use the validation-selected task model, seed 17 by default.
breast-us predict --task classification \
  --image data/raw/busbra/BUSBRA/Images/bus_0001-l.png \
  --output artifacts/example/classification
breast-us predict --task segmentation \
  --image data/raw/busbra/BUSBRA/Images/bus_0001-l.png \
  --output artifacts/example/segmentation

# A specific checkpoint can also be supplied.
breast-us evaluate --checkpoint artifacts/classification_384/seed_17/best.pt
breast-us predict --task segmentation --device cpu \
  --image path/to/image.png --output artifacts/local_image
```

`--task` reads the saved selection file; it does not select again. `--checkpoint` is an alternative for explicit weights. `predict` requires only an image. Classification saves the original **single-image** probability in `prediction.json`; it is not a complete case score when additional views exist. Segmentation saves a native-resolution `mask.png`, exclusive-maximum box coordinates, threshold and source/checkpoint checksums. Unknown images do not acquire an expert diagnosis or an evaluation score.

When individual training runs already exist, use `--resume` or a separate output directory. `report` requires all selected seeds and baselines to have been evaluated. The example `evaluate` path addresses an explicit candidate; the selected names and checkpoints are recorded in `selection.json`.

## Results

<!-- RESULTS_START -->
Selected models: `classification_224` and `segmentation_resnet34_384`, using validation case AP and native case Dice respectively. Neural values are mean ± sample standard deviation over all three seeds; baselines have one run. BUS-BRA testing has 160 cases.

| Model | BUS-BRA AUROC | AP | Dice | IoU |
| --- | ---: | ---: | ---: | ---: |
| Prevalence / mean mask | 0.500 | 0.325 | 0.260 | 0.164 |
| Frozen ResNet18 + logistic regression | 0.777 | 0.693 | — | — |
| ResNet18 classifier · 224 px | 0.903 ± 0.016 | 0.865 ± 0.017 | — | — |
| U-Net / ResNet34 · 384 px | — | — | 0.900 ± 0.002 | 0.830 ± 0.003 |

BrEaST comparison: classifier AUROC 0.847 ± 0.013, AP 0.779 ± 0.023; segmenter Dice 0.735 ± 0.012. Full per-seed results and intervals are in [reports/RESULTS.md](analysis.md).
<!-- RESULTS_END -->

Primary classification metrics use case-mean probabilities. The report includes AP, AUROC, thresholded decisions, confusion matrices, calibration and Brier scores. Segmentation is scored on restored native masks and averaged within cases; Dice, IoU, lower-tail performance and mask-derived box localization are retained. Thresholds and temperature calibration use validation only. Patient bootstrap intervals and training-seed variation are reported separately.

[Results and interpretation](interpretation.md) describes what the models do well and where they fail. [The generated report](analysis.md) contains all selected seeds, patient intervals, paired baseline differences, subgroups and four individual normal-case observations. [Structured results](results.json) and [configuration selection](selection.json) allow numerical inspection without model weights.

## Image explorer

The [explorer](http://127.0.0.1:8773/explorer.html) displays every saved validation/test inference image, plus exported standalone predictions. Choose an image collection and case to see the image alongside its dataset diagnosis, model classification and segmentation overlap. Switch between the original and outlined image, or enable the expert reference. Filters expose classification errors and low-Dice images; model fits, comparison and further display settings are available in expandable sections. The workspace adapts to desktop, tablet and phone screens.

Zoom, opacity and brightness/contrast are display controls. The dark theme never inverts medical-image pixels. Original PNGs, annotated native-size images and a JSON record can be downloaded. Case probabilities and image-level overlap scores retain their distinct units. The viewer reads local saved outputs, with no inference service, uploads or remote analytics. Details and dataset attribution are in [web/README.md](website-instructions.md).

## Repository and checks

- `src/breast_us`: data adapters, auditing, splits, transformations, independent models, training, baselines, inference, metrics, reports and web export.
- `configs/default.yaml`: explicit candidates, data paths, seeds and optimizer/augmentation settings.
- `data/processed`: manifests, immutable split lists, checksums and audit records.
- `artifacts/<candidate>/seed_<seed>`: checkpoints, configurations, source hashes, training history and evaluation outputs; generated locally.
- `reports/runs`: shareable per-case predictions, metrics, policies and run provenance.
- `web`: static HTML/CSS/JavaScript articles and native-image explorer.
- `tests`: patient separation, annotation-independent inference, native geometry, metrics, model selection, checkpoint resume and export integrity.

```bash
pytest -q
ruff check src tests
ruff format --check src tests
breast-us verify
```

Training records the environment, manifest/split checksums and training-source SHA-256 values. `verify` reevaluates all selected checkpoints and refits baselines in a temporary output tree, comparing case/image probabilities and native mask bytes with the saved outputs. It records both the training-time and current source hashes, environment and test output in `reports/verification.json`. Data replay is retained in `reports/data_verification.json`. Verification preserves the original predictions and does not repeat neural training. Exact numerical identity is checked in the executed environment; different hardware or packages can change floating-point results. The lock fixes versions rather than wheel hashes.

GitHub Actions runs CPU tests, lint, CLI and JavaScript syntax checks without downloading medical images or model weights. Changes to the pipeline should retain the patient-separation and image-only inference tests. Published metrics can be checked against the case CSVs independently of the checkpoints.

The checked-in source, documentation, cohort manifests and numerical reports total about 4 MB. Raw dataset archives, checkpoints, full prediction masks and caches are excluded from Git. The published explorer collection is a separate [release asset](https://github.com/chuckinvictus/breast-ultrasound-analysis/releases/tag/explorer-2026-10-18), including public-dataset images, saved binary predictions and license notices. To populate the explorer after a fresh checkout, download that snapshot as described in [web/README.md](website-instructions.md), or run the pipeline and `export-web`. Model weights are not distributed in this repository.

## Limitations and sources

The data contain selected, already visible lesions. These results do not establish screening performance, exhaustive detection or clinical validity. One patient split and three seeds leave split/selection variability unresolved. Resizing, annotation disagreement and acquisition artifacts can affect results. BrEaST scores describe transfer under its released case composition; differences in equipment, prevalence and verification cannot be separated here. Further patient-grouped cross-validation is the next research step.

[Methods](methods.md) specify the current training and evaluation rules. [Data documentation](data.md) covers provenance, licenses, annotation contracts and audits. [Primary-source review](references.md) supports the data and model choices. The split, decoder widths, input sizes, loss weights and optimization settings are engineering choices; the project does not claim a novel architecture or the best published scores.

Required data citations: Gómez-Flores et al., BUS-BRA, [Medical Physics, 2024](https://doi.org/10.1002/mp.16812); Pawłowska et al., BrEaST, [Scientific Data, 2024](https://doi.org/10.1038/s41597-024-02984-z). ResNet [CVPR 2016](https://openaccess.thecvf.com/content_cvpr_2016/html/He_Deep_Residual_Learning_CVPR_2016_paper.html), U-Net [MICCAI 2015](https://arxiv.org/abs/1505.04597), CLAIM [2024 update](https://doi.org/10.1148/ryai.240300), and [Metrics Reloaded](https://doi.org/10.1038/s41592-023-02151-z) inform the implementation and reporting. Code uses the [MIT license](CODE_LICENSE.txt); dataset and pretrained-weight rights remain separate. Original notices: [BUS-BRA](BUSBRA_LICENSE.txt) and [BrEaST](BREAST_LICENSE.txt). Software citation metadata are in [CITATION.cff](CITATION.cff).
