Skip to content

Commit

Permalink
DOC: Adds Inigo's week 8&9 blogposts and adapts image paths to new de…
Browse files Browse the repository at this point in the history
…dicated folder

3 images from past posts had not been moved to the dedicated folder, so moved them
  • Loading branch information
itellaetxe committed Jul 29, 2024
1 parent 07172c6 commit ec20908
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 2 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions posts/2024/2024_07_06_Inigo_week_6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To provide a bit of intuition behind the VAE, let me illustrate first the "vanil

The objective of the AE is to minimize the difference between the input data and the generated data, also called the "reconstruction loss".

.. image:: /_static/images/inigo_vanilla_autoencoder.png
.. image:: /_static/images/gsoc/204/inigo/inigo_vanilla_autoencoder.png
:alt: Vanilla AutoEncoder diagram.
:width: 600

Expand All @@ -24,7 +24,7 @@ Usually the problem with AEs is that the latent space is full of "holes", i.e. i

The VAE does this by adding a "regularization loss" to the AE, which is the Kullback-Leibler divergence between the latent space distribution and a prior distribution (usually a normal distribution). If you are curious, you can find a nice explanation about the differences between AEs and VAEs `here <https://towardsdatascience.com/understanding-variational-autoencoders-vaes-f70510919f73>`_.

.. image:: /_static/images/inigo_variational_autoencoder.png
.. image:: /_static/images/gsoc/204/inigo/inigo_variational_autoencoder.png
:alt: Variational AutoEncoder diagram.
:width: 600

Expand Down
36 changes: 36 additions & 0 deletions posts/2024/2024_07_19_Inigo_week_8.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Week 8 into GSoC 2024: Further advances with the VAE model
==========================================================

.. post:: July 19 2024
:author: Iñigo Tellaetxe
:tags: google
:category: gsoc

What I did this week
~~~~~~~~~~~~~~~~~~~~

This week I continued training the VAE model with the FiberCup dataset, this time for 120 epochs, and the results are promising. The model is able to reconstruct the input data with a decent level of detail.

.. image:: /_static/images/gsoc/204/inigo/vanilla_vae_120_epoch_results.png
:alt: Vanilla Variational AutoEncoder reconstruction results after 120 epochs of training.
:width: 600

I also looked at the theoretical and technical implications of implementing the `beta-VAE architecture <https://openreview.net/forum?id=Sy2fzU9gl>`_ for my experiments, which could help in disentangling the latent space representation of the streamlines according to features learnt in an
unsupervised manner. Shortly, applying a weight (bigger than 1) to the KL loss component of the VAE loss function encourages the model to learn a version of the latent space where features that can be perceived in the data space are aligned with the latent space dimensions. This way,
one can modulate the generative process according to the learnt 'perceivable' features, once they are identified and located in the latent space.
However, increasing the beta weight compromises the reconstruction quality, which is what basically makes streamlines look reasonable. Finding a good beta weight is as 'simple' as running a hyperparameter search while constraining the parameter to be higher than one, and to try to prioritize
the MSE (Mean Squared Error, reconstruction loss) in the search algorithm. From the technical side implementing a beta-VAE is very straightforward, by just adding the beta weight in the loss equation and storing the parameter for traceability, so this did not take a lot of time.

What is coming up next week
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Next week I wanted to tinker around a bit with this parameter to see how it affects the quality of the reconstructions and the organization of the latent space, but I don't think this is an effective strategy, nor the priority. Thus, I will
start implementing the conditional VAE, which will allow me to generate new streamlines by conditioning the latent space with a specific continuous variable.
This is a bit more complex than the vanilla VAE, but I think I will be able to implement it on time because the main components are already there and I just need to add the conditioning part, based on this `paper <https://doi.org/10.1007/978-3-030-32245-8_91>`_.

Did I get stuck anywhere
~~~~~~~~~~~~~~~~~~~~~~~~

This week I haven't got stuck in any particular issue, because I was mainly focused on training the model and understanding the beta-VAE architecture.

Until next week!
53 changes: 53 additions & 0 deletions posts/2024/2024_07_26_Inigo_week_9.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Week 9 into GSoC 2024: The Conditional VAE implementation
=========================================================

.. post:: July 26 2024
:author: Iñigo Tellaetxe
:tags: google
:category: gsoc

What I did this week
~~~~~~~~~~~~~~~~~~~~

This week was a bit shorter than usual because Thursday was a holiday in the Basque Country, and today we had an outdoor activity with my lab mates (we went kayaking to the Urdaibai Biosphere Reserve). Nevertheless, it was full of advances and interesting scientific matters.

