<jupyter_start><jupyter_text>MNIST CNN<jupyter_code>%reload_ext autoreload
%autoreload 2
%matplotlib inline
from fastai.vision.all import *
matplotlib.rc('image', cmap='Greys')<jupyter_output><empty_output><jupyter_text>Data<jupyter_code># path = untar_data(URLs.MNIST_SAMPLE)
path = untar_data(URLs.MNIST)
path
# !ls /home/ext-share/.fastai/data/mnist_sample
# !ls /home/ext-share/.fastai/data/mnist_png/
# !cp -r /home/ext-share/.fastai/data/mnist_png/train /home/ext-share/.fastai/data/mnist_png/train

im3 = Image.open(path/'train'/'3'/'12.png')
# im3 = Image.open(path/'training'/'3'/'12.png')
show_image(im3);
im3_t = tensor(im3)

df = pd.DataFrame(im3_t[:28,:28])
df.style.set_properties(**{'font-size':'6pt'}).background_gradient('Greys')
# GrandparentSplitter??
# datablock

# GrandparentSplitter require something...  

mnist = DataBlock((ImageBlock(cls=PILImageBW),
                   CategoryBlock), 
                   get_items=get_image_files, 
                   splitter=RandomSplitter(valid_pct=0.2, seed=42),
#                    splitter=GrandparentSplitter(),
                   get_y=parent_label)

dls = mnist.dataloaders(path)
xb,yb = first(dls.valid)
xb.shape
len(dls.train), len(dls.valid)
# il.items[0]
# 28*28 784
# (784) > (1, 28, 28)
# 以前やった時は(64, 784) だった
dls.show_batch()<jupyter_output><empty_output><jupyter_text>Basic CNN with batchnorm<jupyter_code># convolutionはnn.Conv2d使うだけ

# stride 2
def conv_stride2(ni,nf):
    return nn.Conv2d(ni, nf, kernel_size=3, stride=2, padding=1)
model = nn.Sequential(
    
    conv_stride2(1, 8), # 14
    nn.BatchNorm2d(8),
    nn.ReLU(),
    
    conv_stride2(8, 16), # 7
    nn.BatchNorm2d(16),
    nn.ReLU(),
    
    conv_stride2(16, 32), # 4
    nn.BatchNorm2d(32),
    nn.ReLU(),
    
    conv_stride2(32, 16), # 2
    nn.BatchNorm2d(16),
    nn.ReLU(),
    
    conv_stride2(16, 10), # 1
    nn.BatchNorm2d(10),
    
    Flatten()     # remove (1,1) grid
)
model
learn = Learner(dls, model, loss_func = nn.CrossEntropyLoss(), metrics=accuracy)
model.cuda()
xb = xb.cuda()
model(xb).shape
learn.lr_find(end_lr=100)
learn.fit_one_cycle(3, max_lr=0.1)<jupyter_output><empty_output><jupyter_text>Refactor<jupyter_code># def conv_stride2(ni,nf):

def conv_stride2_and_bn_relu(ni,nf):
    return nn.Sequential(
        conv_stride2(ni, nf),
        nn.BatchNorm2d(nf),
        nn.ReLU(),
    )
model = nn.Sequential(
    
    conv_stride2_and_bn_relu(1, 8),
    
    conv_stride2_and_bn_relu(8, 16),
    
    conv_stride2_and_bn_relu(16, 32),
    
    conv_stride2_and_bn_relu(32, 16),
    
    conv_stride2(16, 10), # 1
    nn.BatchNorm2d(10),
    
    Flatten()     # remove (1,1) grid
)
model
# stride 1
def conv_stride1(ni,nf):
    return nn.Conv2d(ni, nf, kernel_size=3, stride=1, padding=1)
def conv_stride1_and_bn_relu(ni,nf):
    return nn.Sequential(
        conv_stride1(ni, nf),
        nn.BatchNorm2d(nf),
        nn.ReLU(),
    )
learn = Learner(dls, model, loss_func = nn.CrossEntropyLoss(), metrics=accuracy)
learn.summary()
learn.fit_one_cycle(3, max_lr=0.1)
# stride 1を使えば延々と長くできる

model = nn.Sequential(
    
    conv_stride2_and_bn_relu(1, 8),
    
    conv_stride1_and_bn_relu(8, 8),
    
    conv_stride2_and_bn_relu(8, 16),
    
    conv_stride1_and_bn_relu(16, 16),
    
    conv_stride2_and_bn_relu(16, 32),
    
    conv_stride1_and_bn_relu(32, 32),
    
    conv_stride2_and_bn_relu(32, 16),
    
    conv_stride1_and_bn_relu(16, 16),
    
    conv_stride2(16, 10), # 1
    nn.BatchNorm2d(10),
    
    Flatten()     # remove (1,1) grid
)
learn = Learner(dls, model, loss_func = nn.CrossEntropyLoss(), metrics=accuracy)
learn.summary()
learn.fit_one_cycle(1, max_lr=0.1)<jupyter_output><empty_output><jupyter_text>Resnet-ish<jupyter_code>class ResBlock(nn.Module):
    def __init__(self, nf):
        super().__init__()
        self.conv1 = conv_stride1_and_bn_relu(nf,nf)
        self.conv2 = conv_stride1_and_bn_relu(nf,nf)
        
    def forward(self, x):
        return x + self.conv1(self.conv2(x))
model = nn.Sequential(
    
    conv_stride2(1, 8),
    ResBlock(8),
    
    conv_stride2(8, 16),
    ResBlock(16),
    
    conv_stride2(16, 32),
    ResBlock(32),
    
    conv_stride2(32, 16),
    ResBlock(16),
    
    conv2(16, 10),
    Flatten()
)
def conv_and_res(ni,nf):
    return nn.Sequential(conv_stride2(ni, nf), ResBlock(nf))
model = nn.Sequential(
    conv_and_res(1, 8),
    conv_and_res(8, 16),
    conv_and_res(16, 32),
    conv_and_res(32, 16),
    conv2(16, 10),
    Flatten()
)
# model
learn = Learner(dls, model, loss_func = nn.CrossEntropyLoss(), metrics=accuracy)
learn.lr_find()
learn.fit_one_cycle(1, max_lr=0.05)
print(learn.summary())<jupyter_output><empty_output><jupyter_text>fin<jupyter_code># fastaiのソースコード
class MergeLayer(Module):
    "Merge a shortcut with the result of the module by adding them or concatenating them if `dense=True`."
    def __init__(self, dense:bool=False): self.dense=dense
    def forward(self, x):
        if self.dense:
            return torch.cat([x,x.orig], dim=1) 
        else:
            return (x + x.orig)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1422979056566843, 'fraction_numerical': 0.04952045410060677, 'mean_word_length': 3.5341614906832297, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '140446', 'license': 'MIT', 'n_tokens_mistral': 2251, 'n_tokens_neox': 2100, 'n_words': 315, 'path': 'nbs/v1_lesson7-resnet-mnist_ja.ipynb', 'repo_name': 'akiraenduo/mytutorials', 'size': '5109'}