AlexNet网络参数详解
我们以FashionMNIST作为数据集,因此下面的模型代码是在所用的数据集基础上有所调整,输入部分是灰色图因此是1227227的,目标是做10分类,因此最后一层全连接层的输出通道为10.
值得注意的是:
每一层的卷积之后都需要用激活函数来进行激活。
全连接层是否有激活函数,是由网络结构决定的。
#模型搭建完整代码
import torch
from torch import nn
from torchsummary import summary #输入,出特征图大小,以及网络层数的一些细节
import torch.nn.functional as F #便于dropout操作,防止过拟合
class AlexNet(nn.Module): #继承nn里面的一些库
#初始化定义一些网络层,初始化
def __init__(self):
super(AlexNet,self).__init__() #开始搭建前向传播的一些网络层
self.ReLU = nn.ReLU() #名字可以自己去取,尽可能知道是干什么的即可,()不要少
#在原理讲解时候,数据集是彩色(RGB)的,即三通道的,这里的数据集是灰色的,因此输入通道数是1
self.c1 = nn.Conv2d(in_channels=1,out_channels=96,kernel_size=11,stride=4)
#用的是最大池化,需要注意,不存在通道数的改变,只关注,感受野,步长,填充大小即可
self.s2 = nn.MaxPool2d(kernel_size=3,stride=2)
self.c3 = nn.Conv2d(in_channels=96,out_channels=256,kernel_size=5,padding=2)
self.s4 = nn.MaxPool2d(kernel_size=3, stride=2)
self.c5 = nn.Conv2d(in_channels=256,out_channels=384,kernel_size=3,padding=1)
self.c6 = nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1)
self.c7 = nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1)
self.s8 = nn.MaxPool2d(kernel_size=3, stride=2)
self.flatten = nn.Flatten()
self.f1 = nn.Linear(6*6*256,4096)
self.f2 = nn.Linear(4096, 4096)
self.f3 = nn.Linear(4096, 10) ##这里是因为要做的是10分类,因此输出通道数为10,可以根据自己的目的进行改变
##前向传播过程,串起来所有的神经网络
def forward(self,x):
##特征提取的过程
x = self.ReLU(self.c1(x)) #先经过卷积层,后经过激活函数输出
x = self.s2(x) #经过池化层输出的特征图
x = self.ReLU(self.c3(x))
x = self.s4(x)
x = self.ReLU(self.c5(x))
x = self.ReLU(self.c6(x))
x = self.ReLU(self.c7(x))
x = self.s8(x)
##经过全连接层部分,网络原理提到前两层的全连接层是用ReLU激活函数的,还有dropout操作随机神经元失活
x = self.flatten(x)
x = self.ReLU(self.f1(x))
x = F.dropout(x,0.5) #设置一定的比例,防止过拟合
x = self.ReLU(self.f2(x))
x = F.dropout(x, 0.5)
x = self.f3(x)
return x #前向传播结束后的输出
#写一个主函数测试一下,是否跑通了
if __name__ == "__main__":
device = torch.device("cuda" if torch.cuda.is_available() else 'cpu')
model = AlexNet().to(device) #将实例化之后的代码放入到设备中
print(summary(model,(1,227,227))) #放入模型及输入的维度,打印输入输出特征图的尺寸,以及网络结构的参数
self.ReLU = nn.ReLU()
这里的括号一定不能少
如果少了,便会出现下面的报错;
补充:
在 PyTorch 中,nn.ReLU 可以以两种方式使用:
- 作为函数使用:直接调用 nn.ReLU() 作为函数,它将对输入张量逐元素地应用 ReLU 激活函数。这种方式不需要实例化,直接使用即可。
- 作为模块实例化:通过 nn.ReLU()(注意没有括号)实例化成一个模块对象,这个对象可以被保存、加载或重复使用。当你实例化它时,你可以将它赋给一个变量,然后在模型的 forward 方法中使用这个变量来调用 ReLU 激活函数。
- self.ReLU = nn.ReLU 与 self.ReLU = nn.ReLU()
● self.ReLU = nn.ReLU:这种方式是将 nn.ReLU 作为一个类引用赋值给了 self.ReLU。这实际上并没有创建 ReLU 的实例,而是将类本身赋给了变量。在 PyTorch 中,这样使用是不正确的,因为当你尝试调用 self.ReLU(x) 时,PyTorch 会期望一个模块实例,而不是类本身。
● self.ReLU = nn.ReLU():这种方式创建了 nn.ReLU 的一个实例,并将其赋值给了 self.ReLU。这样,你就可以在模型的 forward 方法中使用 self.ReLU(x) 来对输入 x 应用 ReLU 激活函数。
正确用法
在你的 AlexNet 类中,如果你想使用 ReLU 激活函数,你应该这样定义和使用它:
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()