As I mentioned in my last blog post, this week I worked on the implementation of the conditional VAE based on `this implementation <https://github.com/QingyuZhao/VAE-for-Regression/tree/master>` of this `paper <https://doi.org/10.1007/978-3-030-32245-8_91>`.

As a refresher, the main idea behind conditional generative models is being able to generate new data with some desired properties or parameters. To achieve this, it is common to organize the latent representation in a way that allows locating the regions in which the desired properties are found. For example, imagine our VAE learned a latent representation of images of cats with different fur lengths. If we do not condition our latent space on the fur length, our model might not learn about this distinctive feature found in the data space, and cats with drastically different fur lengths may be closely clustered together in the latent space. But with conditioning, we can tell the model to cluster the images along a "fur-length" dimension, so if we sample 2 images from a line that varies along that dimension but in opposite sides, we get a cat with very short fur, and another one, with very long fur. This results in a generative process that can be tuned on demand!

However, there are many methods to condition a Variational AutoEncoder, and they usually depend on the type of variable we want to condition on, so the methods for categoric variables (cat vs. dog, bundle_1_fiber vs. bundle_2_fiber, etc.) and continuous ones (age of the person, length of a streamline) are normally not applicable to both types. In the case of the FiberCup dataset, I chose to condition the latent space on the length of the streamlines, which is a continuous variable and it is a fairly easy thing to learn from the morphology of the streamlines.

After implementing the conditional VAE as in the provided reference and training it for 64 epochs (early stopped due to lack of improvement in the MSE) I got a very crappy looking reconstruction, but the latent space seems to be organized differently compared to the vanilla VAE, which suggests that the conditioning is doing something (good or not, we will see...).

.. image:: /_static/images/gsoc/2024/inigo/cvae_first_reconstruction_result.png
:alt: First reconstruction of the training data of the conditional VAE (cVAE).
:width: 600

On the other hand, note that the FiberCup has 7 distinct bundles, and both latent spaces show (when 2D-projected with the t-SNE algorithm) 7 clusters, suggesting that the network does know about the different bundles. Samples/streamlines are colored according to their length, and even if the bundle to which they belong is not plotted, we know that each cluster is formed by streamlines of different bundles because each bundle has a distinctive length. Note that the t-SNE representation may have aligned other dimensions more meaningful to the algorithm that do not necessarily include the conditioning variable (streamline length). Maybe the authors of the code I based mine were lucky to get the alignment, or smart enough to manipulate the conditioning variable (normalization, Z-scoring, etc.) to make t-SNE grab this information and put it along an axis in their plots.

.. image:: /_static/images/gsoc/2024/inigo/latent_space_comparison_VAE_cVAE_colored_by_streamline_length.png
:alt: t-SNE projections of the latent space (only plausible fibers) of the conditional VAE and the vanilla VAE.
:width: 600


What is coming up next week
~~~~~~~~~~~~~~~~~~~~~~~~~~~

After discussing with my mentors, we decided to take two steps:

1. Validate reliably whether the conditioning is working or not. For this, there are two strategies:
- Checking that the predicted conditioning variable matches the input. In other words, measuring the MSE between the "true age" VS the "predicted age", their correlation, and plotting one against the other. This way you know how good the encoder is capturing the conditioning variable variation in the training data. The authors of the paper I based my implementation on do it like this:
.. image:: /_static/images/gsoc/2024/inigo/conditioning_validation_using_mse.png
:alt: Scatter plot of true vs predicted conditioning variable for validation.
:width: 600

- Visual checking fiber generation for specific bundles. Knowing that different bundles have different fiber lengths, we try to generate fibers of specific length, and see whether the generated fibers belong to the desired bundle (no matter if they are plausible or implausible). Having length as the conditioning variable allows us to perform this trick, what would not be so intuitive to check if we had used Fractional Anisotropy or other DTI-derived metrics, as these are not visually as intuitive as length.

2. To try out an adversarial framework, which is 1) easier to implement 2) easier to understand, and 3) likely to also work (we'll see if better or not). The idea is to have a discriminator that tries to predict the conditioning variable from the latent space, and the encoder tries to fool the discriminator. This way, the encoder learns to encode the conditioning variable in the latent space, and the discriminator learns to predict it. This is a very common approach in GANs, and it is called "Conditional GAN" (cGAN). As a result, we would have what I would call a conditional adversarial VAE (CA-VAE). You can read more about adversarial VAEs `here <https://arxiv.org/pdf/2012.11551>`_ or `here <https://arxiv.org/pdf/1702.08423>`_

Did I get stuck anywhere
~~~~~~~~~~~~~~~~~~~~~~~~

Luckily this week I also did not get stuck in any problem, but I am a bit worried about the quality of the reconstructions of the cVAE. I hope that the adversarial framework will help with this.

Until next week!

0 comments on commit ec20908

Please sign in to comment.