Skip to content

Commit

Permalink
Merge branch 'main' into prototype/multiweight_cleanup2
Browse files Browse the repository at this point in the history
  • Loading branch information
datumbox authored Nov 24, 2021
2 parents 1172e1f + 8d25de7 commit fc7a23b
Show file tree
Hide file tree
Showing 47 changed files with 644 additions and 370 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml

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

2 changes: 1 addition & 1 deletion .circleci/config.yml.in
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ jobs:
conda env remove -n python${PYTHON_VERSION} || true
conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION}
conda activate python${PYTHON_VERSION}
conda install Pillow>=5.3.0
conda install "Pillow>=5.3.0,!=8.3.*"
conda install -v -y -c pytorch-nightly pytorch
conda install -v -y $(ls ~/workspace/torchvision*.tar.bz2)
- run:
Expand Down
6 changes: 3 additions & 3 deletions .circleci/smoke_test/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ RUN conda create -y --name python3.7 python=3.7
RUN conda create -y --name python3.8 python=3.8
SHELL [ "/bin/bash", "-c" ]
RUN echo "source /usr/local/etc/profile.d/conda.sh" >> ~/.bashrc
RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y Pillow>=5.3.0
RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y Pillow>=5.3.0
RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.8 && conda install -y Pillow>=5.3.0
RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y "Pillow>=5.3.0,!=8.3.*"
RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y "Pillow>=5.3.0,!=8.3.*"
RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.8 && conda install -y "Pillow>=5.3.0,!=8.3.*"
CMD [ "/bin/bash"]
2 changes: 1 addition & 1 deletion .circleci/unittest/linux/scripts/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ dependencies:
- ca-certificates
- pip:
- future
- pillow >=5.3.0, !=8.3.0
- pillow >=5.3.0, !=8.3.*
- scipy
- av
2 changes: 1 addition & 1 deletion .circleci/unittest/linux/scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fi
if [ $PYTHON_VERSION == "3.6" ]; then
printf "Installing minimal PILLOW version\n"
# Install the minimal PILLOW version. Otherwise, let setup.py install the latest
pip install pillow>=5.3.0
pip install "pillow>=5.3.0,!=8.3.*"
fi

printf "* Installing torchvision\n"
Expand Down
2 changes: 1 addition & 1 deletion .circleci/unittest/windows/scripts/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
- ca-certificates
- pip:
- future
- pillow >=5.3.0, !=8.3.0
- pillow >=5.3.0, !=8.3.*
- scipy
- av
- dataclasses
2 changes: 1 addition & 1 deletion .circleci/unittest/windows/scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge "pytorch-${UPLOAD
if [ $PYTHON_VERSION == "3.6" ]; then
printf "Installing minimal PILLOW version\n"
# Install the minimal PILLOW version. Otherwise, let setup.py install the latest
pip install pillow>=5.3.0
pip install "pillow>=5.3.0,!=8.3.*"
fi

torch_cuda=$(python -c "import torch; print(torch.cuda.is_available())")
Expand Down
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ABI_FILTERS=armeabi-v7a,arm64-v8a,x86,x86_64

VERSION_NAME=0.10.0-SNAPSHOT
VERSION_NAME=0.12.0-SNAPSHOT
GROUP=org.pytorch
MAVEN_GROUP=org.pytorch
SONATYPE_STAGING_PROFILE=orgpytorch
Expand Down
4 changes: 2 additions & 2 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ warn_unreachable = True
; miscellaneous strictness flags
allow_redefinition = True

[mypy-torchvision.io._video_opt.*]
[mypy-torchvision.io.image.*]

ignore_errors = True

[mypy-torchvision.io.*]
[mypy-torchvision.io.video.*]

ignore_errors = True

Expand Down
2 changes: 1 addition & 1 deletion packaging/build_cmake.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ setup_conda_pytorch_constraint
setup_conda_cudatoolkit_plain_constraint

if [[ "$OSTYPE" == "msys" ]]; then
conda install -yq conda-build cmake pillow>=5.3.0 future
conda install -yq conda-build cmake "pillow>=5.3.0,!=8.3.*" future
pip install dataclasses
fi

