Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LVAE losses tests #180

Closed
wants to merge 40 commits into from
Closed

LVAE losses tests #180

wants to merge 40 commits into from

Conversation

CatEek
Copy link
Contributor

@CatEek CatEek commented Jul 11, 2024

Description

  • What: Moved losses/NMs/LL/etc out of lightning module
  • Why: To be able to train LVAE based algorithms in CAREamics
  • How: Coded with my elbows, unfortunately

Changes Made

Added:

  • Some amount of very questionable quality code which needs to be refactored right away
  • Very basic tests which just ensure loss is not nan

Known problems

  • Noise models doesn't work because even the logic is actually not there yet
  • Training logic for NMs isn't clear
  • Most of the parameters should be documented, some should be refactored or removed
  • The whole pipeline isn't complete

Please ensure your PR meets the following requirements:

  • Code builds and passes tests locally, including doctests
  • New tests have been added (for bug fixes/features)
  • Pre-commit passes
  • PR to the documentation exists (for bug fixes / features)

Copy link
Member

@jdeschamps jdeschamps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should stick with the original plan of only using the new algorithms (HDN, denoiSplit) with the LightningAPI and not make them available through the CAREamist AP.

We are very close to a 0.1.0 release, which means that we might get an influx of users and incorporating code that does not work or might break can create a lot of issues.

If the modules are in the code base, they can be instantiated independently with the Ligthning API, that will be more than enough for Ashesh's paper. Once we are confident the quality of the code (integration, testing, documentation) is high enough, then we can make it available through the CAREamist.

So in the meantime, I would suggest keeping the configuration clean (removing LVAE, NoiseModels, Likelihood, and the new entries in the supported enums) and adding placeholder NotImplementedErrors in CAREamist.

For now, NoiseModel and Likelihood could be passed directly as parameters along the algorithm configuration. We can also discuss alternatives (e.g. allowing additional parameters in the Pydantic model via ConfigDict, but that would require a lot of asserts in the LVAE related code).

