Pytorch CIFAR10图像分类 AlexNet篇
Posted Real&Love
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch CIFAR10图像分类 AlexNet篇相关的知识,希望对你有一定的参考价值。
Pytorch CIFAR10图像分类 AlexNet篇
文章目录
4.定义网络(AlexNet)
AlexNet 结构:
-
输入层:图像大小为 227×227×3,其中 3 表示输入图像的 channel 数(R,G,B)为 3。
-
卷积层:filter 大小 11×11,filter 个数 96,卷积步长 s=4。(filter 大小只列出了宽和高,filter矩阵的 channel 数和输入图片的 channel 数一样,在这里没有列出)
-
池化层:max pooling,filter 大小 3×3,步长 s=2。
-
卷积层:filter 大小 5×5,filter 个数 256,步长 s=1,padding 使用 same convolution,即使得卷积层输出图像和输入图像在宽和高上保持不变。
-
池化层:max pooling,filter 大小 3×3,步长 s=2。
-
卷积层:filter 大小 3×3,filter 个数 384,步长 s=1,padding 使用 same convolution。
-
卷积层:filter 大小 3×3,filter 个数 384,步长 s=1,padding 使用 same convolution。
-
卷积层:filter 大小 3×3,filter 个数 256,步长 s=1,padding 使用 same convolution。
-
池化层:max pooling,filter 大小 3×3,步长 s=2;池化操作结束后,将大小为 6×6×256 的输出矩阵 flatten 成一个 9216 维的向量。
-
全连接层:neuron 数量为 4096。
-
全连接层:neuron 数量为 4096。
-
全连接层,输出层:softmax 激活函数,neuron 数量为 1000,代表 1000 个类别。
AlexNet 一些性质:
- 大约 60million 个参数;
- 使用 ReLU 作为激活函数。
首先我们还是得判断是否可以利用GPU,因为GPU的速度可能会比我们用CPU的速度快20-50倍左右,特别是对卷积神经网络来说,更是提升特别明显。
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 定义神经网络
class AlexNet(nn.Module): # 训练 ALexNet
'''
5层卷积,3层全连接
'''
def __init__(self):
super(AlexNet, self).__init__()
# 五个卷积层 输入 32 * 32 * 3
self.conv1 = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=1), # (32-3+2)/1+1 = 32
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0) # (32-2)/2+1 = 16
)
self.conv2 = nn.Sequential( # 输入 16 * 16 * 6
nn.Conv2d(in_channels=6, out_channels=16, kernel_size=3, stride=1, padding=1), # (16-3+2)/1+1 = 16
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0) # (16-2)/2+1 = 8
)
self.conv3 = nn.Sequential( # 输入 8 * 8 * 16
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1), # (8-3+2)/1+1 = 8
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0) # (8-2)/2+1 = 4
)
self.conv4 = nn.Sequential( # 输入 4 * 4 * 64
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1), # (4-3+2)/1+1 = 4
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0) # (4-2)/2+1 = 2
)
self.conv5 = nn.Sequential( # 输入 2 * 2 * 128
nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),# (2-3+2)/1+1 = 2
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0) # (2-2)/2+1 = 1
) # 最后一层卷积层,输出 1 * 1 * 128
# 全连接层
self.dense = nn.Sequential(
nn.Linear(128, 120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, 10)
)
def forward(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = self.conv3(x)
x = self.conv4(x)
x = self.conv5(x)
x = x.view(x.size()[0],-1)
x = self.dense(x)
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
net = AlexNet().to(device)
summary(net,(3,32,32))
---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ Conv2d-1 [-1, 6, 32, 32] 168 ReLU-2 [-1, 6, 32, 32] 0 MaxPool2d-3 [-1, 6, 16, 16] 0 Conv2d-4 [-1, 16, 16, 16] 880 ReLU-5 [-1, 16, 16, 16] 0 MaxPool2d-6 [-1, 16, 8, 8] 0 Conv2d-7 [-1, 32, 8, 8] 4,640 ReLU-8 [-1, 32, 8, 8] 0 MaxPool2d-9 [-1, 32, 4, 4] 0 Conv2d-10 [-1, 64, 4, 4] 18,496 ReLU-11 [-1, 64, 4, 4] 0 MaxPool2d-12 [-1, 64, 2, 2] 0 Conv2d-13 [-1, 128, 2, 2] 73,856 ReLU-14 [-1, 128, 2, 2] 0 MaxPool2d-15 [-1, 128, 1, 1] 0 Linear-16 [-1, 120] 15,480 ReLU-17 [-1, 120] 0 Linear-18 [-1, 84] 10,164 ReLU-19 [-1, 84] 0 Linear-20 [-1, 10] 850 ================================================================ Total params: 124,534 Trainable params: 124,534 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.01 Forward/backward pass size (MB): 0.24 Params size (MB): 0.48 Estimated Total Size (MB): 0.73 ----------------------------------------------------------------
首先从我们summary可以看到,我们定义的模型的参数大概是124 thousands,我们输入的是(batch,3,32,32)的张量,并且这里也能看到每一层后我们的图像输出大小的变化,最后输出10个参数,再通过softmax函数就可以得到我们每个类别的概率了。
我们也可以打印出我们的模型观察一下
AlexNet(
(conv1): Sequential(
(0): Conv2d(3, 6, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(conv2): Sequential(
(0): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(conv3): Sequential(
(0): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(conv4): Sequential(
(0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(conv5): Sequential(
(0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(dense): Sequential(
(0): Linear(in_features=128, out_features=120, bias=True)
(1): ReLU()
(2): Linear(in_features=120, out_features=84, bias=True)
(3): ReLU()
(4): Linear(in_features=84, out_features=10, bias=True)
)
)
如果你的电脑有多个GPU,这段代码可以利用GPU进行并行计算,加快运算速度
net =AlexNet().to(device)
if device == 'cuda':
net = nn.DataParallel(net)
# 当计算图不会改变的时候(每次输入形状相同,模型不改变)的情况下可以提高性能,反之则降低性能
torch.backends.cudnn.benchmark = True
5. 定义损失函数和优化器
pytorch将深度学习中常用的优化方法全部封装在torch.optim之中,所有的优化方法都是继承基类optim.Optimizier
损失函数是封装在神经网络工具箱nn中的,包含很多损失函数
这里我使用的是SGD + momentum算法,并且我们损失函数定义为交叉熵函数,除此之外学习策略定义为动态更新学习率,如果5次迭代后,训练的损失并没有下降,那么我们便会更改学习率,会变为原来的0.5倍,最小降低到0.00001
如果想更加了解优化器和学习率策略的话,可以参考以下资料
- Pytorch Note15 优化算法1 梯度下降(Gradient descent varients)
- Pytorch Note16 优化算法2 动量法(Momentum)
- Pytorch Note34 学习率衰减
这里决定迭代20次
import torch.optim as optim
optimizer = optim.SGD(net.parameters(), lr=1e-1, momentum=0.9, weight_decay=5e-4)
criterion = nn.CrossEntropyLoss()
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', factor=0.5 ,patience = 5,min_lr = 0.000001) # 动态更新学习率
# scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=[75, 150], gamma=0.5)
import time
epoch = 20
6. 训练
首先定义模型保存的位置
import os
if not os.path.exists('./model'):
os.makedirs('./model')
else:
print('文件已存在')
save_path = './model/AlexNet.pth'
我定义了一个train函数,在train函数中进行一个训练,并保存我们训练后的模型
from utils import trainfrom utils import plot_historyAcc, Loss以上是关于Pytorch CIFAR10图像分类 AlexNet篇的主要内容,如果未能解决你的问题,请参考以下文章
Pytorch CIFAR10图像分类 EfficientNet v1篇