Skip to content

Commit f5de7f4

Browse files
authored
Merge pull request #13 from funkelab/dev
Documentation update
2 parents 84fa00a + 338d9eb commit f5de7f4

28 files changed

+711
-175
lines changed

.github/workflows/tests.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ jobs:
2222
pip install ".[dev]"
2323
- name: Test with pytest
2424
run: |
25-
pytest tests
25+
pytest tests

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
**/wandb
55
docs/build
66
docs/_build
7+
8+
# pixi environments
9+
.pixi
10+
*.egg-info

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
[![tests](https://github.com/funkelab/quac/actions/workflows/tests.yaml/badge.svg)](https://github.com/funkelab/quac/actions/workflows/tests.yaml)
44
[![documentation](https://github.com/funkelab/quac/actions/workflows/deploy-docs.yaml/badge.svg)](https://github.com/funkelab/quac/actions/workflows/deploy-docs.yaml)
5+
[![DOI:10.1101/2024.11.26.625505](http://img.shields.io/badge/DOI-10.1101/2024.11.26.625505-B31B1B.svg)](https://doi.org/10.1101/2024.11.26.625505)
56

7+
Pre-print can be found on [bioRxiv](https://www.biorxiv.org/content/10.1101/2021.01.08.425840v1)
68
Documentation can be found [here](https://funkelab.github.io/quac/).
79

810
<img src="docs/source/assets/overview.png" />

docs/source/assets/fictus.png

808 KB
Loading

docs/source/assets/synapses.png

773 KB
Loading

docs/source/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"sphinx_togglebutton",
3636
"sphinxcontrib.jquery",
3737
"sphinx.ext.intersphinx",
38+
"sphinxcontrib.email",
3839
]
3940

4041
templates_path = ["_templates"]
@@ -63,3 +64,6 @@
6364
"networkx": ("https://networkx.org/documentation/stable/", None),
6465
"numpy": ("https://numpy.org/doc/stable/", None),
6566
}
67+
68+
# Email
69+
email_automode = True

docs/source/examples.rst

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
===============
2+
Example gallery
3+
===============
4+
5+
Here are some examples of datasets that have been investigated with QuAC, as well as what was found.
6+
If you have tried QuAC on your own dataset (even unsuccessfully!) please :email:`let us know <[email protected]>` so we can add it to the gallery.
7+
8+
9+
*Fictus Aggregatum* synthetic cells
10+
====================================
11+
12+
The *Fictus aggregatum* dataset is a synthetic dataset that was created in the `Funke Lab <https://www.janelia.org/lab/funke-lab>`_ specifically to understand how QuAC works on biological data.
13+
The code to generate this dataset is available `here <https://github.com/funkelab/fictus.aggregatum>`_.
14+
15+
.. figure:: assets/fictus.png
16+
:figwidth: 100%
17+
:alt: Fictus aggregatum
18+
:align: center
19+
20+
An example of the query (top) and counterfactual (bottom) images, highlighting the differences.
21+
22+
We evaluated, using this *fictus* dataset, whether QuAC was able to retrieve all of the differences between classes when these are known.
23+
We found that, although this was sometimes done in surprising ways, the changes described by QuAC were generally in line with what was expected from the data.
24+
25+
26+
*Drosophila melanogaster* synapses
27+
==================================
28+
29+
The differences between synapses emitting different neurotransmitters in the fruit fly *Drosophila melanogaster* are so subtle that it was not though possible to tell them apart.
30+
When `it was found that a deep learning model could do so <https://www.cell.com/cell/fulltext/S0092-8674(24)00307-6>`_, however, this opened up possibilities for gaining insight into the relation between strcuture and function in these synapses.
31+
32+
.. figure:: assets/synapses.png
33+
:figwidth: 100%
34+
:alt: Synapses in EM
35+
:align: center
36+
37+
A few examples of synapses in the *Drosophila* brain, as seen in electron microscopy, translated from one class to another.
38+
39+
QuAC explanations suggested quite a few new features that could be used to distinguish between these synapse types, the prevalence of which is currently being investigated.
40+
41+
42+
Fly identity
43+
============
44+
45+
.. |simon says| image:: assets/quac.png
46+
:width: 50
47+
48+
.. attention::
49+
This dataset is still under construction. Come back soon for updates! |simon says|

docs/source/index.rst

+18-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,26 @@
33
Quantitative Attributions with Counterfactuals
44
==============================================
55

6-
Description of QuAC
6+
.. attention::
7+
Check out the new pre-print on biorxiv: `Quantitative Attributions with Counterfactuals <https://doi.org/10.1101/2024.11.26.625505>`_!
8+
9+
10+
.. image:: assets/overview.png
11+
:width: 800
12+
:align: center
13+
14+
QuAC is a tool for understanding the sometimes subtle differences between classes of images, by questioning a classifier's decisions.
15+
The method generates counterfactual images: making slight changes in an image to change its clasification.
16+
The counterfactuals in QuAC have localized changes, and are quantitatively scored to determine how well they describe the classifier's decision.
17+
18+
Get started with :doc:`installation </install>`, then check out the :doc:`tutorials <tutorials>` to run each step of the QuAC pipeline on an example dataset.
19+
20+
Unsure whether QuAC is right for your dataset? Check out the :doc:`examples </examples>` to see how it has been used already!
21+
722

823
.. toctree::
924
:maxdepth: 2
1025

1126
install
12-
tutorials
27+
examples
28+
Tutorials <tutorials>

docs/source/install.rst

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
.. _install:
2+
3+
============
14
Installation
25
============
36

47
Installing:
8+
59
1. Clone this repository
610
2. Create a `conda` environment with `python, pytorch, torchvision`; I recommend `mamba`
711
3. Activate your new environment (`mamba activate ...`)
812
4. Change into the directory holding this repository.
913
5. `pip install .`
1014

1115
Installing as developper:
12-
1. - 4. Same as above.
13-
5. `pip install -e .\[dev\]`
16+
17+
1. Do items 1 through 4 the same as above.
18+
2. `pip install -e .\[dev\]`

docs/source/tutorials.rst

+54-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,60 @@
1-
Tutorials
1+
================================
2+
So you've decided to use QuAC...
3+
================================
4+
5+
Great! In these tutorials we'll go through the process of setting up QuAC for your images.
6+
We built QuAC with biological images in mind, so those will be our analogies here. However, you're very welcome to use QuAC with any kind of image data!
7+
If you're interested in using it with non-image data, please :email:`contact us <[email protected]>`.
8+
9+
But first, a quick overview of the method.
10+
11+
What even is QuAC?
212
==================
13+
QuAC, or Quantitative Attributions with Counterfactuals, is a method for generating and scoring visual counterfactual explanations of an image clasifier.
14+
Let's assume, for instance, that you have images of cells grown in two different conditions.
15+
To your eye, the phenotypic difference between the two conditions is hidden within the cell-to-cell variability of the dataset, but you know it is there because you've trained a classifier to differentiate the two conditions and it works. So how do you pull out the differences?
16+
17+
We begin by training a generative neural network to convert your images from one class to another. Here, we'll use a StarGAN. This allows us to go from our real, **query** image, to our **generated** image.
18+
Using information learned from **reference** images, the StarGAN is trained in such a way that the **generated** image will have a different class!
19+
20+
While very powerful, these generative networks *can potentially* make some changes that are not necessary to the classification.
21+
In our example below, the **generated** image's membrane has been unnecessarily changed.
22+
We use Discriminative Attribution methods to generate a set of candidate attribution masks.
23+
Among these, we are looking for the smallest mask that has the greatest change in the classification output.
24+
By taking only the changes *within* that mask, we create the counterfactual image.
25+
It is as close as possible to the original image, with only the necessary changes to turn its class!
26+
27+
.. image:: assets/overview.png
28+
:width: 800
29+
:align: center
30+
31+
Before you begin, download [the data]() and [the pre-trained models]() for an example.
32+
Then, make sure you've installed QuAC by following the :doc:`Installation guide <install>`.
333

434

35+
The conversion network
36+
===============================
37+
38+
You have two options for training the StarGAN, you can either :doc:`define parameters directly in Python <tutorials/train>` or :doc:`train it using a YAML file <tutorials/train_yaml>`.
39+
We recommend the latter, which will make it easier to keep track of your experiments!
40+
Once you've trained a decent model, generate a set of images using the :doc:`image generation tutorial <tutorials/generate>` before moving on to the next steps.
41+
542
.. toctree::
6-
:maxdepth: 2
43+
:maxdepth: 1
744

845
tutorials/train
9-
tutorials/attribute
10-
tutorials/generate
46+
tutorials/train_yaml
47+
Generating images <tutorials/generate>
48+
49+
Attribution and evaluation
50+
==========================
51+
52+
With the generated images in hand, we can now run the attribution and evaluation steps.
53+
These two steps allow us to overcome the limitations of the generative network to create *truly* minimal counterfactual images, and to score the query-counterfactual pairs based on how well they explain the classifier.
54+
55+
.. toctree::
56+
:maxdepth: 1
57+
58+
Attribution <tutorials/attribute>
59+
Evaluation <tutorials/evaluate>
60+
Visualizing results <tutorials/visualize>

docs/source/tutorials/attribute.rst

+58-54
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,97 @@
11
.. _sec_attribute:
22

3-
================================================
4-
Attribution and evaluation given counterfactuals
5-
================================================
3+
===============================================
4+
Discriminative attribution from Counterfactuals
5+
===============================================
66

7-
Attribution
8-
===========
7+
Now that we have generated counterfactuals, we will refine our **generated** images into **counterfactuals** using discriminative attribution.
8+
Remember that although the conversion network is trained to keep as much of the image fixed as possible, it is not perfect.
9+
This means that there may still be regions of the **generated** image that differ from the **query** image *even if they don't need to*.
10+
Luckily, we have a classifier that can help us identify and keep only the necessary regions of change.
11+
12+
The first thing that we want to do is load the classifier.
913

1014
.. code-block:: python
1115
:linenos:
1216
13-
# Load the classifier
17+
classifier_checkpoint = "path/to/classifier/checkpoint"
18+
1419
from quac.generate import load_classifier
1520
classifier = load_classifier(
16-
21+
checkpoint_path=classifier_checkpoint
1722
)
1823
24+
Next, we will define the attribution that we want to use.
25+
In this tutorial, we will use Discriminative Integrated Gradients, using the classifier as a baseline.
26+
As a comparison, we will also use Vanilla Integrated Gradients, which uses a black image as a baseline.
27+
This will allow us to identify the regions of the image that are most important for the classifier to make its decision.
28+
Later in the :doc:`evaluation <evaluate>` tutorial, we will process these attributions into masks, and finally get our counterfactuals.
29+
30+
31+
.. code-block:: python
32+
:linenos:
33+
34+
# Parameters
35+
attribution_directory = "path/to/store/attributions"
36+
1937
# Defining attributions
2038
from quac.attribution import (
21-
DDeepLift,
2239
DIntegratedGradients,
40+
VanillaIntegratedGradients,
2341
AttributionIO
2442
)
2543
from torchvision import transforms
2644
2745
attributor = AttributionIO(
2846
attributions = {
29-
"deeplift" : DDeepLift(),
30-
"ig" : DIntegratedGradients()
47+
"discriminative_ig" : DIntegratedGradients(classifier),
48+
"vanilla_ig" : VanillaIntegratedGradients(classifier)
3149
},
32-
output_directory = "my_attributions_directory"
50+
output_directory = atttribution_directory
3351
)
3452
53+
54+
Finally, we want to make sure that the images are processed as we would like for the classifier.
55+
Here, we will simply define a set of `torchvision` transforms to do this, we will pass them to the `attributor` object.
56+
Keep in mind that if you processed your data in a certain way when training your classfier, you will need to use the same processing here.
57+
58+
.. code-block:: python
59+
:linenos:
60+
3561
transform = transforms.Compose(
3662
[
37-
transforms.Resize(224),
38-
transforms.CenterCrop(224),
39-
transforms.Normalize(...)
63+
transforms.ToTensor(),
64+
transforms.Grayscale(),
65+
transforms.Resize(128),
66+
transforms.Normalize(0.5, 0.5),
4067
]
4168
)
4269
43-
# This will run attributions and store all of the results in the output_directory
44-
# Shows a progress bar
45-
attributor.run(
46-
source_directory="my_source_image_directory",
47-
counterfactual_directory="my_counterfactual_image_directory",
48-
transform=transform
49-
)
50-
51-
Evaluation
52-
==========
53-
54-
Once you have attributions, you can run evaluations.
55-
You may want to try different methods for thresholding and smoothing the attributions to get masks.
56-
57-
58-
In this example, we evaluate the results from the DeepLift attribution method.
70+
Finally, let's run the attributions.
5971

6072
.. code-block:: python
6173
:linenos:
6274
63-
# Defining processors and evaluators
64-
from quac.evaluation import Processor, Evaluator
65-
from sklearn.metrics import ConfusionMatrixDisplay
75+
data_directory = "path/to/data/directory"
76+
counterfactual_directory = "path/to/counterfactual/directory"
6677
67-
classifier = load_classifier(...)
68-
69-
evaluator = Evaluator(
70-
classifier,
71-
source_directory="my_source_image_directory",
72-
counterfactual_directory="my_counterfactual_image_directory",
73-
attribution_directory="my_attributions_directory/deeplift",
78+
# This will run attributions and store all of the results in the output_directory
79+
# Shows a progress bar
80+
attributor.run(
81+
source_directory=data_directory,
82+
counterfactual_directory=counterfactual_directory,
7483
transform=transform
7584
)
7685
86+
If you look into the `attribution_directory`, you should see a set of attributions.
87+
They will be organized in the following way:
7788

78-
cf_confusion_matrix = evaluator.classification_report(
79-
data="counterfactuals", # this is the default
80-
return_classifications=False,
81-
print_report=True,
82-
)
89+
.. code-block:: bash
8390
84-
# Plot the confusion matrix
85-
disp = ConfusionMatrixDisplay(
86-
confusion_matrix=cf_confusion_matrix,
87-
)
88-
disp.show()
91+
attribution_directory/
92+
attribution_method_name/
93+
source_class/
94+
target_class/
95+
image_name.npy
8996
90-
# Run QuAC evaluation on your attribution and store a report
91-
report = evaluator.quantify(processor=Processor())
92-
# The report will be stored based on the processor's name, which is "default" by default
93-
report.store("my_attributions_directory/deeplift/reports")
97+
In the next tutorial, we will use these attributions to generate masks and finally get our counterfactuals.

0 commit comments

Comments
 (0)