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

Updated coreset subsampling method to improve accuracy #73

Merged
merged 4 commits into from
Jan 18, 2022

Conversation

blakshma
Copy link
Contributor

@blakshma blakshma commented Jan 16, 2022

Fixes #74 and #6

Copy link
Collaborator

@ashwinvaidya17 ashwinvaidya17 left a comment

Choose a reason for hiding this comment

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

Thanks for addressing this! It's also nice that we could get rid of all the extra modules. I have only two minor comments.

@@ -14,7 +14,7 @@ dataset:
use_random_tiling: False
random_tile_count: 16
image_size: 224
train_batch_size: 32
train_batch_size: 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this by choice or an artefact of debugging?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. It was an artifact. Fixed it.

Comment on lines 308 to 311
embedding: (sample_count, d) tensor of patches.
sample_count: Number of patches to select.
eps: Parameter for spare projection aggresion.
force_cpu: Force cpu, useful in case of GPU OOM.
Copy link
Collaborator

Choose a reason for hiding this comment

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

These seem to be missing the types.

Copy link
Contributor

@samet-akcay samet-akcay left a comment

Choose a reason for hiding this comment

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

Forgot to submit my review

anomalib/models/patchcore/README.md Show resolved Hide resolved
anomalib/models/patchcore/README.md Show resolved Hide resolved
anomalib/models/patchcore/README.md Show resolved Hide resolved
@@ -14,7 +14,7 @@ dataset:
use_random_tiling: False
random_tile_count: 16
image_size: 224
train_batch_size: 32
train_batch_size: 1
Copy link
Contributor

Choose a reason for hiding this comment

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

Why train_batch_size is set to 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. It was an artifact. Fixed it.

anomalib/models/patchcore/model.py Outdated Show resolved Hide resolved
transformer = random_projection.SparseRandomProjection(eps=eps)
sample_set = torch.tensor(transformer.fit_transform(sample_set)) # pylint: disable=not-callable
except ValueError:
print(" Error: could not project vectors. Please increase `eps` value.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above. Add logger todo

print("Fitting random projections...")
try:
transformer = random_projection.SparseRandomProjection(eps=eps)
sample_set = torch.tensor(transformer.fit_transform(sample_set)) # pylint: disable=not-callable
Copy link
Contributor

Choose a reason for hiding this comment

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

We could maybe move to GPU like the following:

sample_set = torch.tensor(transformer.fit_transform(sample_set.cpu())).to(sample_set.device)

This would automate the assign to the device.

Comment on lines 329 to 332
if torch.cuda.is_available() and not force_cpu:
last_item = last_item.to("cuda")
sample_set = sample_set.to("cuda")
min_distances = min_distances.to("cuda")
Copy link
Contributor

Choose a reason for hiding this comment

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

When the device is automatically assigned as suggeste above in Line 320, we wouldn't need to move to cuda.


last_item = sample_set[select_idx : select_idx + 1]
min_distances[select_idx] = 0
coreset_idx.append(select_idx.to("cpu")) # type: ignore[attr-defined]
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this moved to cpu?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was due to the way select_idx was initialized. Updated this in the latest commit.

@blakshma
Copy link
Contributor Author

Thanks for the review @samet-akcay @ashwinvaidya17 . I have addressed them in the recent commit.

Copy link
Contributor

@djdameln djdameln left a comment

Choose a reason for hiding this comment

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

@blakshma Thanks a lot for this PR. Great to finally see the Patchcore implementation produce results that are in line with the paper. Also nice to get rid of the helper classes, the implementation is much cleaner this way. Just two minor comments.

"""Returns n subsampled coreset idx for given sample_set.

Args:
embedding (Tensor): (sample_count, d) tensor of patches.
Copy link
Contributor

Choose a reason for hiding this comment

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

This naming differs from the method signature


return batch

def get_coreset_idx(
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel that maybe this method should be part of the PatchcoreModel class. In the other implementations we reserve the lightning class for the learning and inference logic, and define any model-specific operations in the Torch class. Maybe it could be called create_coreset or subsample_coreset and placed in PatchcoreModel. It could also assign the embeddings attribute from within the method so that it doesn't need to return anything. This would keep the lightning class a bit cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a great idea. I have made that change.

@samet-akcay samet-akcay merged commit 3613a6e into development Jan 18, 2022
@samet-akcay samet-akcay deleted the fix/barath/patchcore branch January 18, 2022 08:16
@samet-akcay samet-akcay mentioned this pull request Jan 18, 2022
samet-akcay added a commit that referenced this pull request Jan 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Diverged metrics in PatchCore: dropping from 0.99 to 0.44 and 0.03 is rather critical?
4 participants