-
Notifications
You must be signed in to change notification settings - Fork 378
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
Add random crop logic to DeepGlobeLandCover Datamodule #876
Conversation
I confirmed this all works as expected with the actual dataset! |
I noticed something after the last commit, namely the case when
Just wanted to ask, which logic we should go for and whether we can do that consistently across all the datamodules. |
What is the minimum test complaining about? |
Same thing I fixed here. Either merge that PR first or make the same change to this PR. |
Suggestions made in #929 (relative imports in datamodule and if guard for collate fn) are applicable here as well |
Not sure what you think of the transform implementation I did. It is very similar to the existing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this approach makes sense. Or rather, it's a perfectly valid approach, but it's not the way torchvision/torchgeo/kornia do things, and I don't see any reason why we need to introduce a completely different way of handling this. The way I think about it is:
_pad_segmentation_sample
is a transform/data augmentation- All transforms/data augmentations in torchvision/torchgeo/kornia are classes that implement
__call__
, not functions - Kornia's AugmentationSequential/AugmentationPatches and torchvision's Compose are containers, not transforms/data augmentations
There are also a lot of inconsistencies in the API that this introduces:
- All torchgeo transforms are in
torchgeo/transforms
, nottorchgeo/datasets
- Kornia: AugmentationSequential/AugmentationPatches, TorchGeo: AugmentationSequential/PatchesAugmentation (names are not consistent)
- Kornia: AugmentationPatches splits into patches, performs augmentation, reassembles. TorchGeo: PatchesAugmentation applies augmentations to all patches (behavior is not consistent)
I still think we should use a transform instead of a function. Then you can use it with Compose or AugmentationSequential or whatever else. I would subclass nn.Module
like all of our other existing transforms.
I also think this probably belongs in torchgeo/transforms/
, although we can still keep it a hidden method until we have a better idea of where to fit it in the library. We can put it in transforms.py
for now.
Okay so I should
|
I think we want to move FROM: function We can bikeshed on the name later, but I'll prob want to rename it to match whatever torchvision/kornia calls it. I also think we want to remove I'm starting to suspect that there's something I'm not understanding about why |
# kornia 0.6.5+ required due to change in kornia.augmentation API | ||
kornia>=0.6.5,<0.7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Kornia 0.6.5+, all augmentation instance methods have a new flags
parameter. So the transforms I added won't work with Kornia 0.6.4 and older. Once we upstream these transforms to Kornia, we'll need to depend on an even newer version anyway.
from torchvision.transforms import Compose | ||
from kornia.augmentation import Normalize |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm planning on removing all torchvision transforms. Torchvision relies on PIL for many of its transforms, which doesn't support MSI. Kornia has all of the same transforms, but they are in pure PyTorch, so they can run on the GPU and support MSI. I don't see a good reason not to only use Kornia transforms.
*batch_size* was replaced by *num_tile_per_batch*, *num_patches_per_tile*, | ||
and *patch_size*. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to only document API changes, not internal changes. So the fact that we're now using random cropping isn't documented, only that the parameters changed.
self.kwargs = kwargs | ||
|
||
def preprocess(self, sample: Dict[str, Any]) -> Dict[str, Any]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot use instance methods as transforms, see #886 for what happens when we do.
self.train_dataset: Dataset[Any] | ||
self.val_dataset: Dataset[Any] | ||
|
||
if self.val_split_pct > 0.0: | ||
self.train_dataset, self.val_dataset, _ = dataset_split( | ||
dataset, val_pct=self.val_split_pct, test_pct=0.0 | ||
) | ||
else: | ||
self.train_dataset = dataset | ||
self.val_dataset = dataset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea why our previous logic was so complicated, but I don't think it needs to be.
if self.trainer: | ||
if self.trainer.training: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So much cleaner than our previous logic!
# Kornia adds a channel dimension to the mask | ||
batch["mask"] = batch["mask"].squeeze(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kornia does a lot of weird stuff with transforms that I don't like. Masks are required to be floats (why? slower, more storage). If the mask you input doesn't have a channel dimension, it will add one. Some of the transforms actually break if the mask doesn't have a channel dimension when you input it, so we may need to add an unsqueeze above.
@overload | ||
def _to_tuple(value: Union[Tuple[int, int], int]) -> Tuple[int, int]: | ||
... | ||
|
||
|
||
@overload | ||
def _to_tuple(value: Union[Tuple[float, float], float]) -> Tuple[float, float]: | ||
... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Python typing, all ints are floats, but not all floats are ints. This meant that if I pass an int as input, mypy would consider its output type to be float. These overloads ensure that int maps to int and float maps to float as expected.
Returns: | ||
the transformation | ||
""" | ||
out: Tensor = self.identity_matrix(input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't correct but something is required and we don't actually use it. I'll iron out the details when we upstream this.
eb2ac43
to
d35773b
Compare
I am using the following script to test:
But in |
* crop logic * typo * change train_batch_size logic * fix failing test * typos and naming * return argument train dataloader * typo * fix failing test * suggestions except about test file * remove test_deepglobe and add test to trainer * forgot new conf file * reanme collate function * move cropping logic to transform and utils * remove comment * simplify * move pad_segmentation to transforms * another one * naming and versionadded * another transforms approach * typo * fix read the docs * some checks for Ncrop * add unit tests new transforms * Remove cruft * More simplification * Add config file * Implemented ExtractTensorPatches * Remove tests * Remove unnecessary attrs * Apply to both input and mask * Implement RandomNCrop * Fix dimensions * mypy fixes * Fix docs * Ensure that image and mask get the same transformation * Bump min kornia version * ignore still needed? * Remove unneeded hacks * Fix pydocstyle * Fix dimensions Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
Adressing #855 by adding random crop logic to datamodule. Additionally, add a test file for the datamodule.