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

doc updates #530

Merged
merged 16 commits into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 36 additions & 23 deletions docs/source/models_howto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,51 @@ For example, you could use a pretrained VAE to generate features for an image da

.. code-block:: python
Borda marked this conversation as resolved.
Show resolved Hide resolved

from pl_bolts.models.autoencoders import VAE
from pl_bolts.models.self_supervised import SimCLR

model = VAE(pretrained='imagenet2012')
encoder = model.encoder
weight_path = 'https://pl-bolts-weights.s3.us-east-2.amazonaws.com/simclr/bolts_simclr_imagenet/simclr_imagenet.ckpt'
simclr = SimCLR.load_from_checkpoint(weight_path, strict=False)
encoder = simclr.encoder
encoder.freeze()

for (x, y) in own_data
features = encoder(x)

The advantage of bolts is that each system can be decomposed and used in interesting ways.
For instance, this resnet18 was trained using self-supervised learning (no labels) on Imagenet, and thus
might perform better than the same resnet18 trained with labels
For instance, this resnet50 was trained using self-supervised learning (no labels) on Imagenet, and thus
might perform better than the same resnet50 trained with labels

.. code-block:: python
Borda marked this conversation as resolved.
Show resolved Hide resolved

# trained without labels
from pl_bolts.models.self_supervised import CPCV2
from pl_bolts.models.self_supervised import SimCLR

model = CPCV2(encoder='resnet18', pretrained='imagenet128')
resnet18_unsupervised = model.encoder.freeze()
weight_path = 'https://pl-bolts-weights.s3.us-east-2.amazonaws.com/simclr/bolts_simclr_imagenet/simclr_imagenet.ckpt'
simclr = SimCLR.load_from_checkpoint(weight_path, strict=False)
resnet50_unsupervised = simclr.encoder.freeze()

# trained with labels
from torchvision.models import resnet18
resnet18_supervised = resnet18(pretrained=True)
from torchvision.models import resnet50
resnet50_supervised = resnet50(pretrained=True)

# perhaps the features when trained without labels are much better for classification or other tasks
x = image_sample()
unsup_feats = resnet18_unsupervised(x)
sup_feats = resnet18_supervised(x)
unsup_feats = resnet50_unsupervised(x)
sup_feats = resnet50_supervised(x)

# which one will be better?

Bolts are often trained on more than just one dataset.

.. code-block:: python
Borda marked this conversation as resolved.
Show resolved Hide resolved

model = CPCV2(encoder='resnet18', pretrained='stl10')
from pl_bolts.models.self_supervised import SimCLR

# cifar-10 weights
weight_path = 'https://pl-bolts-weights.s3.us-east-2.amazonaws.com/simclr/simclr-cifar10-v1-exp12_87_52/epoch%3D960.ckpt'
simclr = SimCLR.load_from_checkpoint(weight_path, strict=False)

simclr.freeze()

---------------

Expand All @@ -68,14 +75,17 @@ In this approach, we load the pretrained model and unfreeze from the beginning

.. code-block:: python
Borda marked this conversation as resolved.
Show resolved Hide resolved

model = CPCV2(encoder='resnet18', pretrained='imagenet128')
resnet18 = model.encoder
from pl_bolts.models.self_supervised import SimCLR

weight_path = 'https://pl-bolts-weights.s3.us-east-2.amazonaws.com/simclr/simclr-cifar10-v1-exp12_87_52/epoch%3D960.ckpt'
simclr = SimCLR.load_from_checkpoint(weight_path, strict=False)
resnet50 = simclr.encoder
# don't call .freeze()

classifier = LogisticRegression()

for (x, y) in own_data:
feats = resnet18(x)
feats = resnet50(x)
y_hat = classifier(feats)
...

Expand All @@ -97,7 +107,7 @@ Or as a LightningModule
return loss

trainer = Trainer(gpus=2)
model = FineTuner(resnet18)
model = FineTuner(resnet50)
trainer.fit(model)

Sometimes this works well, but more often it's better to keep the encoder frozen for a while
Expand All @@ -109,21 +119,24 @@ The approach that works best most often is to freeze first then unfreeze later
.. code-block:: python
Borda marked this conversation as resolved.
Show resolved Hide resolved

# freeze!
model = CPCV2(encoder='resnet18', pretrained='imagenet128')
resnet18 = model.encoder
resnet18.freeze()
from pl_bolts.models.self_supervised import SimCLR

weight_path = 'https://pl-bolts-weights.s3.us-east-2.amazonaws.com/simclr/bolts_simclr_imagenet/simclr_imagenet.ckpt'
simclr = SimCLR.load_from_checkpoint(weight_path, strict=False)
resnet50 = simclr.encoder
resnet50.freeze()

classifier = LogisticRegression()

for epoch in epochs:
for (x, y) in own_data:
feats = resnet18(x)
feats = resnet50(x)
y_hat = classifier(feats)
loss = cross_entropy_with_logits(y_hat, y)

# unfreeze after 10 epochs
if epoch == 10:
resnet18.unfreeze()
resnet50.unfreeze()

.. note:: In practice, unfreezing later works MUCH better.

Expand All @@ -138,7 +151,7 @@ Or in Lightning as a Callback so you don't pollute your research code.
encoder.unfreeze()

trainer = Trainer(gpus=2, callbacks=[UnFreezeCallback()])
model = FineTuner(resnet18)
model = FineTuner(resnet50)
trainer.fit(model)

Unless you still need to mix it into your research code.
Expand Down
15 changes: 7 additions & 8 deletions docs/source/self_supervised_models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ In this example, we'll load a resnet 18 which was pretrained on imagenet using C

Example::
Borda marked this conversation as resolved.
Show resolved Hide resolved

from pl_bolts.models.self_supervised import CPCV2
from pl_bolts.models.self_supervised import SimCLR

# load resnet18 pretrained using CPC on imagenet
model = CPCV2(pretrained='resnet18')
cpc_resnet18 = model.encoder
cpc_resnet18.freeze()
# load resnet50 pretrained using SimCLR on imagenet
weight_path = 'https://pl-bolts-weights.s3.us-east-2.amazonaws.com/simclr/bolts_simclr_imagenet/simclr_imagenet.ckpt'
simclr = SimCLR.load_from_checkpoint(weight_path, strict=False)

# it supports any torchvision resnet
model = CPCV2(pretrained='resnet50')
simclr_resnet50 = simclr.encoder
simclr_resnet50.freeze()

This means you can now extract image representations that were pretrained via unsupervised learning.

Expand All @@ -38,7 +37,7 @@ Example::
my_dataset = SomeDataset()
for batch in my_dataset:
x, y = batch
out = cpc_resnet18(x)
out = simclr_resnet50(x)

----------------

Expand Down