Expand Down
2 changes: 1 addition & 1 deletion packaging/torchvision/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ requirements:
- libpng
- ffmpeg >=4.2 # [not win]
- jpeg
- pillow >=5.3.0
- pillow >=5.3.0, !=8.3.*
- pytorch-mutex 1.0 {{ build_variant }} # [not osx ]
{{ environ.get('CONDA_PYTORCH_CONSTRAINT') }}
{{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT', '') }}
Expand Down
2 changes: 1 addition & 1 deletion references/classification/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ the following parameters:
### AlexNet and VGG

Since `AlexNet` and the original `VGG` architectures do not include batch
normalization, the default initial learning rate `--lr 0.1` is to high.
normalization, the default initial learning rate `--lr 0.1` is too high.

```
torchrun --nproc_per_node=8 train.py\
Expand Down
4 changes: 2 additions & 2 deletions references/classification/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ def train_one_epoch(model, criterion, optimizer, data_loader, device, epoch, arg
for i, (image, target) in enumerate(metric_logger.log_every(data_loader, args.print_freq, header)):
start_time = time.time()
image, target = image.to(device), target.to(device)
with torch.cuda.amp.autocast(enabled=args.amp):
with torch.cuda.amp.autocast(enabled=scaler is not None):
output = model(image)
loss = criterion(output, target)

optimizer.zero_grad()
if args.amp:
if scaler is not None:
scaler.scale(loss).backward()
if args.clip_grad_norm is not None:
# we should unscale the gradients of optimizer's assigned params if do gradient clipping
Expand Down
5 changes: 3 additions & 2 deletions references/classification/train_quantization.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def main(args):
if args.distributed:
train_sampler.set_epoch(epoch)
print("Starting training for epoch", epoch)
train_one_epoch(model, criterion, optimizer, data_loader, device, epoch, args.print_freq)
train_one_epoch(model, criterion, optimizer, data_loader, device, epoch, args)
lr_scheduler.step()
with torch.inference_mode():
if epoch >= args.num_observer_update_epochs:
Expand All @@ -132,7 +132,7 @@ def main(args):
model.apply(torch.nn.intrinsic.qat.freeze_bn_stats)
print("Evaluate QAT model")

evaluate(model, criterion, data_loader_test, device=device)
evaluate(model, criterion, data_loader_test, device=device, log_suffix="QAT")
quantized_eval_model = copy.deepcopy(model_without_ddp)
quantized_eval_model.eval()
quantized_eval_model.to(torch.device("cpu"))
Expand Down Expand Up @@ -261,6 +261,7 @@ def get_args_parser(add_help=True):
parser.add_argument(
"--train-crop-size", default=224, type=int, help="the random crop size used for training (default: 224)"
)
parser.add_argument("--clip-grad-norm", default=None, type=float, help="the maximum gradient norm (default None)")

# Prototype models only
parser.add_argument("--weights", default=None, type=str, help="the weights enum name to load")
Expand Down
20 changes: 3 additions & 17 deletions test/builtin_dataset_mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from torch.testing import make_tensor as _make_tensor
from torchdata.datapipes.iter import IterDataPipe
from torchvision.prototype import datasets
from torchvision.prototype.datasets._api import DEFAULT_DECODER_MAP, DEFAULT_DECODER
from torchvision.prototype.datasets._api import find
from torchvision.prototype.utils._internal import add_suggestion

Expand Down Expand Up @@ -99,28 +100,16 @@ def _get(self, dataset, config):
self._cache[(name, config)] = mock_resources, mock_info
return mock_resources, mock_info

def _decoder(self, dataset_type):
def to_bytes(file):
try:
return file.read()
finally:
file.close()

if dataset_type == datasets.utils.DatasetType.RAW:
return datasets.decoder.raw
else:
return to_bytes

def load(
self, name: str, decoder=DEFAULT_TEST_DECODER, split="train", **options: Any
self, name: str, decoder=DEFAULT_DECODER, split="train", **options: Any
) -> Tuple[IterDataPipe, Dict[str, Any]]:
dataset = find(name)
config = dataset.info.make_config(split=split, **options)
resources, mock_info = self._get(dataset, config)
datapipe = dataset._make_datapipe(
[resource.to_datapipe() for resource in resources],
config=config,
decoder=self._decoder(dataset.info.type) if decoder is DEFAULT_TEST_DECODER else decoder,
decoder=DEFAULT_DECODER_MAP.get(dataset.info.type) if decoder is DEFAULT_DECODER else decoder,
)
return datapipe, mock_info

Expand Down Expand Up @@ -155,9 +144,6 @@ def _big_endian_dtype(dtype):
@classmethod
def _create_binary_file(cls, root, filename, *, num_samples, shape, dtype, compressor, low=0, high):
with compressor(root / filename, "wb") as fh:
if dtype != torch.uint8:
print()

for meta in (cls._magic(dtype, len(shape)), num_samples, *shape):
fh.write(cls._encode(meta))

Expand Down
9 changes: 1 addition & 8 deletions test/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,7 @@ def get_export_import_copy(m):
with freeze_rng_state():
results_from_imported = m_import(*args)
tol = 3e-4
try:
torch.testing.assert_close(results, results_from_imported, atol=tol, rtol=tol)
except ValueError:
# custom check for the models that return named tuples:
# we compare field by field while ignoring None as assert_close can't handle None
for a, b in zip(results, results_from_imported):
if a is not None:
torch.testing.assert_close(a, b, atol=tol, rtol=tol)
torch.testing.assert_close(results, results_from_imported, atol=tol, rtol=tol)

TEST_WITH_SLOW = os.getenv("PYTORCH_TEST_WITH_SLOW", "0") == "1"
if not TEST_WITH_SLOW or skip:
Expand Down
79 changes: 44 additions & 35 deletions test/test_prototype_builtin_datasets.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,51 @@
import functools
import io

import builtin_dataset_mocks
import pytest
from torch.utils.data.graph import traverse
from torchdata.datapipes.iter import IterDataPipe
from torchvision.prototype import datasets
from torchvision.prototype import datasets, features
from torchvision.prototype.datasets._api import DEFAULT_DECODER
from torchvision.prototype.utils._internal import sequence_to_str


_loaders = []
_datasets = []

# TODO: this can be replaced by torchvision.prototype.datasets.list() as soon as all builtin datasets are supported
TMP = [
"mnist",
"fashionmnist",
"kmnist",
"emnist",
"qmnist",
"cifar10",
"cifar100",
"caltech256",
"caltech101",
"imagenet",
]
for name in TMP:
loader = functools.partial(builtin_dataset_mocks.load, name)
_loaders.append(pytest.param(loader, id=name))

info = datasets.info(name)
_datasets.extend(
[
pytest.param(*loader(**config), id=f"{name}-{'-'.join([str(value) for value in config.values()])}")
for config in info._configs
]
)
def to_bytes(file):
return file.read()


def dataset_parametrization(*names, decoder=to_bytes):
if not names:
# TODO: Replace this with torchvision.prototype.datasets.list() as soon as all builtin datasets are supported
names = (
"mnist",
"fashionmnist",
"kmnist",
"emnist",
"qmnist",
"cifar10",
"cifar100",
"caltech256",
"caltech101",
"imagenet",
)

loaders = pytest.mark.parametrize("loader", _loaders)
builtin_datasets = pytest.mark.parametrize(("dataset", "mock_info"), _datasets)
params = []
for name in names:
for config in datasets.info(name)._configs:
id = f"{name}-{'-'.join([str(value) for value in config.values()])}"
dataset, mock_info = builtin_dataset_mocks.load(name, decoder=decoder, **config)
params.append(pytest.param(dataset, mock_info, id=id))

return pytest.mark.parametrize(("dataset", "mock_info"), params)


class TestCommon:
@builtin_datasets
@dataset_parametrization()
def test_smoke(self, dataset, mock_info):
if not isinstance(dataset, IterDataPipe):
raise AssertionError(f"Loading the dataset should return an IterDataPipe, but got {type(dataset)} instead.")

@builtin_datasets
@dataset_parametrization()
def test_sample(self, dataset, mock_info):
try:
sample = next(iter(dataset))
Expand All @@ -59,15 +58,15 @@ def test_sample(self, dataset, mock_info):
if not sample:
raise AssertionError("Sample dictionary is empty.")

@builtin_datasets
@dataset_parametrization()
def test_num_samples(self, dataset, mock_info):
num_samples = 0
for _ in dataset:
num_samples += 1

assert num_samples == mock_info["num_samples"]

@builtin_datasets
@dataset_parametrization()
def test_decoding(self, dataset, mock_info):
undecoded_features = {key for key, value in next(iter(dataset)).items() if isinstance(value, io.IOBase)}
if undecoded_features:
Expand All @@ -76,6 +75,16 @@ def test_decoding(self, dataset, mock_info):
f"{sequence_to_str(sorted(undecoded_features), separate_last='and ')} were not decoded."
)

@dataset_parametrization(decoder=DEFAULT_DECODER)
def test_at_least_one_feature(self, dataset, mock_info):
sample = next(iter(dataset))
if not any(isinstance(value, features.Feature) for value in sample.values()):
raise AssertionError("The sample contained no feature.")

@dataset_parametrization()
def test_traversable(self, dataset, mock_info):
traverse(dataset)


class TestQMNIST:
@pytest.mark.parametrize(
Expand Down
Loading

0 comments on commit fc7a23b

Please sign in to comment.