diff --git a/.gitignore b/.gitignore index 9bce9eb..0447b8b 100644 --- a/.gitignore +++ b/.gitignore @@ -113,4 +113,4 @@ venv.bak/ dmypy.json # Pyre type checker -.pyre/ \ No newline at end of file +.pyre/ diff --git a/CHANGELOG.md b/CHANGELOG.md index f43fc39..91547cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,37 +4,37 @@ ### Added -* Add argument `--save-stats` allowing to compute dataset statistics and save them as an `.npz` file ([#80](https://github.com/mseitzer/pytorch-fid/pull/80)). The `.npz` file can be used in subsequent FID computations instead of recomputing the dataset statistics. This option can be used in the following way: `python -m pytorch_fid --save-stats path/to/dataset path/to/outputfile`. +- Add argument `--save-stats` allowing to compute dataset statistics and save them as an `.npz` file ([#80](https://github.com/mseitzer/pytorch-fid/pull/80)). The `.npz` file can be used in subsequent FID computations instead of recomputing the dataset statistics. This option can be used in the following way: `python -m pytorch_fid --save-stats path/to/dataset path/to/outputfile`. ### Fixed -* Do not use `os.sched_getaffinity` to get number of available CPUs on Windows, as it is not available there ([232b3b14](https://github.com/mseitzer/pytorch-fid/commit/232b3b1468800102fcceaf6f2bb8977811fc991a), [#84](https://github.com/mseitzer/pytorch-fid/issues/84)). -* Do not use Inception model argument `pretrained`, as it was deprecated in torchvision 0.13 ([#88](https://github.com/mseitzer/pytorch-fid/pull/88)). +- Do not use `os.sched_getaffinity` to get number of available CPUs on Windows, as it is not available there ([232b3b14](https://github.com/mseitzer/pytorch-fid/commit/232b3b1468800102fcceaf6f2bb8977811fc991a), [#84](https://github.com/mseitzer/pytorch-fid/issues/84)). +- Do not use Inception model argument `pretrained`, as it was deprecated in torchvision 0.13 ([#88](https://github.com/mseitzer/pytorch-fid/pull/88)). ## [0.2.1] - 2021-10-10 ### Added -* Add argument `--num-workers` to select number of dataloader processes ([#66](https://github.com/mseitzer/pytorch-fid/pull/66)). Defaults to 8 or the number of available CPUs if less than 8 CPUs are available. +- Add argument `--num-workers` to select number of dataloader processes ([#66](https://github.com/mseitzer/pytorch-fid/pull/66)). Defaults to 8 or the number of available CPUs if less than 8 CPUs are available. ### Fixed -* Fixed package setup to work under Windows ([#55](https://github.com/mseitzer/pytorch-fid/pull/55), [#72](https://github.com/mseitzer/pytorch-fid/issues/72)) +- Fixed package setup to work under Windows ([#55](https://github.com/mseitzer/pytorch-fid/pull/55), [#72](https://github.com/mseitzer/pytorch-fid/issues/72)) ## [0.2.0] - 2020-11-30 ### Added -* Load images using a Pytorch dataloader, which should result in a speed-up. ([#47](https://github.com/mseitzer/pytorch-fid/pull/47)) -* Support more image extensions ([#53](https://github.com/mseitzer/pytorch-fid/pull/53)) -* Improve tooling by setting up Nox, add linting and test support ([#52](https://github.com/mseitzer/pytorch-fid/pull/52)) -* Add some unit tests +- Load images using a Pytorch dataloader, which should result in a speed-up. ([#47](https://github.com/mseitzer/pytorch-fid/pull/47)) +- Support more image extensions ([#53](https://github.com/mseitzer/pytorch-fid/pull/53)) +- Improve tooling by setting up Nox, add linting and test support ([#52](https://github.com/mseitzer/pytorch-fid/pull/52)) +- Add some unit tests ## [0.1.1] - 2020-08-16 ### Fixed -* Fixed software license string in `setup.py` +- Fixed software license string in `setup.py` ## [0.1.0] - 2020-08-16 diff --git a/README.md b/README.md index 607cbbe..874f84b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ FID is calculated by computing the [Fréchet distance](https://en.wikipedia.org/ Further insights and an independent evaluation of the FID score can be found in [Are GANs Created Equal? A Large-Scale Study](https://arxiv.org/abs/1711.10337). -The weights and the model are exactly the same as in [the official Tensorflow implementation](https://github.com/bioinf-jku/TTUR), and were tested to give very similar results (e.g. `.08` absolute error and `0.0009` relative error on LSUN, using ProGAN generated images). However, due to differences in the image interpolation implementation and library backends, FID results still differ slightly from the original implementation. So if you report FID scores in your paper, and you want them to be *exactly comparable* to FID scores reported in other papers, you should consider using [the official Tensorflow implementation](https://github.com/bioinf-jku/TTUR). +The weights and the model are exactly the same as in [the official Tensorflow implementation](https://github.com/bioinf-jku/TTUR), and were tested to give very similar results (e.g. `.08` absolute error and `0.0009` relative error on LSUN, using ProGAN generated images). However, due to differences in the image interpolation implementation and library backends, FID results still differ slightly from the original implementation. So if you report FID scores in your paper, and you want them to be _exactly comparable_ to FID scores reported in other papers, you should consider using [the official Tensorflow implementation](https://github.com/bioinf-jku/TTUR). ## Installation @@ -22,6 +22,7 @@ pip install pytorch-fid ``` Requirements: + - python3 - pytorch - torchvision @@ -32,6 +33,7 @@ Requirements: ## Usage To compute the FID score between two datasets, where images of each dataset are contained in an individual folder: + ``` python -m pytorch_fid path/to/dataset1 path/to/dataset2 ``` @@ -49,14 +51,17 @@ The resulting scores might also no longer correlate with visual quality. You can select the dimensionality of features to use with the flag `--dims N`, where N is the dimensionality of features. The choices are: -- 64: first max pooling features -- 192: second max pooling features -- 768: pre-aux classifier features + +- 64: first max pooling features +- 192: second max pooling features +- 768: pre-aux classifier features - 2048: final average pooling features (this is the default) ## Generating a compatible `.npz` archive from a dataset + A frequent use case will be to compare multiple models against an original dataset. To save training multiple times on the original dataset, there is also the ability to generate a compatible `.npz` archive from a dataset. This is done using any combination of the previously mentioned arguments with the addition of the `--save-stats` flag. For example: + ``` python -m pytorch_fid --save-stats path/to/dataset path/to/outputfile ``` diff --git a/src/pytorch_fid/fid_score.py b/src/pytorch_fid/fid_score.py index 9c8acb2..cdaf0e1 100755 --- a/src/pytorch_fid/fid_score.py +++ b/src/pytorch_fid/fid_score.py @@ -136,10 +136,8 @@ def get_activations( if batch_size > len(files): print( - ( - "Warning: batch size is bigger than the data size. " - "Setting batch size to data size" - ) + "Warning: batch size is bigger than the data size. " + "Setting batch size to data size" ) batch_size = len(files) @@ -228,7 +226,7 @@ def calculate_frechet_distance(mu1, sigma1, mu2, sigma2, eps=1e-6): if np.iscomplexobj(covmean): if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3): m = np.max(np.abs(covmean.imag)) - raise ValueError("Imaginary component {}".format(m)) + raise ValueError(f"Imaginary component {m}") covmean = covmean.real tr_covmean = np.trace(covmean) @@ -269,7 +267,7 @@ def compute_statistics_of_path(path, model, batch_size, dims, device, num_worker else: path = pathlib.Path(path) files = sorted( - [file for ext in IMAGE_EXTENSIONS for file in path.glob("*.{}".format(ext))] + [file for ext in IMAGE_EXTENSIONS for file in path.glob(f"*.{ext}")] ) m, s = calculate_activation_statistics( files, model, batch_size, dims, device, num_workers diff --git a/src/pytorch_fid/inception.py b/src/pytorch_fid/inception.py index a6fb465..993a381 100644 --- a/src/pytorch_fid/inception.py +++ b/src/pytorch_fid/inception.py @@ -66,7 +66,7 @@ def __init__( strongly advised to set this parameter to true to get comparable results. """ - super(InceptionV3, self).__init__() + super().__init__() self.resize_input = resize_input self.normalize_input = normalize_input @@ -221,7 +221,7 @@ class FIDInceptionA(torchvision.models.inception.InceptionA): """InceptionA block patched for FID computation""" def __init__(self, in_channels, pool_features): - super(FIDInceptionA, self).__init__(in_channels, pool_features) + super().__init__(in_channels, pool_features) def forward(self, x): branch1x1 = self.branch1x1(x) @@ -248,7 +248,7 @@ class FIDInceptionC(torchvision.models.inception.InceptionC): """InceptionC block patched for FID computation""" def __init__(self, in_channels, channels_7x7): - super(FIDInceptionC, self).__init__(in_channels, channels_7x7) + super().__init__(in_channels, channels_7x7) def forward(self, x): branch1x1 = self.branch1x1(x) @@ -278,7 +278,7 @@ class FIDInceptionE_1(torchvision.models.inception.InceptionE): """First InceptionE block patched for FID computation""" def __init__(self, in_channels): - super(FIDInceptionE_1, self).__init__(in_channels) + super().__init__(in_channels) def forward(self, x): branch1x1 = self.branch1x1(x) @@ -313,7 +313,7 @@ class FIDInceptionE_2(torchvision.models.inception.InceptionE): """Second InceptionE block patched for FID computation""" def __init__(self, in_channels): - super(FIDInceptionE_2, self).__init__(in_channels) + super().__init__(in_channels) def forward(self, x): branch1x1 = self.branch1x1(x) diff --git a/tests/test_fid_score.py b/tests/test_fid_score.py index 4e4b6a1..a93a885 100644 --- a/tests/test_fid_score.py +++ b/tests/test_fid_score.py @@ -53,7 +53,7 @@ def test_compute_statistics_of_path(mocker, tmp_path, device): paths = [] for idx, image in enumerate(images): - paths.append(str(tmp_path / "{}.png".format(idx))) + paths.append(str(tmp_path / f"{idx}.png")) Image.fromarray(image, mode="RGB").save(paths[-1]) stats = fid_score.compute_statistics_of_path( @@ -93,7 +93,7 @@ def test_image_types(tmp_path): paths = [] for ext in fid_score.IMAGE_EXTENSIONS: - paths.append(str(tmp_path / "img.{}".format(ext))) + paths.append(str(tmp_path / f"img.{ext}")) in_image.save(paths[-1]) dataset = fid_score.ImagePathDataset(paths)