李宏毅《机器学习》总结 - 2022 HW3(图像识别、CNN) Strong Baseline
调参调吐了。。做的最艰难的一次(虽然一共也没做几次)
最好做到了 private 0.82 / public 0.808
这题前前后后做了五天。。主要是后来 train 一次就得花很长很长时间,我的 kaggle 余额也用的差不多了。。
这个题目大概就是给你 11 种食物的图片,让你学习,并分类
题目分析
4-fold ensemble \(epoch=25\) 能过 medium,\(epoch=100\) 过 strong
代码分析
处理图片就先转化成 \(128\times 128\) 个 pixel,然后做 CNN。pytorch 的卷积层长这样:
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)
前面两个可以理解成原来的图为 \(\mathit{in}\times N\times N\),卷积之后变成 \(\mathit{out}\times N\times N\)
kernel 就是 filter 的大小,stride 就是 filter 每次移动的步长,padding 就是移动出去之后填充的数字
做完卷积之后通常接一个batch normalization,防止 gradient exploding/vanishing
为了减少运算,一般再加一个池化层,设成 \(2\times 2\)
class Classifier(nn.Module):
def __init__(self):
super(Classifier, self).__init__()
# torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)
# torch.nn.MaxPool2d(kernel_size, stride, padding)
# input 維度 [3, 128, 128]
self.cnn = nn.Sequential(
nn.Conv2d(3, 64, 3, 1, 1), # [64, 128, 128]
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0), # [64, 64, 64]
nn.Conv2d(64, 128, 3, 1, 1), # [128, 64, 64]
nn.BatchNorm2d(128),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0), # [128, 32, 32]
nn.Conv2d(128, 256, 3, 1, 1), # [256, 32, 32]
nn.BatchNorm2d(256),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0), # [256, 16, 16]
nn.Conv2d(256, 512, 3, 1, 1), # [512, 16, 16]
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0), # [512, 8, 8]
nn.Conv2d(512, 512, 3, 1, 1), # [512, 8, 8]
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0), # [512, 4, 4]
)
self.fc = nn.Sequential(
nn.Dropout(0.4),
nn.Linear(512*4*4, 1024),
nn.ReLU(),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Linear(512, 11)
)
def forward(self, x):
out = self.cnn(x)
out = out.view(out.size()[0], -1)
return self.fc(out)
然后结合一下 ensemble,简单来说就是跑好几次这个模型,testing 预测的时候取 argmax,也叫做 k-fold,这里我让 \(k=4\)
还有就是 cross validation,由于是 4-fold,我每次重新划分训练集和验证集,具体的可以先把所有的训练资料存起来,然后每一轮训练的时候重新划分。
这样跑几轮,大概 2、3 个小时(当时我让 \(epoch=25\)),就跑出来 private 0.77 / public 0.79(所以后来四天我就让 public 提升了 0.02?)
感觉到 strong baseline 就只需要把训练时间延长就行了,也试了不同的模型 & loss 函数,感觉差距也不是很大。单个模型延长到 \(epoch=100\),1-fold 跑出来就 0.78 了
又跑了将近 20 个小时,跑出来 4-fold 就是 private 0.82 了