Skip to content

Port Multi-weight support from prototype to main TorchVision #5618

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

Merged
merged 52 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
d44e44d
Moving basefiles outside of prototype and porting Alexnet, ConvNext, …
datumbox Mar 11, 2022
78f90ce
Porting googlenet
datumbox Mar 11, 2022
548d9ca
Porting inception
datumbox Mar 11, 2022
46ff348
Porting mnasnet
datumbox Mar 11, 2022
58be05b
Porting mobilenetv2
datumbox Mar 11, 2022
99930d5
Porting mobilenetv3
datumbox Mar 11, 2022
9b4a3ef
Porting regnet
datumbox Mar 11, 2022
3788fb8
Porting resnet
datumbox Mar 11, 2022
0eabb0c
Porting shufflenetv2
datumbox Mar 11, 2022
8c45c1a
Porting squeezenet
datumbox Mar 14, 2022
b7916d3
Porting vgg
datumbox Mar 14, 2022
a7fabb3
Porting vit
datumbox Mar 14, 2022
76f017c
Fix docstrings
datumbox Mar 14, 2022
eb5254d
Fixing imports
datumbox Mar 14, 2022
56e0e01
Adding missing import
datumbox Mar 14, 2022
2a42fd2
Merge branch 'main' into multiweight/full
datumbox Mar 14, 2022
34f45d0
Fix mobilenet imports
datumbox Mar 14, 2022
7cd616c
Fix tests
datumbox Mar 14, 2022
5ce348d
Fix prototype tests
datumbox Mar 14, 2022
a8650a4
Exclude get_weight from models on test
datumbox Mar 14, 2022
08c5f9b
Fix init files
datumbox Mar 14, 2022
bc6d94f
Porting googlenet
datumbox Mar 14, 2022
c106748
Porting inception
datumbox Mar 14, 2022
db33f53
porting mobilenetv2
datumbox Mar 14, 2022
f342797
porting mobilenetv3
datumbox Mar 14, 2022
3db3e77
porting resnet
datumbox Mar 14, 2022
829c5c1
porting shufflenetv2
datumbox Mar 14, 2022
469eadd
Fix test and linter
datumbox Mar 14, 2022
66d7642
Fixing docs.
datumbox Mar 14, 2022
a39e60e
Porting Detection models (#5617)
datumbox Mar 15, 2022
5a96c9a
Porting Optical Flow, Segmentation, Video models (#5619)
datumbox Mar 15, 2022
6d96ed5
Porting docs, examples, tutorials and galleries (#5620)
datumbox Mar 15, 2022
31dd3b8
Merge branch 'main' into multiweight
datumbox Mar 15, 2022
c88b8dc
Resolve conflict
datumbox Mar 15, 2022
f121ca7
Porting model tests (#5622)
datumbox Mar 15, 2022
189cbc8
Merge branch 'main' into multiweight
datumbox Mar 15, 2022
db0fd27
Update CI on Multiweight branch to use the new weight download approa…
datumbox Mar 16, 2022
e8fa42c
Merge branch 'main' into multiweight
datumbox Mar 16, 2022
96b99dc
Merge branch 'main' into multiweight
datumbox Mar 16, 2022
0a612cb
Porting reference scripts and updating presets (#5629)
datumbox Mar 17, 2022
f51d5f8
Setting `weights_backbone` to its fully BC value (#5653)
datumbox Mar 21, 2022
8b9631b
Update docs.
datumbox Mar 21, 2022
fea9e39
Update preprocessing on reference scripts.
datumbox Mar 21, 2022
59bdfbd
Change qat/ptq to their full values.
datumbox Mar 21, 2022
e85f494
Refactoring preprocessing
datumbox Mar 21, 2022
0b0fc82
Fix video preset
datumbox Mar 21, 2022
903a3d5
No initialization on VGG if pretrained
datumbox Mar 21, 2022
cbec5b1
Merge branch 'main' into multiweight
datumbox Mar 21, 2022
db9139a
Fix warning messages for backbone utils.
datumbox Mar 22, 2022
545e431
Adding star to all preset constructors.
datumbox Mar 22, 2022
da10c9b
Merge branch 'main' into multiweight
datumbox Mar 22, 2022
ff3fd54
Fix mypy.
datumbox Mar 22, 2022
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
20 changes: 15 additions & 5 deletions .circleci/config.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 15 additions & 5 deletions .circleci/config.yml.in
Original file line number Diff line number Diff line change
Expand Up @@ -366,19 +366,28 @@ jobs:
resource_class: xlarge
steps:
- checkout
- download_model_weights:
extract_roots: torchvision/prototype/models
- install_torchvision
- install_prototype_dependencies
- pip_install:
args: scipy pycocotools h5py
descr: Install optional dependencies
- run:
name: Enable prototype tests
command: echo 'export PYTORCH_TEST_WITH_PROTOTYPE=1' >> $BASH_ENV
- run_tests_selective:
file_or_dir: test/test_prototype_*.py

unittest_extended:
Copy link
Member

Choose a reason for hiding this comment

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

(Replying to https://github.com/pytorch/vision/pull/5618/files#r829105451 here because GitHub hides the .yml file)

Are these tests really that long to run? If they are, could we simply just skip them for all non-linux CI jobs (we could even pin a Python version if we want to make sure they only run once)? No strong opinion but perhaps there are simpler solutions than adding a new job

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They don't take that long for now and yes we could skip them on all but 1 configuration. One potential benefit from doing it this way is we don't have to run the tests on FBcode where we would have to download the weights serially from manifold.

Let's review the model testing strategy as a whole later this half and redesign our testing strategy. We can catch work together on this if you have the bandwidth.

docker:
- image: circleci/python:3.7
resource_class: xlarge
steps:
- checkout
- download_model_weights
- install_torchvision
- run:
name: Enable extended tests
command: echo 'export PYTORCH_TEST_WITH_EXTENDED=1' >> $BASH_ENV
- run_tests_selective:
file_or_dir: test/test_extended_*.py

binary_linux_wheel:
<<: *binary_common
docker:
Expand Down Expand Up @@ -1115,6 +1124,7 @@ workflows:
- unittest_torchhub
- unittest_onnx
- unittest_prototype
- unittest_extended
{{ unittest_workflows() }}

cmake:
Expand Down
13 changes: 10 additions & 3 deletions android/test_app/make_assets.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import torch
import torchvision
from torch.utils.mobile_optimizer import optimize_for_mobile
from torchvision.models.detection import (
fasterrcnn_mobilenet_v3_large_320_fpn,
FasterRCNN_MobileNet_V3_Large_320_FPN_Weights,
)

print(torch.__version__)

model = torchvision.models.detection.fasterrcnn_mobilenet_v3_large_320_fpn(
pretrained=True, box_score_thresh=0.7, rpn_post_nms_top_n_test=100, rpn_score_thresh=0.4, rpn_pre_nms_top_n_test=150
model = fasterrcnn_mobilenet_v3_large_320_fpn(
weights=FasterRCNN_MobileNet_V3_Large_320_FPN_Weights.DEFAULT,
box_score_thresh=0.7,
rpn_post_nms_top_n_test=100,
rpn_score_thresh=0.4,
rpn_pre_nms_top_n_test=150,
)

model.eval()
Expand Down
54 changes: 1 addition & 53 deletions docs/source/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,58 +98,6 @@ You can construct a model with random weights by calling its constructor:
convnext_large = models.convnext_large()

We provide pre-trained models, using the PyTorch :mod:`torch.utils.model_zoo`.
These can be constructed by passing ``pretrained=True``:

.. code:: python

import torchvision.models as models
resnet18 = models.resnet18(pretrained=True)
alexnet = models.alexnet(pretrained=True)
squeezenet = models.squeezenet1_0(pretrained=True)
vgg16 = models.vgg16(pretrained=True)
densenet = models.densenet161(pretrained=True)
inception = models.inception_v3(pretrained=True)
googlenet = models.googlenet(pretrained=True)
shufflenet = models.shufflenet_v2_x1_0(pretrained=True)
mobilenet_v2 = models.mobilenet_v2(pretrained=True)
mobilenet_v3_large = models.mobilenet_v3_large(pretrained=True)
mobilenet_v3_small = models.mobilenet_v3_small(pretrained=True)
resnext50_32x4d = models.resnext50_32x4d(pretrained=True)
wide_resnet50_2 = models.wide_resnet50_2(pretrained=True)
mnasnet = models.mnasnet1_0(pretrained=True)
efficientnet_b0 = models.efficientnet_b0(pretrained=True)
efficientnet_b1 = models.efficientnet_b1(pretrained=True)
efficientnet_b2 = models.efficientnet_b2(pretrained=True)
efficientnet_b3 = models.efficientnet_b3(pretrained=True)
efficientnet_b4 = models.efficientnet_b4(pretrained=True)
efficientnet_b5 = models.efficientnet_b5(pretrained=True)
efficientnet_b6 = models.efficientnet_b6(pretrained=True)
efficientnet_b7 = models.efficientnet_b7(pretrained=True)
efficientnet_v2_s = models.efficientnet_v2_s(pretrained=True)
efficientnet_v2_m = models.efficientnet_v2_m(pretrained=True)
efficientnet_v2_l = models.efficientnet_v2_l(pretrained=True)
regnet_y_400mf = models.regnet_y_400mf(pretrained=True)
regnet_y_800mf = models.regnet_y_800mf(pretrained=True)
regnet_y_1_6gf = models.regnet_y_1_6gf(pretrained=True)
regnet_y_3_2gf = models.regnet_y_3_2gf(pretrained=True)
regnet_y_8gf = models.regnet_y_8gf(pretrained=True)
regnet_y_16gf = models.regnet_y_16gf(pretrained=True)
regnet_y_32gf = models.regnet_y_32gf(pretrained=True)
regnet_x_400mf = models.regnet_x_400mf(pretrained=True)
regnet_x_800mf = models.regnet_x_800mf(pretrained=True)
regnet_x_1_6gf = models.regnet_x_1_6gf(pretrained=True)
regnet_x_3_2gf = models.regnet_x_3_2gf(pretrained=True)
regnet_x_8gf = models.regnet_x_8gf(pretrained=True)
regnet_x_16gf = models.regnet_x_16gf(pretrainedTrue)
regnet_x_32gf = models.regnet_x_32gf(pretrained=True)
vit_b_16 = models.vit_b_16(pretrained=True)
vit_b_32 = models.vit_b_32(pretrained=True)
vit_l_16 = models.vit_l_16(pretrained=True)
vit_l_32 = models.vit_l_32(pretrained=True)
convnext_tiny = models.convnext_tiny(pretrained=True)
convnext_small = models.convnext_small(pretrained=True)
convnext_base = models.convnext_base(pretrained=True)
convnext_large = models.convnext_large(pretrained=True)

Instancing a pre-trained model will download its weights to a cache directory.
This directory can be set using the `TORCH_HOME` environment variable. See
Expand Down Expand Up @@ -525,7 +473,7 @@ Obtaining a pre-trained quantized model can be done with a few lines of code:
.. code:: python

import torchvision.models as models
model = models.quantization.mobilenet_v2(pretrained=True, quantize=True)
model = models.quantization.mobilenet_v2(weights=MobileNet_V2_QuantizedWeights.IMAGENET1K_QNNPACK_V1, quantize=True)
model.eval()
# run the model with quantized inputs and weights
out = model(torch.rand(1, 3, 224, 224))
Expand Down
2 changes: 1 addition & 1 deletion examples/cpp/hello_world/trace_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
HERE = osp.dirname(osp.abspath(__file__))
ASSETS = osp.dirname(osp.dirname(HERE))

model = torchvision.models.resnet18(pretrained=False)
model = torchvision.models.resnet18()
model.eval()

traced_model = torch.jit.script(model)
Expand Down
34 changes: 15 additions & 19 deletions gallery/plot_optical_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import torch
import matplotlib.pyplot as plt
import torchvision.transforms.functional as F
import torchvision.transforms as T


plt.rcParams["savefig.bbox"] = "tight"
Expand Down Expand Up @@ -88,24 +87,19 @@ def plot(imgs, **imshow_kwargs):
# reduce the image sizes for the example to run faster. Image dimension must be
# divisible by 8.

from torchvision.models.optical_flow import Raft_Large_Weights

def preprocess(batch):
transforms = T.Compose(
[
T.ConvertImageDtype(torch.float32),
T.Normalize(mean=0.5, std=0.5), # map [0, 1] into [-1, 1]
T.Resize(size=(520, 960)),
]
)
batch = transforms(batch)
return batch
weights = Raft_Large_Weights.DEFAULT
transforms = weights.transforms()


# If you can, run this example on a GPU, it will be a lot faster.
device = "cuda" if torch.cuda.is_available() else "cpu"
def preprocess(img1_batch, img2_batch):
img1_batch = F.resize(img1_batch, size=[520, 960])
img2_batch = F.resize(img2_batch, size=[520, 960])
return transforms(img1_batch, img2_batch)


img1_batch = preprocess(img1_batch).to(device)
img2_batch = preprocess(img2_batch).to(device)
img1_batch, img2_batch = preprocess(img1_batch, img2_batch)

print(f"shape = {img1_batch.shape}, dtype = {img1_batch.dtype}")

Expand All @@ -121,7 +115,10 @@ def preprocess(batch):

from torchvision.models.optical_flow import raft_large

model = raft_large(pretrained=True, progress=False).to(device)
# If you can, run this example on a GPU, it will be a lot faster.
device = "cuda" if torch.cuda.is_available() else "cpu"

model = raft_large(weights=Raft_Large_Weights.DEFAULT, progress=False).to(device)
model = model.eval()

list_of_flows = model(img1_batch.to(device), img2_batch.to(device))
Expand Down Expand Up @@ -182,10 +179,9 @@ def preprocess(batch):
# from torchvision.io import write_jpeg
# for i, (img1, img2) in enumerate(zip(frames, frames[1:])):
# # Note: it would be faster to predict batches of flows instead of individual flows
# img1 = preprocess(img1[None]).to(device)
# img2 = preprocess(img2[None]).to(device)
# img1, img2 = preprocess(img1, img2)

# list_of_flows = model(img1_batch, img2_batch)
# list_of_flows = model(img1.to(device), img1.to(device))
# predicted_flow = list_of_flows[-1][0]
# flow_img = flow_to_image(predicted_flow).to("cpu")
# output_folder = "/tmp/" # Update this to the folder of your choice
Expand Down
8 changes: 5 additions & 3 deletions gallery/plot_repurposing_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,14 @@ def show(imgs):
# Here is demo with a Faster R-CNN model loaded from
# :func:`~torchvision.models.detection.fasterrcnn_resnet50_fpn`

from torchvision.models.detection import fasterrcnn_resnet50_fpn
from torchvision.models.detection import fasterrcnn_resnet50_fpn, FasterRCNN_ResNet50_FPN_Weights

model = fasterrcnn_resnet50_fpn(pretrained=True, progress=False)
weights = FasterRCNN_ResNet50_FPN_Weights.DEFAULT
model = fasterrcnn_resnet50_fpn(weights=weights, progress=False)
print(img.size())

img = F.convert_image_dtype(img, torch.float)
tranforms = weights.transforms()
img = tranforms(img)
target = {}
target["boxes"] = boxes
target["labels"] = labels = torch.ones((masks.size(0),), dtype=torch.int64)
Expand Down
12 changes: 4 additions & 8 deletions gallery/plot_scripted_tensor_transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,16 @@ def show(imgs):
# Let's define a ``Predictor`` module that transforms the input tensor and then
# applies an ImageNet model on it.

from torchvision.models import resnet18
from torchvision.models import resnet18, ResNet18_Weights


class Predictor(nn.Module):

def __init__(self):
super().__init__()
self.resnet18 = resnet18(pretrained=True, progress=False).eval()
self.transforms = nn.Sequential(
T.Resize([256, ]), # We use single int value inside a list due to torchscript type restrictions
T.CenterCrop(224),
T.ConvertImageDtype(torch.float),
T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
)
weights = ResNet18_Weights.DEFAULT
self.resnet18 = resnet18(weights=weights, progress=False).eval()
self.transforms = weights.transforms()

def forward(self, x: torch.Tensor) -> torch.Tensor:
with torch.no_grad():
Expand Down
39 changes: 27 additions & 12 deletions gallery/plot_visualization_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,17 @@ def show(imgs):
# :func:`~torchvision.models.detection.ssd300_vgg16`. For more details
# on the output of such models, you may refer to :ref:`instance_seg_output`.

from torchvision.models.detection import fasterrcnn_resnet50_fpn
from torchvision.transforms.functional import convert_image_dtype
from torchvision.models.detection import fasterrcnn_resnet50_fpn, FasterRCNN_ResNet50_FPN_Weights


batch_int = torch.stack([dog1_int, dog2_int])
batch = convert_image_dtype(batch_int, dtype=torch.float)

model = fasterrcnn_resnet50_fpn(pretrained=True, progress=False)
weights = FasterRCNN_ResNet50_FPN_Weights.DEFAULT
transforms = weights.transforms()

batch = transforms(batch_int)

model = fasterrcnn_resnet50_fpn(weights=weights, progress=False)
model = model.eval()

outputs = model(batch)
Expand Down Expand Up @@ -120,13 +123,15 @@ def show(imgs):
# images must be normalized before they're passed to a semantic segmentation
# model.

from torchvision.models.segmentation import fcn_resnet50
from torchvision.models.segmentation import fcn_resnet50, FCN_ResNet50_Weights

weights = FCN_ResNet50_Weights.DEFAULT
transforms = weights.transforms(resize_size=None)

model = fcn_resnet50(pretrained=True, progress=False)
model = fcn_resnet50(weights=weights, progress=False)
model = model.eval()

normalized_batch = F.normalize(batch, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))
normalized_batch = transforms(batch)
output = model(normalized_batch)['out']
print(output.shape, output.min().item(), output.max().item())

Expand Down Expand Up @@ -262,8 +267,14 @@ def show(imgs):
# of them may not have masks, like
# :func:`~torchvision.models.detection.fasterrcnn_resnet50_fpn`.

from torchvision.models.detection import maskrcnn_resnet50_fpn
model = maskrcnn_resnet50_fpn(pretrained=True, progress=False)
from torchvision.models.detection import maskrcnn_resnet50_fpn, MaskRCNN_ResNet50_FPN_Weights

weights = MaskRCNN_ResNet50_FPN_Weights.DEFAULT
transforms = weights.transforms()

batch = transforms(batch_int)

model = maskrcnn_resnet50_fpn(weights=weights, progress=False)
model = model.eval()

output = model(batch)
Expand Down Expand Up @@ -378,13 +389,17 @@ def show(imgs):
# Note that the keypoint detection model does not need normalized images.
#

from torchvision.models.detection import keypointrcnn_resnet50_fpn
from torchvision.models.detection import keypointrcnn_resnet50_fpn, KeypointRCNN_ResNet50_FPN_Weights
from torchvision.io import read_image

person_int = read_image(str(Path("assets") / "person1.jpg"))
person_float = convert_image_dtype(person_int, dtype=torch.float)

model = keypointrcnn_resnet50_fpn(pretrained=True, progress=False)
weights = KeypointRCNN_ResNet50_FPN_Weights.DEFAULT
transforms = weights.transforms()

person_float = transforms(person_int)

model = keypointrcnn_resnet50_fpn(weights=weights, progress=False)
model = model.eval()

outputs = model([person_float])
Expand Down
13 changes: 10 additions & 3 deletions ios/VisionTestApp/make_assets.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import torch
import torchvision
from torch.utils.mobile_optimizer import optimize_for_mobile
from torchvision.models.detection import (
fasterrcnn_mobilenet_v3_large_320_fpn,
FasterRCNN_MobileNet_V3_Large_320_FPN_Weights,
)

print(torch.__version__)

model = torchvision.models.detection.fasterrcnn_mobilenet_v3_large_320_fpn(
pretrained=True, box_score_thresh=0.7, rpn_post_nms_top_n_test=100, rpn_score_thresh=0.4, rpn_pre_nms_top_n_test=150
model = fasterrcnn_mobilenet_v3_large_320_fpn(
weights=FasterRCNN_MobileNet_V3_Large_320_FPN_Weights.DEFAULT,
box_score_thresh=0.7,
rpn_post_nms_top_n_test=100,
rpn_score_thresh=0.4,
rpn_pre_nms_top_n_test=150,
)

model.eval()
Expand Down
Loading