Pytorch 深度卷积网络在 CIFAR10 上不收敛
Posted
技术标签:
【中文标题】Pytorch 深度卷积网络在 CIFAR10 上不收敛【英文标题】:Pytorch deep convolutional network does not converge on CIFAR10 【发布时间】:2019-09-19 22:30:19 【问题描述】:我从 PyTorch 教程中复制了 CIFAR10 示例网络并添加了更多层,包括 BN。即使在 45 个 epoch 之后,网络在测试集上仍然保持 68% 的分类准确率。
网络包括:
2 个卷积层和 3x3 内核(输入大小从 32px 减少到 28px) 一个最大池化层(输入大小从 28px 减少到 14px) 3 个卷积层和 3x3 内核(输入大小从 14 像素减少到 8 像素) 具有 3 层 256->256->10 个神经元的全连接网络 批量归一化应用于所有层,包括卷积层,最后一个 FC 层除外 Relu 应用于所有卷积层和所有隐藏 FC 层我是否构建/使用不当?
import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1_1 = nn.Conv2d(3, 16, 3) # 32 -> 30
self.bn1_1 = nn.BatchNorm2d(16)
self.conv1_2 = nn.Conv2d(16, 16, 3) # 30 - > 28
self.bn1_2 = nn.BatchNorm2d(16)
self.pool = nn.MaxPool2d(2, 2) # 28 -> 14
self.conv2_1 = nn.Conv2d(16, 16, 3) # 14 -> 12
self.bn2_1 = nn.BatchNorm2d(16)
self.conv2_2 = nn.Conv2d(16, 16, 3) # 12 -> 10
self.bn2_2 = nn.BatchNorm2d(16)
self.conv2_3 = nn.Conv2d(16, 16, 3) # 10 -> 8
self.bn2_3 = nn.BatchNorm2d(16)
self.fc1 = nn.Linear(16 * 8 * 8, 256)
self.bn4 = nn.BatchNorm1d(256)
self.fc2 = nn.Linear(256, 256)
self.bn5 = nn.BatchNorm1d(256)
self.fc3 = nn.Linear(256, 10)
def forward(self, x):
x = F.relu(self.bn1_1(self.conv1_1(x)))
x = self.pool(F.relu(self.bn1_2(self.conv1_2(x))))
x = F.relu(self.bn2_1(self.conv2_1(x)))
x = F.relu(self.bn2_2(self.conv2_2(x)))
x = F.relu(self.bn2_3(self.conv2_3(x)))
x = x.view(-1, 16 * 8 * 8)
x = F.relu(self.bn4(self.fc1(x)))
x = F.relu(self.bn5(self.fc2(x)))
x = self.fc3(x)
return x
net = Net()
device = 'cuda:0'
net.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=8,
shuffle=True, num_workers=2)
for epoch in range(128): # loop over the dataset multiple times
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
注意:添加了“Python”标签以便代码高亮
注意:更新了 forward
方法以将 F.relu
应用于隐藏的 FC 层
【问题讨论】:
值得一试。也许尝试使用不同的参数显式初始化,例如nn.init.xavier_normal_
,看看它是否有任何区别。
它seems like默认初始化是init.kaiming_uniform_
。
顺便说一句,您的网络的完全连接层之间似乎没有非线性激活函数
@Shai 如果他在最后一层没有非线性可能会出现问题。我只记得 2 年前我使用 Keras 使用类似 VGG11 的网络获得了完全相同的准确率,约为 68%。后来我发现我忘了转调通道暗淡。然而,他在这里使用了来自 torchvision 的现成数据集 :)
你做得很好。但是您确定标准化的手段和标准差吗?我会使用 PIL 或 pyplot 来可视化一些样本并确保它们以您想要的方式提供,在 PyTorch 中是 [B,C,H,W]。从 PyTorch doc 看来,您可以获得 0-255 范围内的值。此外,我建议在卷积之前使用 BN 层(我知道这不是您经常看到的方式,但在数学上它是最有用的)并且使用 Adam 作为优化器应该会进一步改善您的结果。
【参考方案1】:
对最后一层使用 sigmoid 激活。
【讨论】:
以上是关于Pytorch 深度卷积网络在 CIFAR10 上不收敛的主要内容,如果未能解决你的问题,请参考以下文章
[Pytorch系列-45]:卷积神经网络 - 用GPU训练AlexNet+CIFAR10数据集
深度学习之卷积神经网络 CIFAR10与ResNet18实战
深度残差网络+自适应参数化ReLU激活函数(调参记录24)Cifar10~95.80%