Code

count_trainable and RGB pictures — write them yourself

build_resnet works. Two more things you cannot do without it — this time empty skeletons, no holes:

  1. count_trainable — how many parameters are really trainable.
  2. The RGB picture path in data.py — colour, 224 × 224, normalised the way ImageNet was.

1. count_trainable

It is one line, but it is a check at the start of every training run. By printing "trainable parameters: 2,052 of 11,178,564" you see whether freezing really worked, before you spend five minutes.

trainable ← number of parameters of those p whose p.requires_grad is True
total     ← number of all parameters
return (trainable, total)

The number of elements of a parameter p is p.numel().

2. RGB pictures

We added the parameters size (the side) and rgb (whether the picture is colour). Two things await you:

  • build_transform, the rgb=True branch. The picture has to be resized to (size, size) — transforms.Resize. Do not turn it gray again: ImageFolder already reads the file as 3-channel RGB (a gray PNG gets its one channel tripled).
  • make_loaders, the rgb=True branch. The mean and std come not from your data but from ImageNet (IMAGENET_MEAN, IMAGENET_STD, already at the top). A pretrained network expects that scale.

Note that the rgb=False (default) branch stays as it was — lesson 9's code works unchanged.

The test

test_transfer.py has grown. The new tests check that:

  • count_trainable returns (2052, 11178564) for a frozen network and (8395780, 11178564) with layer4;
  • the default loaders still give [N, 1, 28, 28];
  • rgb=True gives [N, 3, 64, 64];
  • the pixels agree with a hand-computed (x − mean) / std using the ImageNet statistics.

Run python -m unittest test_transfer (you already have the holes filled):

EE.....EE
======================================================================
ERROR: test_count_trainable_frozen_backbone (...)
NotImplementedError: return (trainable parameters, all parameters)

ERROR: test_count_trainable_with_layer4 (...)
NotImplementedError: return (trainable parameters, all parameters)

ERROR: test_rgb_loaders_give_three_channels_at_the_requested_size (...)
NotImplementedError: use IMAGENET_MEAN and IMAGENET_STD

ERROR: test_rgb_pixels_use_the_imagenet_statistics (...)
NotImplementedError: use IMAGENET_MEAN and IMAGENET_STD
----------------------------------------------------------------------
Ran 9 tests in 0.7s

FAILED (errors=4)

(Shortened.) Five tests pass, four wait. Once you fill in one make_loaders branch, you will see the second message: write the rgb branch.

transfer.py and data.py are shown with skeletons in the panel. The panel shows the skeleton, not your file.

When it does not pass

  • RuntimeError: output with shape [1, 64, 64] doesn't match the broadcast shape [3, 64, 64] — a Grayscale was left in the rgb branch: the picture has one channel, the ImageNet means have three.
  • Tensor-likes are not close! Greatest absolute difference: 0.92… — the pixels were normalised with other numbers (e.g. [0.5, 0.5, 0.5]).
  • Tuples differ: (11178564, 2052) != (2052, 11178564) — count_trainable returns (total, trainable) and it should be the other way round.