BETA

fastai動かしてみたLesson7①

投稿日:2019-07-15
最終更新:2019-07-15

久々に書きます(汗)

MNIST CNN

いつも通りMNISTのデータをとってくる

%reload_ext autoreload  
%autoreload 2  
%matplotlib inline  

from fastai.vision import *  

path = untar_data(URLs.MNIST)  

il = ImageList.from_folder(path, convert_mode='L')  

defaults.cmap='binary'#色の設定  

il[0].show()  

convert_mode='L'  

とすると、読み込みをPillowで行う

il  

ImageList (70000 items)
[Image (1, 28, 28), Image (1, 28, 28), Image (1, 28, 28), Image (1, 28, 28), Image (1, 28, 28)]...
Path: /home/ubuntu/.fastai/data/mnist_png

これを検証用・訓練用データ分ける

sd = il.split_by_folder(train='training', valid='testing')  
sd  

ItemLists;
Train: ImageList (60000 items)
Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28)
Path: /root/.fastai/data/mnist_png;
Valid: ImageList (10000 items)
Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28)
Path: /root/.fastai/data/mnist_png;
Test: None

ラベル付けを行う

ll = sd.label_from_folder()  
ll  

LabelLists;
Train: LabelList (60000 items)
x: ImageList
Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28)
y: CategoryList
2,2,2,2,2
Path: /root/.fastai/data/mnist_png;
Valid: LabelList (10000 items)
x: ImageList
Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28),Image (1, 28, 28)
y: CategoryList
2,2,2,2,2
Path: /root/.fastai/data/mnist_png;
Test: None

中身を見てみる

x,y = ll.train[0]  
x.show()  
print(y,x.shape)  

2 torch.Size([1, 28, 28])

画像の変形の設定をする

tfms = ([*rand_pad(padding=3, size=28, mode='zeros')], [])  
ll = ll.transform(tfms)  

batchsizeを決めて、databunchを作って正規化を行う

bs = 128  
# not using imagenet_stats because not using pretrained model  
data = ll.databunch(bs=bs).normalize()  

データの準備ができた
これを使うと、訓練データからデータを持ってきてtransformを行った画像を3×3で表示する

def _plot(i,j,ax): data.train_ds[0][0].show(ax, cmap='gray')  
plot_multi(_plot, 3, 3, figsize=(8,8))  

これを行うと、1batch分だけxとyを取り出す

xb,yb = data.one_batch()  
xb.shape,yb.shape  

(torch.Size([128, 1, 28, 28]), torch.Size([128]))
(torch.Size([batchsize, channel, num_rows, num_columns]), torch.Size([128]))

基本的なCNNとBatch正規化を行うModelを作ってみる

中身はPytorchなので、Pytorchを使う
畳み込み層の定義をする

def conv(ni,nf):  
    return nn.Conv2d(ni, nf, kernel_size=3, stride=2, padding=1)  

inputしたniをnfの大きさにし、kernelの大きさを3、strideを2、paddingを1で行う
kernelが見ていく範囲の大きさで、strideが見ていく範囲をずらす大きさ、paddingが元のサイズの周りに加える大きさのことのはず
詳しくはググれば出ます

model = nn.Sequential(  
    conv(1, 8), # 14  
    nn.BatchNorm2d(8),  
    nn.ReLU(),  
    conv(8, 16), # 7  
    nn.BatchNorm2d(16),  
    nn.ReLU(),  
    conv(16, 32), # 4  
    nn.BatchNorm2d(32),  
    nn.ReLU(),  
    conv(32, 16), # 2  
    nn.BatchNorm2d(16),  
    nn.ReLU(),  
    conv(16, 10), # 1  
    nn.BatchNorm2d(10),  
    Flatten()     # remove (1,1) grid  
)  

fastaiのLearnerでモデルを読み込む
ここでは損失関数をCrossEntropyにする
metricsは評価尺度

learn = Learner(data, model, loss_func = nn.CrossEntropyLoss(), metrics=accuracy)  
learn  

Sequential
Layer (type) Output Shape Param # Trainable
Conv2d [8, 14, 14] 80 True
BatchNorm2d [8, 14, 14] 16 True
ReLU [8, 14, 14] 0 False
Conv2d [16, 7, 7] 1,168 True
BatchNorm2d [16, 7, 7] 32 True
ReLU [16, 7, 7] 0 False
Conv2d [32, 4, 4] 4,640 True
BatchNorm2d [32, 4, 4] 64 True
ReLU [32, 4, 4] 0 False
Conv2d [16, 2, 2] 4,624 True
BatchNorm2d [16, 2, 2] 32 True
ReLU [16, 2, 2] 0 False
Conv2d [10, 1, 1] 1,450 True
BatchNorm2d [10, 1, 1] 20 True
Flatten [10] 0 False

先ほど書いたModelが表示される

さっき1batch分取り出したxをGPUで計算するようにする

xb = xb.cuda()  

lr_find()で最適な学習率を見つけて訓練する
end_lrの意味は忘れました

learn.lr_find(end_lr=100)  

learn.fit_one_cycle(3, max_lr=0.1)  

epoch train_loss valid_loss accuracy time
0 0.229697 0.233719 0.924200 00:03
1 0.127474 0.107830 0.965600 00:03
2 0.072414 0.041416 0.987700 00:03

上のモデルはもっと簡単に書ける

def conv2(ni,nf):  
    return conv_layer(ni,nf,stride=2)  

model = nn.Sequential(  
    conv2(1, 8),   # 14  
    conv2(8, 16),  # 7  
    conv2(16, 32), # 4  
    conv2(32, 16), # 2  
    conv2(16, 10), # 1  
    Flatten()      # remove (1,1) grid  
)  

Resnetっぽいものを作る

ResBlock層を定義しておく

class ResBlock(nn.Module):  
    def __init__(self, nf):  
        super().__init__()  
        self.conv1 = conv_layer(nf,nf)  
        self.conv2 = conv_layer(nf,nf)  

    def forward(self, x): return x + self.conv2(self.conv1(x))  

さっきのようなModelに組み込む

model = nn.Sequential(  
    conv2(1, 8),  
    res_block(8),  
    conv2(8, 16),  
    res_block(16),  
    conv2(16, 32),  
    res_block(32),  
    conv2(32, 16),  
    res_block(16),  
    conv2(16, 10),  
    Flatten()  
)  

これをLearnerでさっきと同じように学習機を作れば同じように訓練できる

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

大学生の書きなぐりブログ 間違ってる事も書いてるので自己責任で勉強しましょう

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!