参考にしたのは
にあるCIFAR10の分類器のトレーニングからベースとなるコードをコピーしました。
チュートリアルでは
入力層
conv層 2層
fc 3層
出力層
という構造になっているものからいじっていったものを説明して行こうと思います
#1 data augmentation
Cifar10のような少ない(?)データセットではdata augmentationが効くらしいです。
transform = transforms.Compose(
[transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
transforms.RandomHorizontalFlip()を加えた。これはランダムに(多分バッチごとに)画像を左右反転にさせる前処理となります。
おまじないのように書いていたtransdorms.Composeですが、
どうやらデータの前処理をまとめてくれるようで結構便利そうだと感じました。
#2 network構造
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 64, 3)
self.bn1 = nn.BatchNorm2d(64)
self.conv2 = nn.Conv2d(64, 64, 3)
self.conv3 = nn.Conv2d(64, 64, 3)
self.do1 = nn.Dropout2d(p=0.3)
self.pool = nn.MaxPool2d(2, 2)
self.conv4 = nn.Conv2d(64, 128, 3)
self.bn2 = nn.BatchNorm2d(128)
self.conv5 = nn.Conv2d(128, 128, 3)
self.conv6 = nn.Conv2d(128, 128, 3)
#self.pool = nn.Maxpool2d(2,2)
self.conv7 = nn.Conv2d(128, 256, 3)
self.conv8 = nn.Conv2d(256, 256, 3)
self.conv9 = nn.Conv2d(256, 256, 3)
#self.pool = nn.Maxpool2d(2,2)
self.conv10 = nn.Conv2d(256,100,1)
self.bn3 = nn.BatchNorm2d(256)
self.conv11 = nn.Conv2d(100, 10, 4)
self.zeropad = nn.ConstantPad2d(1, 0)
def forward(self, x):
x = F.relu(self.conv1(self.zeropad(x)))#32*32
x = self.bn1(x)
x = F.relu(self.conv2(self.zeropad(x)))
x = self.do1(x)
x = self.pool(F.relu(self.conv3(self.zeropad(x))))#16*16
x = F.relu(self.conv4(self.zeropad(x)))
x = self.bn2(x)
x = self.do1(x)
x = F.relu(self.conv5(self.zeropad(x)))
x = self.pool(F.relu(self.conv6(self.zeropad(x))))#8*8
x = F.relu(self.conv7(self.zeropad(x)))
x = self.bn3(x)
x = self.do1(x)
x = F.relu(self.conv8(self.zeropad(x)))
x = self.pool(F.relu(self.conv9(self.zeropad(x))))#4*4
x = self.bn3(x)
x = self.do1(x)
x = F.relu(self.conv10(x))
x = self.conv11(x)
x = x.view(-1, 10)
return x
(書いてから思ったんだが、conv層って同じだったらこんなに定義しなくてもよいのでは...)
とりあえず深くして、畳み込み層を増やしてみた形です。
val lossを確認しながら、各パラメータを調整しました
#3 dropout層とBatchNorm層の追加
やってみるとiteration=30くらいで激しく過学習を起こしていることがわかりました。
そこで、Dropout層をいくつか追加しました。
また、深くするにつれ、1 iter目から学習が進まなくなりましたので、
BatchNorm層を追加すると学習が進むようになりました(batchnormすげぇ。。。)
#4 GPU のおまじない
device = 'cuda' if torch.cuda.is_available() else 'cpu'
net = Net()
net = net.to(device)
if device == 'cuda':
net = torch.nn.DataParallel(net)
cudnn.benchmark = True
Colabでやってますが、GPUでないと時間がすごくかかります。
#5 optimizerとscheduler
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr = 0.01, momentum=0.9)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)
optimizerにmomentumを追加
また、schedulerを用いて10epochが進むごとに学習率が半分になるようにしました。
精度をあげるためにしたのはこんなところです。
以下パラメータ数 |
---|
:-- |
Layer (type) Output Shape Param # |
================================================================ |
ConstantPad2d-1 [-1, 3, 34, 34] 0 |
Conv2d-2 [-1, 64, 32, 32] 1,792 |
BatchNorm2d-3 [-1, 64, 32, 32] 128 |
ConstantPad2d-4 [-1, 64, 34, 34] 0 |
Conv2d-5 [-1, 64, 32, 32] 36,928 |
Dropout2d-6 [-1, 64, 32, 32] 0 |
ConstantPad2d-7 [-1, 64, 34, 34] 0 |
Conv2d-8 [-1, 64, 32, 32] 36,928 |
MaxPool2d-9 [-1, 64, 16, 16] 0 |
ConstantPad2d-10 [-1, 64, 18, 18] 0 |
Conv2d-11 [-1, 128, 16, 16] 73,856 |
BatchNorm2d-12 [-1, 128, 16, 16] 256 |
Dropout2d-13 [-1, 128, 16, 16] 0 |
ConstantPad2d-14 [-1, 128, 18, 18] 0 |
Conv2d-15 [-1, 128, 16, 16] 147,584 |
ConstantPad2d-16 [-1, 128, 18, 18] 0 |
Conv2d-17 [-1, 128, 16, 16] 147,584 |
MaxPool2d-18 [-1, 128, 8, 8] 0 |
ConstantPad2d-19 [-1, 128, 10, 10] 0 |
Conv2d-20 [-1, 256, 8, 8] 295,168 |
Dropout2d-21 [-1, 256, 8, 8] 0 |
ConstantPad2d-22 [-1, 256, 10, 10] 0 |
Conv2d-23 [-1, 256, 8, 8] 590,080 |
ConstantPad2d-24 [-1, 256, 10, 10] 0 |
Conv2d-25 [-1, 256, 8, 8] 590,080 |
MaxPool2d-26 [-1, 256, 4, 4] 0 |
BatchNorm2d-27 [-1, 256, 4, 4] 512 |
Dropout2d-28 [-1, 256, 4, 4] 0 |
Conv2d-29 [-1, 100, 4, 4] 25,700 |
Conv2d-30 [-1, 10, 1, 1] 16,010 |
Net-31 [-1, 10] 0 |
================================================================ |
Total params: 1,962,606 |
Trainable params: 1,962,606 |
Non-trainable params: 0 |
---------------------------------------------------------------- |
Input size (MB): 0.01 |
Forward/backward pass size (MB): 6.98 |
Params size (MB): 7.49 |
Estimated Total Size (MB): 14.48 |
---------------------------------------------------------------- |
87%まで出ているコードは
https://github.com/daikiclimate/CIFAR10
に載っています。
https://qiita.com/koshian2/items/e66a7ee9bf60ca24c940
よりも少ないパラメータで90%達成したいです。