Skip to content

Commit 3077694

Browse files
committed
Initial commit
0 parents  commit 3077694

187 files changed

Lines changed: 22065 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3+
4+
name: Python application
5+
6+
on:
7+
push:
8+
branches: [ "main" ]
9+
pull_request:
10+
branches: [ "main" ]
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
test:
17+
runs-on: ubuntu-latest
18+
strategy:
19+
matrix:
20+
python-version: ["3.10"]
21+
steps:
22+
- uses: actions/checkout@v4
23+
- name: Install the latest version of uv and set the python version
24+
uses: astral-sh/setup-uv@v5
25+
with:
26+
python-version: ${{ matrix.python-version }}
27+
enable-cache: false
28+
- name: Install dependencies
29+
run: uv pip install ".[dev]"
30+
- name: Loggin wandb
31+
shell: bash
32+
run: wandb login "$(printf '%*s' 40 '' | tr ' ' 'X')"
33+
- name: Run tests
34+
run: pytest

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
__pycache__/
2+
*.py[cod]
3+
*.out

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
[![Python application](https://github.com/PierreMarza/fmbench2dev/actions/workflows/ci.yml/badge.svg)](https://github.com/PierreMarza/fmbench2dev/actions/workflows/ci.yml)
2+
3+
# Tile-level Histopathology image Understanding benchmark
4+
5+
<img src="docs/banner.svg" />
6+
7+
We introduce **THUNDER**, a comprehensive benchmark designed to rigorously compare foundation models across various downstream tasks in computational pathology. THUNDER enables the evaluation and analysis of feature representations, robustness, and uncertainty quantification of these models across different datasets. Our benchmark encompasses a diverse collection of well-established datasets, covering multiple cancer types, image magnifications, and varying image and sample sizes. We propose an extensive set of tasks aimed at thoroughly assessing the capabilities and limitations of foundation models in digital pathology.
8+
9+
10+
## Overview
11+
12+
We propose a benchmark to compare and study foundation models across three axes: (i) downstream task performance, (ii) feature space comparisons, and (iii) uncertainty and robustness. Our current version integrates 23 foundation models, vision-only, vision-language, trained on pathology or natural images, on 16 datasets covering different magnifications and organs. THUNDER also supports the use of new user-defined models for direct comparisons.
13+
14+
<img src="docs/overview.svg" />
15+
16+
17+
## Usage
18+
19+
An API and command line interface (CLI) are provided to allow users to download datasets, models, and run benchmarks. The API is designed to be user-friendly and allows for easy integration into existing workflows. The CLI provides a convenient way to access the same functionality from the command line.
20+
21+
> [!IMPORTANT]
22+
> **Downloading supported foundation models**: you will have to visit the Huggingface URL of supported models you wish to use in order to accept usage conditions.
23+
24+
### API Usage
25+
When using the API you can run the following code to download datasets, models and run a benchmark:
26+
27+
```python
28+
from thunder import benchmark
29+
30+
benchmark("phikon", "break_his", "knn")
31+
```
32+
33+
### CLI Usage
34+
When using the CLI you can run the following command to see all available options,
35+
36+
```console
37+
thunder --help
38+
```
39+
40+
In order to reproduce the above example you can run the following command:
41+
42+
```console
43+
thunder benchmark phikon break_his knn
44+
```
45+
46+
## Installing thunder
47+
48+
Code tested with Python 3.10. To replicate, you can create the following conda environment and activate it,
49+
```console
50+
conda create -n thunder_env python=3.10
51+
conda activate thunder_env
52+
```
53+
54+
To install `thunder` run the following command:
55+
56+
```console
57+
pip install -e . # install the package in editable mode
58+
pip install . # install the package
59+
```
60+
61+
Before running `thunder`, ensure that the environment variable `THUNDER_BASE_DATA_FOLDER` is defined. This variable specifies the path where outputs, foundation models, and datasets will be stored. You can set it by running:
62+
63+
```console
64+
export THUNDER_BASE_DATA_FOLDER="/path/to/your/data/folder"
65+
```
66+
67+
Replace `/path/to/your/data/folder` with your desired storage directory.

docs/api.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
::: thunder.benchmark.benchmark
2+
3+
::: thunder.download_datasets
4+
5+
::: thunder.download_models
6+
7+
::: thunder.generate_splits
8+
9+
::: thunder.models.PretrainedModel

docs/banner.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/custom_config.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
## Overriding config parameters
2+
3+
Default parameters are used for various aspects of the benchmark, e.g., the batch sizes, learning rates. These default parameters can be overriden using the following syntaxes for both CLI and API uses.
4+
5+
```bash
6+
thunder benchmark hiboub bach knn --task.pre_comp_emb_batch_size 123 \
7+
--task.k_vals "[1, 2, 3]"
8+
```
9+
10+
```python
11+
import thunder
12+
thunder.benchmark('hiboub',
13+
'bach',
14+
'knn',
15+
**{'task.pre_comp_emb_batch_size': 123, 'task.k_vals': [1, 2, 3]})
16+
```
17+
18+
## Overridable parameters
19+
Here is a non exhaustive list of the parameters that you may want to override per task, as well as the type and a small description.
20+
21+
### Frozen linear probing
22+
| Name | Type | Description |
23+
|------|---|---|
24+
| adaptation.batch_size | int | Batch size used for training. |
25+
| adaptation.num_workers | int | Number of workers for the data loader. |
26+
| adaptation.lr | list[int] | List of learning rates used for the grid search. |
27+
| adaptation.weight_decay | list[int] | List of weight decays used for the grid search. |
28+
| adaptation.epochs | int | Number of training epochs. |
29+
30+
31+
### LoRA linear probing
32+
| Name | Type | Description |
33+
|------|---|---|
34+
| adaptation.lora_rank | int | Rank for the LoRA adapter. |
35+
| adaptation.lora_alpha | int | Alpha parameter for LoRA. |
36+
| adaptation.batch_size | int | Batch size used for training. |
37+
| adaptation.num_workers | int | Number of workers for the data loader. |
38+
| adaptation.lr | list[int] | List of learning rates used for the grid search. |
39+
| adaptation.weight_decay | list[int] | List of weight decays used for the grid search. |
40+
| adaptation.epochs | int | Number of training epochs. |
41+
42+
### Adversarial attack
43+
| Name | Type | Description |
44+
|------|---|---|
45+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
46+
| task.attack_batch_size | int | Batch size for the attacks. |
47+
| task.nb_attack_images | int | Number of images to use. |
48+
| task.attack.eps | float | Radius of the norm ball. |
49+
| task.attack.alpha | float | Step size per PGD iteration. |
50+
| task.attack.n_steps | int | Number of PGD iterations. |
51+
52+
### Alignment scoring
53+
| Name | Type | Description |
54+
|------|---|---|
55+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
56+
57+
### Image retrieval
58+
| Name | Type | Description |
59+
|------|---|---|
60+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
61+
| task.k_vals | list[int] | Values of k to use. |
62+
63+
### K-nn
64+
| Name | Type | Description |
65+
|------|---|---|
66+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
67+
| task.k_vals | list[int] | Values of k to use. |
68+
69+
### Precomputing embeddings
70+
| Name | Type | Description |
71+
|------|---|---|
72+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
73+
74+
### Simple shot
75+
| Name | Type | Description |
76+
|------|---|---|
77+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
78+
79+
### Transformation invariance
80+
| Name | Type | Description |
81+
|------|---|---|
82+
| task.pre_comp_emb_batch_size | int | Batch size for precomputing the embeddings. |
83+
| task.nb_images | int | Number of images to use. |

docs/custom_model.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
You can use any custom model to run the benchmark by inheriting from the `thunder.models.PretrainedModel` class.
2+
3+
!!!note
4+
A few examples of such files described bellow can be found in the `examples` folder of the repository.
5+
6+
To do so you will need to prepare a `.py` with a class definition of your model that inherits from `thunder.models.PretrainedModel` and overrides the following methods:
7+
8+
- `get_transform`: This method should return a transform function that will be used to preprocess the input data. The transform function should take a single argument, which is the input data, and return the transformed data.
9+
- `get_linear_probing_embeddings`: This method should return the embeddings for the linear probing task. It should take a single argument, which is the input data, and return the embeddings (bs, emb_size).
10+
- `get_segmentation_embeddings`: This method should return the embeddings for the segmentation task. It should take a single argument, which is the input data, and return the embeddings (bs, tokens, emb_size).
11+
12+
Additionally two properties should be available in the class:
13+
14+
- `name`: This property should return the name of the model.
15+
- `emb_dim`: This property should return the embedding dimension of the model.
16+
17+
Here is an example of such a file:
18+
19+
```python
20+
# my_model.py
21+
from thunder.models import PretrainedModel
22+
23+
class DINOv2Features(PretrainedModel):
24+
def __init__(self):
25+
super().__init__()
26+
27+
import torch
28+
from torchvision import transforms
29+
30+
self.dinov2 = torch.hub.load("facebookresearch/dinov2", "dinov2_vits14")
31+
self.t = transforms.Compose(
32+
[
33+
transforms.ToTensor(),
34+
transforms.Resize((224, 224)),
35+
]
36+
)
37+
self.name = "dinov2_vits14"
38+
self.emb_dim = 384
39+
40+
def forward(self, x):
41+
feats = self.dinov2.forward_features(x)
42+
return feats
43+
44+
def get_transform(self):
45+
return self.t
46+
47+
def get_linear_probing_embeddings(self, x):
48+
x = self.dinov2.forward_features(x)
49+
return x["x_norm_clstoken"]
50+
51+
def get_segmentation_embeddings(self, x):
52+
x = self.dinov2.forward_features(x)
53+
return x['x_norm_patchtokens']
54+
```
55+
56+
With this file ready, you can run any benchmark task using the following command:
57+
58+
```console
59+
thunder benchmark custom:my_model.py db_name task_name
60+
```
61+
62+
or through the API:
63+
64+
```python
65+
from thunder import benchmark
66+
from my_model import DINOv2Features
67+
68+
if __name__ == "__main__":
69+
model = DINOv2Features()
70+
benchmark(model, dataset="ccrcc", task="linear_probing")
71+
```

docs/getting_started.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
## Installation
2+
3+
In order to use the package, you need to install it first. You can do this by running the following command in your terminal:
4+
5+
```console
6+
pip install thundr
7+
```
8+
9+
The package is storing all the datasets, models and results under a folder that you will need to define through the environment variable `THUNDER_BASE_DATA_FOLDER`. You can do this by running the following command in your terminal:
10+
```console
11+
export THUNDER_BASE_DATA_FOLDER=/path/to/thunder_base_data_folder
12+
```
13+
14+
!!!important
15+
Without this environment variable, the package will not work. The folder should be empty and the package will create the necessary subfolders.
16+
17+
## CLI Usage
18+
19+
You can run the following command to see all available options,
20+
```console
21+
> thunder --help
22+
Usage: thunder [OPTIONS] COMMAND [ARGS]...
23+
```
24+
25+
The available commands are:
26+
- `benchmark`: Benchmarks the models on the datasets for a task.
27+
- `download-datasets`: Downloads datasets.
28+
- `download-models`: Downloads models.
29+
- `generate-data-splits`: Generate data splits for the downloaded datasets.
30+
- `results-summary`: Compiles a summary csv file of the results.
31+
32+
33+
To benchmark the models, you can run the following command,
34+
```console
35+
> thunder benchmark --help
36+
Usage: thunder benchmark [OPTIONS] MODEL DATASET TASK
37+
> thunder benchmark phikon ccrcc knn
38+
```
39+
40+
In case you want to download a datasets, you can run the following command,
41+
```console
42+
> thunder download-datasets ccrcc patch_camelyon bach
43+
> thunder download-datasets classification
44+
> thunder download-datasets all --make_splits # Generates splits after downloading
45+
```
46+
47+
To download the models, you can run the following command,
48+
```console
49+
> thunder download-models phikon keep
50+
> thunder download-models dinov2base
51+
```
52+
53+
To generate splits for the downloaded, you can run the following command,
54+
```console
55+
> thunder generate-data-splits ccrcc patch_camelyon bach
56+
> thunder generate-data-splits classification
57+
> thunder generate-data-splits all
58+
```
59+
60+
## API Usage
61+
62+
You can also use the package as a library. For example, you can run the following code to download datasets,
63+
```python
64+
from thunder import download_datasets, download_models, generate_splits, benchmark
65+
66+
# Download datasets
67+
download_datasets(["ccrcc", "patch_camelyon", "bach"])
68+
download_datasets(["all"])
69+
download_datasets(["classification"])
70+
71+
# Download models
72+
download_models(["phikon", "dinov2base"])
73+
74+
# Generate data splits
75+
generate_splits(["all"])
76+
77+
# Benchmark
78+
benchmark(model="phikon", dataset="ccrcc", task="knn")
79+
```

0 commit comments

Comments
 (0)