fastbook 13 Implement CNN
from fastai.vision.all import *
top_edge = tensor([[-1,-1,-1],
[0,0,0],
[1,1,1]]).float()
path = untar_data(URLs.MNIST_SAMPLE)
Path.BASE_PATH = path
path.ls()
im3 = Image.open(path/'train'/'3'/'12.png')
show_image(im3)
im3_t = tensor(im3)
im3_t[:3,:3] * top_edge
im3_t[:3,:3] * top_edge.sum()
df = pd.DataFrame(im3_t[:10,:20])
df
df.style.background_gradient('Greys')
df.style.set_properties(**{'font-size':'6pt'}).background_gradient('Greys')
(im3_t[4:7,6:9]*top_edge).sum()
(im3_t[5:8,6:9]*top_edge).sum()
(im3_t[7:10,17:20]*top_edge).sum()
def apply_kernel(row, col, kernel):
return (im3_t[row-1:row+2,col-1:col+2]*kernel).sum()
apply_kernel(5,7, top_edge)
tmp = []
for i in range(1,5):
l = [(i,j) for j in range(1,5)]
tmp.append(l)
tmp
[[(i,j) for j in range(1,5)] for i in range(1,5)]
def apply_kernel_(k):
''''apply specified 'kernel' to all 28*28 dimention'''
return tensor([[apply_kernel(i,j,k) for j in range(1,27)] for i in range(1,27)])
show_image(apply_kernel_(top_edge))
left_edge = tensor([[-1,1,0],
[-1,1,0],
[-1,1,0],]).float()
show_image(apply_kernel_(left_edge))
diag1_edge = torch.eye(3).flip(0)
diag1_edge[1,0] = -1.
diag1_edge[0,1] = -1.
diag1_edge
diag2_edge = diag1_edge.flip(1);diag2_edge
edge_kernels = torch.stack([
left_edge,
top_edge,
diag1_edge,
diag2_edge,
])
edge_kernels.shape
dls = DataBlock(
(ImageBlock(cls=PILImageBW), CategoryBlock),
get_items=get_image_files,
splitter=GrandparentSplitter(),
get_y=parent_label).dataloaders(path)
xb, yb = first(dls.valid)
xb.shape, yb.shape
xb, yb = to_cpu(xb), to_cpu(yb)
kernel shpae is $ ({out\_channels}, \frac, kH , kW) $ , where ${groups}$ could divide the ${in\_channels}$ into # of the ${groups}$ to be masked by the # of ${out\_channels}$ respectively.
edge_kernels.shape,edge_kernels.unsqueeze(1).shape,edge_kernels[:,None,:,:].shape
edge_kernels = edge_kernels.unsqueeze(1)
batch_features = F.conv2d(xb, edge_kernels)
batch_features.shape
show_image(batch_features[0,0])
show_image(batch_features[0,1])
show_image(batch_features[1,0])
show_image(batch_features[1,1])
def new_len(n, ks, stride): return (n + 2*(ks//2) - ks) // stride + 1 # After Conv2d
new_len(28, 3, 1)
simple_net = nn.Sequential(
nn.Linear(28*28, 30),
nn.ReLU(),
nn.Linear(30, 1)
)
simple_net
broken_cnn = nn.Sequential(
nn.Conv2d(1, 30, 3, padding=1),
nn.ReLU(),
nn.Conv2d(30, 1, 3, padding=1)
)
broken_cnn
broken_cnn(xb).shape
def conv(ni, nf, ks=3, act=True):
res = nn.Conv2d(ni, nf, stride=2, kernel_size=ks, padding=ks//2)
if act: res = nn.Sequential(res, nn.ReLU())
return res
simple_cnn = nn.Sequential(
conv(1, 4),
conv(4, 8),
conv(8, 16),
conv(16,32),
conv(32, 2, act=False),
Flatten(),
)
Learner(dls, simple_cnn).summary()
xb, yb = xb.to('cuda'), yb.to('cuda')
simple_cnn(xb).shape
learn = Learner(dls, simple_cnn, loss_func=F.cross_entropy, metrics=accuracy)
learn.summary()
learn.fit_one_cycle(2, 0.01)
m = learn.model[0]
m
m[0].weight.shape, m[0].bias.shape,
path = untar_data(URLs.MNIST)
path.ls()
def get_dls(bs=64):
return DataBlock(
blocks=(ImageBlock(cls=PILImageBW), CategoryBlock),
get_items=get_image_files,
splitter=GrandparentSplitter('training', 'testing'),
get_y=parent_label,
batch_tfms=Normalize(),
).dataloaders(path, bs=bs)
dls = get_dls()
dls.show_batch(figsize=(4,4))
def simple_cnn():
return nn.Sequential(
conv(1, 8, ks=5),
conv(8, 16),
conv(16,32),
conv(32,64),
conv(64, 10, act=False),
Flatten(),
)
Learner(dls, simple_cnn()).summary()
from fastai.callback.hook import *
def fit(epochs=1):
learn = Learner(dls, simple_cnn(), loss_func=F.cross_entropy,
metrics=accuracy, cbs=ActivationStats(with_hist=True))
learn.fit(epochs, 0.06)
return learn
learn = fit()
learn.activation_stats.plot_layer_stats(0)
learn.activation_stats.plot_layer_stats(-2)
dls = get_dls(512)
learn = fit()
learn.activation_stats.plot_layer_stats(-2)
from fastai.callback.hook import *
def fit(epochs=1):
learn = Learner(dls, simple_cnn(), loss_func=F.cross_entropy,
metrics=accuracy, cbs=ActivationStats(with_hist=True))
learn.fit_one_cycle(epochs, 0.06)
return learn
learn = fit()
learn.recorder.plot_sched()
learn.activation_stats.plot_layer_stats(-2)
learn.activation_stats.color_dim(-2)
def conv(ni, nf, ks=3, act=True):
res = nn.Conv2d(ni, nf, stride=2, kernel_size=ks, padding=ks//2)
res = nn.Sequential(res, nn.BatchNorm2d(nf))
if act: res = nn.Sequential(res, nn.ReLU())
return res
learn = fit()
learn.activation_stats.color_dim(-2)
def fit(epochs=1, lr=0.06):
learn = Learner(dls, simple_cnn(), loss_func=F.cross_entropy,
metrics=accuracy, cbs=ActivationStats(with_hist=True))
learn.fit_one_cycle(epochs, 0.06)
return learn
learn = fit(5, lr=0.1)
learn = fit(5, lr=0.1)