File size: 6,646 Bytes
8ca3a29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# python3.7
"""Unit test for loading pre-trained models.

Basically, this file tests whether the perceptual model (VGG16) and the
inception model (InceptionV3), which are commonly used for loss computation and
evaluation, have the expected behavior after loading pre-trained weights. In
particular, we compare with the models from repo

https://github.com/NVlabs/stylegan2-ada-pytorch
"""

import torch

from models import build_model
from utils.misc import download_url

__all__ = ['test_model']

_BATCH_SIZE = 4
# pylint: disable=line-too-long
_PERCEPTUAL_URL = 'https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/metrics/vgg16.pt'
_INCEPTION_URL = 'https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/metrics/inception-2015-12-05.pt'
# pylint: enable=line-too-long


def test_model():
    """Collects all model tests."""
    torch.backends.cudnn.enabled = True
    torch.backends.cudnn.allow_tf32 = False
    torch.backends.cuda.matmul.allow_tf32 = False
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True
    print('========== Start Model Test ==========')
    test_perceptual()
    test_inception()
    print('========== Finish Model Test ==========')


def test_perceptual():
    """Test the perceptual model."""
    print('===== Testing Perceptual Model =====')

    print('Build test model.')
    model = build_model('PerceptualModel',
                        use_torchvision=False,
                        no_top=False,
                        enable_lpips=True)

    print('Build reference model.')
    ref_model_path, _, = download_url(_PERCEPTUAL_URL)
    with open(ref_model_path, 'rb') as f:
        ref_model = torch.jit.load(f).eval().cuda()

    print('Test performance: ')
    for size in [224, 128, 256, 512, 1024]:
        raw_img = torch.randint(0, 256, size=(_BATCH_SIZE, 3, size, size))
        raw_img_comp = torch.randint(0, 256, size=(_BATCH_SIZE, 3, size, size))

        # The test model requires input images to have range [-1, 1].
        img = raw_img.to(torch.float32).cuda() / 127.5 - 1
        img_comp = raw_img_comp.to(torch.float32).cuda() / 127.5 - 1
        feat = model(img, resize_input=True, return_tensor='feature')
        pred = model(img, resize_input=True, return_tensor='prediction')
        lpips = model(img, img_comp, resize_input=False, return_tensor='lpips')
        assert feat.shape == (_BATCH_SIZE, 4096)
        assert pred.shape == (_BATCH_SIZE, 1000)
        assert lpips.shape == (_BATCH_SIZE,)

        # The reference model requires input images to have range [0, 255].
        img = raw_img.to(torch.float32).cuda()
        img_comp = raw_img_comp.to(torch.float32).cuda()
        ref_feat = ref_model(img, resize_images=True, return_features=True)
        ref_pred = ref_model(img, resize_images=True, return_features=False)
        temp = ref_model(torch.cat([img, img_comp], dim=0),
                         resize_images=False, return_lpips=True).chunk(2)
        ref_lpips = (temp[0] - temp[1]).square().sum(dim=1, keepdim=False)
        assert ref_feat.shape == (_BATCH_SIZE, 4096)
        assert ref_pred.shape == (_BATCH_SIZE, 1000)
        assert ref_lpips.shape == (_BATCH_SIZE,)

        print(f'    Size {size}x{size}, feature (with resize):\n        '
              f'mean: {(feat - ref_feat).abs().mean().item():.3e}, '
              f'max: {(feat - ref_feat).abs().max().item():.3e}, '
              f'ref_mean: {ref_feat.abs().mean().item():.3e}, '
              f'ref_max: {ref_feat.abs().max().item():.3e}.')
        print(f'    Size {size}x{size}, prediction (with resize):\n        '
              f'mean: {(pred - ref_pred).abs().mean().item():.3e}, '
              f'max: {(pred - ref_pred).abs().max().item():.3e}, '
              f'ref_mean: {ref_pred.abs().mean().item():.3e}, '
              f'ref_max: {ref_pred.abs().max().item():.3e}.')
        print(f'    Size {size}x{size}, LPIPS (without resize):\n        '
              f'mean: {(lpips - ref_lpips).abs().mean().item():.3e}, '
              f'max: {(lpips - ref_lpips).abs().max().item():.3e}, '
              f'ref_mean: {ref_lpips.abs().mean().item():.3e}, '
              f'ref_max: {ref_lpips.abs().max().item():.3e}.')


def test_inception():
    """Test the inception model."""
    print('===== Testing Inception Model =====')

    print('Build test model.')
    model = build_model('InceptionModel', align_tf=True)

    print('Build reference model.')
    ref_model_path, _, = download_url(_INCEPTION_URL)
    with open(ref_model_path, 'rb') as f:
        ref_model = torch.jit.load(f).eval().cuda()

    print('Test performance: ')
    for size in [299, 128, 256, 512, 1024]:
        raw_img = torch.randint(0, 256, size=(_BATCH_SIZE, 3, size, size))

        # The test model requires input images to have range [-1, 1].
        img = raw_img.to(torch.float32).cuda() / 127.5 - 1
        feat = model(img)
        pred = model(img, output_predictions=True)
        pred_nb = model(img, output_predictions=True, remove_logits_bias=True)
        assert feat.shape == (_BATCH_SIZE, 2048)
        assert pred.shape == (_BATCH_SIZE, 1008)
        assert pred_nb.shape == (_BATCH_SIZE, 1008)

        # The reference model requires input images to have range [0, 255].
        img = raw_img.to(torch.float32).cuda()
        ref_feat = ref_model(img, return_features=True)
        ref_pred = ref_model(img)
        ref_pred_nb = ref_model(img, no_output_bias=True)
        assert ref_feat.shape == (_BATCH_SIZE, 2048)
        assert ref_pred.shape == (_BATCH_SIZE, 1008)
        assert ref_pred_nb.shape == (_BATCH_SIZE, 1008)

        print(f'    Size {size}x{size}, feature:\n        '
              f'mean: {(feat - ref_feat).abs().mean().item():.3e}, '
              f'max: {(feat - ref_feat).abs().max().item():.3e}, '
              f'ref_mean: {ref_feat.abs().mean().item():.3e}, '
              f'ref_max: {ref_feat.abs().max().item():.3e}.')
        print(f'    Size {size}x{size}, prediction:\n        '
              f'mean: {(pred - ref_pred).abs().mean().item():.3e}, '
              f'max: {(pred - ref_pred).abs().max().item():.3e}, '
              f'ref_mean: {ref_pred.abs().mean().item():.3e}, '
              f'ref_max: {ref_pred.abs().max().item():.3e}.')
        print(f'    Size {size}x{size}, prediction (without bias):\n        '
            f'mean: {(pred_nb - ref_pred_nb).abs().mean().item():.3e}, '
            f'max: {(pred_nb - ref_pred_nb).abs().max().item():.3e}, '
              f'ref_mean: {ref_pred_nb.abs().mean().item():.3e}, '
              f'ref_max: {ref_pred_nb.abs().max().item():.3e}.')