%reload_ext autoreload
%autoreload 2
%matplotlib inline
from fastai.vision import *
bs = 64
path = untar_data(URLs.PETS)/'images'
tfms = get_transforms(max_rotate=20, max_zoom=1.3, max_lighting=0.4, max_warp=0.4,
p_affine=1., p_lighting=1.)
doc(get_transforms)
src = ImageList.from_folder(path).split_by_rand_pct(0.2, seed=2)
def get_data(size, bs, padding_mode='reflection'):
return (src.label_from_re(r'([^/]+)_\d+.jpg$')
.transform(tfms, size=size, padding_mode=padding_mode)
.databunch(bs=bs).normalize(imagenet_stats))
data = get_data(224, bs, 'zeros')
def _plot(i,j,ax):
x,y = data.train_ds[3]
x.show(ax, y=y)
plot_multi(_plot, 3, 3, figsize=(8,8))
data = get_data(224,bs)
plot_multi(_plot, 3, 3, figsize=(8,8))
gc.collect()
learn = cnn_learner(data, models.resnet34, metrics=error_rate, bn_final=True)
29237
learn.fit_one_cycle(3, slice(1e-2), pct_start=0.8)
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 2.458192 | 1.221388 | 0.276049 | 00:23 |
1 | 1.467777 | 0.333426 | 0.078484 | 00:22 |
2 | 0.906456 | 0.259250 | 0.066982 | 00:22 |
learn.unfreeze()
learn.fit_one_cycle(2, max_lr=slice(1e-6,1e-3), pct_start=0.8)
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 0.708001 | 0.269306 | 0.058187 | 00:29 |
1 | 0.666836 | 0.267181 | 0.060217 | 00:29 |
data = get_data(352,bs)
learn.data = data
learn.fit_one_cycle(2, max_lr=slice(1e-6,1e-4))
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 0.633500 | 0.261447 | 0.054804 | 01:08 |
1 | 0.595398 | 0.259402 | 0.051421 | 01:06 |
learn.save('352')
data = get_data(352,16)
learn = cnn_learner(data, models.resnet34, metrics=error_rate, bn_final=True).load('352')
idx=0
x,y = data.valid_ds[idx]
x.show()
data.valid_ds.y[idx]
Category newfoundland
k = tensor([
[0. ,-5/3,1],
[-5/3,-5/3,1],
[1. ,1 ,1],
]).expand(1,3,3,3)/6
k
tensor([[[[ 0.0000, -0.2778, 0.1667], [-0.2778, -0.2778, 0.1667], [ 0.1667, 0.1667, 0.1667]], [[ 0.0000, -0.2778, 0.1667], [-0.2778, -0.2778, 0.1667], [ 0.1667, 0.1667, 0.1667]], [[ 0.0000, -0.2778, 0.1667], [-0.2778, -0.2778, 0.1667], [ 0.1667, 0.1667, 0.1667]]]])
k.shape
torch.Size([1, 3, 3, 3])
t = data.valid_ds[0][0].data; t.shape
torch.Size([3, 352, 352])
t[None].shape
torch.Size([1, 3, 352, 352])
edge = F.conv2d(t[None], k)
show_image(edge[0], figsize=(5,5));
data.c
37
learn.model
Sequential( (0): Sequential( (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU(inplace) (3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) (4): Sequential( (0): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (1): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (2): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (5): Sequential( (0): BasicBlock( (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (2): BasicBlock( (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (3): BasicBlock( (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (6): Sequential( (0): BasicBlock( (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (2): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (3): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (4): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (5): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (7): Sequential( (0): BasicBlock( (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (2): BasicBlock( (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) ) (1): Sequential( (0): AdaptiveConcatPool2d( (ap): AdaptiveAvgPool2d(output_size=1) (mp): AdaptiveMaxPool2d(output_size=1) ) (1): Flatten() (2): BatchNorm1d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (3): Dropout(p=0.25) (4): Linear(in_features=1024, out_features=512, bias=True) (5): ReLU(inplace) (6): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (7): Dropout(p=0.5) (8): Linear(in_features=512, out_features=37, bias=True) (9): BatchNorm1d(37, eps=1e-05, momentum=0.01, affine=True, track_running_stats=True) ) )
print(learn.summary())
====================================================================== Layer (type) Output Shape Param # Trainable ====================================================================== Conv2d [64, 176, 176] 9,408 False ______________________________________________________________________ BatchNorm2d [64, 176, 176] 128 True ______________________________________________________________________ ReLU [64, 176, 176] 0 False ______________________________________________________________________ MaxPool2d [64, 88, 88] 0 False ______________________________________________________________________ Conv2d [64, 88, 88] 36,864 False ______________________________________________________________________ BatchNorm2d [64, 88, 88] 128 True ______________________________________________________________________ ReLU [64, 88, 88] 0 False ______________________________________________________________________ Conv2d [64, 88, 88] 36,864 False ______________________________________________________________________ BatchNorm2d [64, 88, 88] 128 True ______________________________________________________________________ Conv2d [64, 88, 88] 36,864 False ______________________________________________________________________ BatchNorm2d [64, 88, 88] 128 True ______________________________________________________________________ ReLU [64, 88, 88] 0 False ______________________________________________________________________ Conv2d [64, 88, 88] 36,864 False ______________________________________________________________________ BatchNorm2d [64, 88, 88] 128 True ______________________________________________________________________ Conv2d [64, 88, 88] 36,864 False ______________________________________________________________________ BatchNorm2d [64, 88, 88] 128 True ______________________________________________________________________ ReLU [64, 88, 88] 0 False ______________________________________________________________________ Conv2d [64, 88, 88] 36,864 False ______________________________________________________________________ BatchNorm2d [64, 88, 88] 128 True ______________________________________________________________________ Conv2d [128, 44, 44] 73,728 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ ReLU [128, 44, 44] 0 False ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ Conv2d [128, 44, 44] 8,192 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ ReLU [128, 44, 44] 0 False ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ ReLU [128, 44, 44] 0 False ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ ReLU [128, 44, 44] 0 False ______________________________________________________________________ Conv2d [128, 44, 44] 147,456 False ______________________________________________________________________ BatchNorm2d [128, 44, 44] 256 True ______________________________________________________________________ Conv2d [256, 22, 22] 294,912 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ ReLU [256, 22, 22] 0 False ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [256, 22, 22] 32,768 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ ReLU [256, 22, 22] 0 False ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ ReLU [256, 22, 22] 0 False ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ ReLU [256, 22, 22] 0 False ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ ReLU [256, 22, 22] 0 False ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ ReLU [256, 22, 22] 0 False ______________________________________________________________________ Conv2d [256, 22, 22] 589,824 False ______________________________________________________________________ BatchNorm2d [256, 22, 22] 512 True ______________________________________________________________________ Conv2d [512, 11, 11] 1,179,648 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ ReLU [512, 11, 11] 0 False ______________________________________________________________________ Conv2d [512, 11, 11] 2,359,296 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ Conv2d [512, 11, 11] 131,072 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ Conv2d [512, 11, 11] 2,359,296 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ ReLU [512, 11, 11] 0 False ______________________________________________________________________ Conv2d [512, 11, 11] 2,359,296 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ Conv2d [512, 11, 11] 2,359,296 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ ReLU [512, 11, 11] 0 False ______________________________________________________________________ Conv2d [512, 11, 11] 2,359,296 False ______________________________________________________________________ BatchNorm2d [512, 11, 11] 1,024 True ______________________________________________________________________ AdaptiveAvgPool2d [512, 1, 1] 0 False ______________________________________________________________________ AdaptiveMaxPool2d [512, 1, 1] 0 False ______________________________________________________________________ Flatten [1024] 0 False ______________________________________________________________________ BatchNorm1d [1024] 2,048 True ______________________________________________________________________ Dropout [1024] 0 False ______________________________________________________________________ Linear [512] 524,800 True ______________________________________________________________________ ReLU [512] 0 False ______________________________________________________________________ BatchNorm1d [512] 1,024 True ______________________________________________________________________ Dropout [512] 0 False ______________________________________________________________________ Linear [37] 18,981 True ______________________________________________________________________ BatchNorm1d [37] 74 True ______________________________________________________________________ Total params: 21,831,599 Total trainable params: 563,951 Total non-trainable params: 21,267,648
m = learn.model.eval();
xb,_ = data.one_item(x)
xb_im = Image(data.denorm(xb)[0])
xb = xb.cuda()
from fastai.callbacks.hooks import *
def hooked_backward(cat=y):
with hook_output(m[0]) as hook_a:
with hook_output(m[0], grad=True) as hook_g:
preds = m(xb)
preds[0,int(cat)].backward()
return hook_a,hook_g
hook_a,hook_g = hooked_backward()
acts = hook_a.stored[0].cpu()
acts.shape
torch.Size([512, 11, 11])
avg_acts = acts.mean(0)
avg_acts.shape
torch.Size([11, 11])
def show_heatmap(hm):
_,ax = plt.subplots()
xb_im.show(ax)
ax.imshow(hm, alpha=0.6, extent=(0,352,352,0),
interpolation='bilinear', cmap='magma');
show_heatmap(avg_acts)
grad = hook_g.stored[0][0].cpu()
grad_chan = grad.mean(1).mean(1)
grad.shape,grad_chan.shape
(torch.Size([512, 11, 11]), torch.Size([512]))
mult = (acts*grad_chan[...,None,None]).mean(0)
show_heatmap(mult)
fn = path/'../other/bulldog_maine.jpg' #Replace with your own image
x = open_image(fn); x
xb,_ = data.one_item(x)
xb_im = Image(data.denorm(xb)[0])
xb = xb.cuda()
hook_a,hook_g = hooked_backward()
acts = hook_a.stored[0].cpu()
grad = hook_g.stored[0][0].cpu()
grad_chan = grad.mean(1).mean(1)
mult = (acts*grad_chan[...,None,None]).mean(0)
show_heatmap(mult)
data.classes[0]
'Abyssinian'
hook_a,hook_g = hooked_backward(0)
acts = hook_a.stored[0].cpu()
grad = hook_g.stored[0][0].cpu()
grad_chan = grad.mean(1).mean(1)
mult = (acts*grad_chan[...,None,None]).mean(0)
show_heatmap(mult)