self.cfg.algorithm_config.model.architecture
== SupportedArchitecture.LVAE
): # TODO fuckin mypy thinks model "already defined on line 158"
self.model: VAEModule = VAEModule(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe what you can do about this is to define a type at the top of the module:

Module = Union[FCNModule, VAEModule]

And use that type on line 158.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But mypy isn't complaining about type ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One needs to try, I haven't. 😄

src/careamics/careamist.py Show resolved Hide resolved
self.model: VAEModule = VAEModule(
algorithm_config=self.cfg.algorithm_config,
)
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The configuration allows custom models that are neither Unet nor LVAE (Custom I believe). This breaks that possibility.

We could potentially consider that they should be FCNModule by default. Not sure what it entails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the configuration has only custom and UNet models, these statements should go.

Once the LVAE is in the configuration, we will need to reassess how to deal with custom models.

src/careamics/config/algorithm_model.py Outdated Show resolved Hide resolved
src/careamics/config/algorithm_model.py Outdated Show resolved Hide resolved
src/careamics/losses/lvae/losses.py Show resolved Hide resolved
src/careamics/losses/lvae/losses.py Show resolved Hide resolved
src/careamics/models/lvae/likelihoods.py Outdated Show resolved Hide resolved

import ml_collections
import ml_collections # TODO: refactor this out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see it used except in the declaration of config: ml_collections and then this config is not used (as far as I can tell). So kick it out as we discussed to allow the tests from passing (hopefully)!

src/careamics/models/lvae/noise_models.py Show resolved Hide resolved
@melisande-c
Copy link
Member

So in the meantime, I would suggest keeping the configuration clean (removing LVAE, NoiseModels, Likelihood, and the new entries in the supported enums) and adding placeholder NotImplementedErrors in CAREamist.

I will agree and say let's make the minimum number of modifications possible to the rest of the code until the LVAE pipeline is more complete, maybe not even adding not-implemented-errors to CAREamist. It might become clearer how we add the new components into the rest of CAREamist and the configuration once we understand how they work. I think it will also make the changes to the code easier to follow.

@jdeschamps
Copy link
Member

It seems there is still a hdn hanging around in one of the tests!

@jdeschamps jdeschamps self-requested a review July 15, 2024 21:54
@CatEek CatEek changed the title Towards LVAE training LVAE losses tests Jul 17, 2024
Copy link
Member

@melisande-c melisande-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I still think there are some changes here that are out of scope for the PR (also the current PR title is not descriptive of the changes). I see though that it's pretty hard to make the pydantic model when the LVAE class does need some refactoring to extract components that don't necessarily need to be contained within the class. Maybe the splitting of the configuration you mentioned will help.

Comment on lines -169 to +195
self.model = CAREamicsModule(
algorithm_config=self.cfg.algorithm_config,
)
if (
self.cfg.algorithm_config.model.architecture
== SupportedArchitecture.UNET
):
self.model = FCNModule(
algorithm_config=self.cfg.algorithm_config,
)
else:
raise NotImplementedError("Architecture not supported.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repetition of inner if-else statement can be removed through separation of config initialisation and model initialisation. i.e.

if isinstance(source, Path) and source.is_file():
    if source.suffix == ".yaml" or source.suffix == ".yml":
        self.cfg = load_configuration(source)
        self.model = None
    else:
        self.model, self.cfg = load_pretrained(source)
elif isinstance(source, Configuration):
    self.cfg = source
    self.model = None
else:
    raise ValueError("appropriate message")

# instantiate model
if self.model is None:
    if (
        self.cfg.algorithm_config.model.architecture
        == SupportedArchitecture.UNET
    ):
        self.model = FCNModule(
            algorithm_config=self.cfg.algorithm_config,
        )
    elif (
        self.cfg.algorithm_config.model.architecture
        == SupportedArchitecture.LVAE
    ):  
        raise NotImplementedError(
            "LVAE is currently only supported through lightning api"
        )
    else:
        raise NotImplementedError("Architecture not supported.")

^ just an example can probably be improved further. Extracting to smaller testable sub functions might be good too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those things are gone in the config refac pr

Comment on lines 95 to 109
# Mandatory fields
algorithm: Literal["n2v", "care", "n2n", "custom"] # defined in SupportedAlgorithm
"""Name of the algorithm, as defined in SupportedAlgorithm."""

# defined in SupportedAlgorithm
algorithm: Literal["n2v", "care", "n2n"]
loss: Literal["n2v", "mae", "mse"]
"""Loss function to use, as defined in SupportedLoss."""

model: Union[UNetModel, VAEModel, CustomModel] = Field(discriminator="architecture")
"""Model architecture to use, defined in SupportedArchitecture."""
model: Union[UNetModel, CustomModel] = Field(discriminator="architecture")

# Optional fields
optimizer: OptimizerModel = OptimizerModel()
"""Optimizer to use, defined in SupportedOptimizer."""

lr_scheduler: LrSchedulerModel = LrSchedulerModel()
"""Learning rate scheduler to use, defined in SupportedScheduler."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some docstrings have been deleted, probably by mistake.

src/careamics/lightning/lightning_module.py Show resolved Hide resolved
src/careamics/config/likelihood_model.py Show resolved Hide resolved
CUSTOM = (
"Custom" # TODO all the others tags are small letters, except the architect
"custom" # TODO all the others tags are small letters, except the architect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove TODO

Comment on lines +460 to +466
self.likelihood_gm = GaussianLikelihood(
self.decoder_n_filters,
self.target_ch,
predict_logvar=self.predict_logvar,
logvar_lowerbound=self.logvar_lowerbound,
conv2d_bias=self.topdown_conv2d_bias,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is self.likelihood_gm used? as far as I can see it doesn't seem to be used by any of theLVAE class' methods. If it is only used by external functions maybe it can be removed from the LVAE class and passed to those functions explicitly.

tests/config/architectures/test_lvae_model.py Show resolved Hide resolved
assert act in activations


def test_activation_wrong_values():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe rename test_activation_unknown_value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what that function even doing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just testing an error is raised if "nonlinearity" is not a supported activation, no?

tests/config/test_algorithm_model.py Show resolved Hide resolved
tests/conftest.py Show resolved Hide resolved
@jdeschamps
Copy link
Member

jdeschamps commented Jul 18, 2024

I pushed a fix for the doctests as promised.

@jdeschamps
Copy link
Member

jdeschamps commented Jul 19, 2024

Comment https://github.com/CAREamics/careamics/pull/180/files#r1675427899 still needs to be fixed regarding the custom algorithms and models.

self.model: VAEModule = VAEModule(
algorithm_config=self.cfg.algorithm_config,
)
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the configuration has only custom and UNet models, these statements should go.

Once the LVAE is in the configuration, we will need to reassess how to deal with custom models.

src/careamics/lightning/lightning_module.py Show resolved Hide resolved
target = aux[0]
self.loss_parameters.current_epoch = self.current_epoch
self.loss_parameters.inputs = x
self.loss_parameters.mask = ~((target == 0).reshape(len(target), -1).all(dim=1))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments about what is happening in these steps.


loss: Literal["n2v", "mae", "mse"]
"""Loss function to use, as defined in SupportedLoss."""
"""Name of the algorithm, as defined in SupportedAlgorithm."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Algorithm docs instead of loss docs.

raise ValueError("VAE are currently not implemented.")
if (self.algorithm == "custom") != (self.model.architecture == "custom"):
raise ValueError(
"Algorithm and model architecture must be both `custom` or not."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grammar could be clearer. not what?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it was meant to be "None"!

@CatEek CatEek closed this Aug 22, 2024
@jdeschamps jdeschamps deleted the iz/feat/lvae_losses branch December 6, 2024 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants