Skip to content

Commit

Permalink
Merge branch 'main' of github.com:pytorch/vision into tv-tensor-enhance
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasHug committed Apr 19, 2024
2 parents 1cfe17d + 2ae6a6d commit 2d3c99b
Show file tree
Hide file tree
Showing 91 changed files with 1,169 additions and 540 deletions.
1 change: 1 addition & 0 deletions .github/workflows/prototype-tests-linux-gpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
runner: ["linux.12xlarge"]
gpu-arch-type: ["cpu"]
include:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/tests-schedule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2

- name: TODO REMOVE THIS! Install non pre-release version of mpmath.
run: pip install "mpmath<1.4"

- name: Install torch nightly build
run: pip install --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
runner: ["linux.12xlarge"]
gpu-arch-type: ["cpu"]
include:
Expand Down Expand Up @@ -51,6 +52,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
runner: ["macos-12"]
include:
- python-version: "3.8"
Expand Down Expand Up @@ -81,6 +83,7 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
runner: ["windows.4xlarge"]
gpu-arch-type: ["cpu"]
include:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/models/ssdlite.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The following model builders can be used to instantiate a SSD Lite model, with o
without pre-trained weights. All the model builders internally rely on the
``torchvision.models.detection.ssd.SSD`` base class. Please refer to the `source
code
<https://github.com/pytorch/vision/blob/main/torchvision/models/detection/ssd.py>`_ for
<https://github.com/pytorch/vision/blob/main/torchvision/models/detection/ssdlite.py>`_ for
more details about this class.

.. autosummary::
Expand Down
7 changes: 6 additions & 1 deletion docs/source/transforms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ Color
v2.RandomChannelPermutation
v2.RandomPhotometricDistort
v2.Grayscale
v2.RGB
v2.RandomGrayscale
v2.GaussianBlur
v2.RandomInvert
Expand All @@ -364,6 +365,7 @@ Functionals

v2.functional.permute_channels
v2.functional.rgb_to_grayscale
v2.functional.grayscale_to_rgb
v2.functional.to_grayscale
v2.functional.gaussian_blur
v2.functional.invert
Expand Down Expand Up @@ -405,6 +407,7 @@ Miscellaneous
v2.SanitizeBoundingBoxes
v2.ClampBoundingBoxes
v2.UniformTemporalSubsample
v2.JPEG

Functionals

Expand All @@ -414,8 +417,10 @@ Functionals

v2.functional.normalize
v2.functional.erase
v2.functional.sanitize_bounding_boxes
v2.functional.clamp_bounding_boxes
v2.functional.uniform_temporal_subsample
v2.functional.jpeg

.. _conversion_transforms:

Expand Down Expand Up @@ -583,7 +588,7 @@ Conversion
while performing the conversion, while some may not do any scaling. By
scaling, we mean e.g. that a ``uint8`` -> ``float32`` would map the [0,
255] range into [0, 1] (and vice-versa). See :ref:`range_and_dtype`.

.. autosummary::
:toctree: generated/
:template: class.rst
Expand Down
4 changes: 2 additions & 2 deletions gallery/transforms/plot_transforms_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@
# We need a custom collation function here, since the object detection
# models expect a sequence of images and target dictionaries. The default
# collation function tries to torch.stack() the individual elements,
# which fails in general for object detection, because the number of bouding
# boxes varies between the images of a same batch.
# which fails in general for object detection, because the number of bounding
# boxes varies between the images of the same batch.
collate_fn=lambda batch: tuple(zip(*batch)),
)

Expand Down
11 changes: 11 additions & 0 deletions gallery/transforms/plot_transforms_illustrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@
equalized_imgs = [equalizer(orig_img) for _ in range(4)]
plot([orig_img] + equalized_imgs)

# %%
# JPEG
# ~~~~~~~~~~~~~~
# The :class:`~torchvision.transforms.v2.JPEG` transform
# (see also :func:`~torchvision.transforms.v2.functional.jpeg`)
# applies JPEG compression to the given image with random
# degree of compression.
jpeg = v2.JPEG((5, 50))
jpeg_imgs = [jpeg(orig_img) for _ in range(4)]
plot([orig_img] + jpeg_imgs)

# %%
# Augmentation Transforms
# -----------------------
Expand Down
2 changes: 1 addition & 1 deletion maintainer_guide.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Torchvision maintainers guide
# Torchvision maintainers guide

This document aims at documenting user-facing policies / principles used when
developing and maintaining torchvision. Other maintainer info (e.g. release
Expand Down
74 changes: 28 additions & 46 deletions scripts/release_notes/classify_prs.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,22 @@
# In[1]:

# imports and set configuration
import pandas as pd
from retrieve_prs_data import run

exclude_prototype = True
data_filename = "10.0_to_11.0-rc2.json"
previous_release = "v10.0"
current_release = "v11.0-rc2"

# In[2]:


data_filename = "data.json"
df = pd.read_json(data_filename).T
df.tail()


# In[3]:


all_labels = {lbl for labels in df["labels"] for lbl in labels}
all_labels


# In[4]:


# Add one column per label
for label in all_labels:
df[label] = df["labels"].apply(lambda labels_list: label in labels_list)
df.head()


# In[5]:


# Add a clean "module" column. It contains tuples since PRs can have more than one module.
# Maybe we should include "topics" in that column as well?

Expand All @@ -51,37 +33,26 @@
df["module"] = df.module.apply(tuple)
df.head()


# In[6]:


mod_df = df.set_index("module").sort_index()
mod_df.tail()


# In[7]:


# All improvement PRs
mod_df[mod_df["enhancement"]].head()


# In[8]:


# improvement f module
# note: don't filter module name on the index as the index contain tuples with non-exclusive values
# Use the boolean column instead
mod_df[mod_df["enhancement"] & mod_df["module: transforms"]]


# In[9]:


def format_prs(mod_df):
def format_prs(mod_df, exclude_prototype=True):
out = []
for idx, row in mod_df.iterrows():
if exclude_prototype and row["prototype"]:
if exclude_prototype and "prototype" in row and row["prototype"]:
continue
modules = idx
# Put "documentation" and "tests" first for sorting to be dece
Expand All @@ -98,8 +69,6 @@ def format_prs(mod_df):


# In[10]:


included_prs = pd.DataFrame()

# If labels are accurate, this shouhld generate most of the release notes already
Expand All @@ -112,27 +81,40 @@ def format_prs(mod_df):
("Bug Fixes", "bug"),
("Code Quality", "code quality"),
):
print(f"## {section_title}")
print()
tmp_df = mod_df[mod_df[module_idx]]
included_prs = pd.concat([included_prs, tmp_df])
print(format_prs(tmp_df))
print()
if module_idx in mod_df:
print(f"## {section_title}")
print()
tmp_df = mod_df[mod_df[module_idx]]
included_prs = pd.concat([included_prs, tmp_df])
print(format_prs(tmp_df))
print()


# In[11]:


# Missing PRs are these ones... classify them manually
missing_prs = pd.concat([mod_df, included_prs]).drop_duplicates(subset="pr_number", keep=False)
print(format_prs(missing_prs))

# In[12]:

# Generate list of contributors
print()
print("## Contributors")

command_to_run = f"{{ git shortlog -s {previous_release}..{current_release} | cut -f2- & git log -s {previous_release}..{current_release} | grep Co-authored | cut -f2- -d: | cut -f1 -d\\< | sed 's/^ *//;s/ *$//' ; }} | sort --ignore-case | uniq | tr '\\n' ';' | sed 's/;/, /g;s/, $//' | fold -s"
rc, output, err = run(command_to_run)
print(output)
previous_release = "c35d3855ccbfa6a36e6ae6337a1f2c721c1f1e78"
current_release = "5181a854d8b127cf465cd22a67c1b5aaf6ccae05"
print(
f"{{ git shortlog -s {previous_release}..{current_release} | cut -f2- & git log -s {previous_release}..{current_release} | grep Co-authored | cut -f2- -d: | cut -f1 -d\\< | sed 's/^ *//;s/ *//' ; }} | sort --ignore-case | uniq | tr '\\n' ';' | sed 's/;/, /g;s/,//' | fold -s"
)

# In[13]:
# Utility to extract PR numbers only from multiple lines, useful to bundle all
# the docs changes for example:
import re

s = """
[] Remove unnecessary dependency from macOS/Conda binaries (#8077)
[rocm] [ROCm] remove HCC references (#8070)
"""

print(", ".join(re.findall("(#\\d+)", s)))
26 changes: 26 additions & 0 deletions test/test_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,11 @@ def test_transforms_v2_wrapper_spawn(self):
with self.create_dataset(transform=v2.Resize(size=expected_size)) as (dataset, _):
datasets_utils.check_transforms_v2_wrapper_spawn(dataset, expected_size=expected_size)

def test_slice_error(self):
with self.create_dataset() as (dataset, _):
with pytest.raises(ValueError, match="Index must be of type integer"):
dataset[:2]


class CocoCaptionsTestCase(CocoDetectionTestCase):
DATASET_CLASS = datasets.CocoCaptions
Expand Down Expand Up @@ -1620,6 +1625,10 @@ def inject_fake_data(self, tmpdir, config):
num_examples_total += num_examples
classes.append(cls)

if config.pop("make_empty_class", False):
os.makedirs(pathlib.Path(tmpdir) / "empty_class")
classes.append("empty_class")

return dict(num_examples=num_examples_total, classes=classes)

def _file_name_fn(self, cls, ext, idx):
Expand All @@ -1644,6 +1653,23 @@ def test_classes(self, config):
assert len(dataset.classes) == len(info["classes"])
assert all([a == b for a, b in zip(dataset.classes, info["classes"])])

def test_allow_empty(self):
config = {
"extensions": self._EXTENSIONS,
"make_empty_class": True,
}

config["allow_empty"] = True
with self.create_dataset(config) as (dataset, info):
assert "empty_class" in dataset.classes
assert len(dataset.classes) == len(info["classes"])
assert all([a == b for a, b in zip(dataset.classes, info["classes"])])

config["allow_empty"] = False
with pytest.raises(FileNotFoundError, match="Found no valid file"):
with self.create_dataset(config) as (dataset, info):
pass


class ImageFolderTestCase(datasets_utils.ImageDatasetTestCase):
DATASET_CLASS = datasets.ImageFolder
Expand Down
16 changes: 5 additions & 11 deletions test/test_datasets_download.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import contextlib
import itertools
import shutil
import tempfile
import time
import traceback
import unittest.mock
import warnings
from datetime import datetime
from distutils import dir_util
from os import path
from urllib.error import HTTPError, URLError
from urllib.parse import urlparse
Expand Down Expand Up @@ -180,7 +180,7 @@ def collect_urls(dataset_cls, *args, **kwargs):
@pytest.fixture(scope="module", autouse=True)
def root():
yield ROOT
dir_util.remove_tree(ROOT)
shutil.rmtree(ROOT)


def places365():
Expand Down Expand Up @@ -327,12 +327,6 @@ def kitti():
)


def stanford_cars():
return itertools.chain.from_iterable(
[collect_urls(datasets.StanfordCars, ROOT, split=split, download=True) for split in ["train", "test"]]
)


def url_parametrization(*dataset_urls_and_ids_fns):
return pytest.mark.parametrize(
"url",
Expand Down Expand Up @@ -378,9 +372,9 @@ def test_url_is_accessible(url):
retry(lambda: assert_url_is_accessible(url))


@url_parametrization(
stanford_cars, # https://github.com/pytorch/vision/issues/7545
)
# TODO: if e.g. caltech101 starts failing, remove the pytest.mark.parametrize below and use
# @url_parametrization(caltech101)
@pytest.mark.parametrize("url", ("http://url_that_doesnt_exist.com",)) # here until we actually have a failing dataset
@pytest.mark.xfail
def test_url_is_not_accessible(url):
"""
Expand Down
Loading

0 comments on commit 2d3c99b

Please sign in to comment.