当前位置:   article > 正文

Pytorch实现简单的卷积神经网络_pytorch搭建简单的卷积神经网络

pytorch搭建简单的卷积神经网络

近期开始学习Pytorch,在这里小小记录下。
由于是实现卷积神经网络,所以数据集统一使用CIFAR10。
首先,搭建最简单的卷积神经网络:

class Model(nn.Module):
    def __init__(self) :
        super().__init__()
        # 序列化
        self.model1=Sequential(
            # 卷积层,参数依次为输入通道数、输出通道数、卷积核大小、填补大小
            nn.Conv2d(3, 32, 5, padding=2),
            # 最大池化层
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            # 扁平化
            nn.Flatten(),
            # 线性层,参数依次为输入特征数、输出特征数
            nn.Linear(1024,64),
            nn.Linear(64,10)
        )
    # 前向传播函数
    def forward(self,x):
        x=self.model1(x)
        return x
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

主要是定义一个继承torch.nn.Module的类,然后定义初始化函数和forward函数,其中初始化函数中的序列化函数中操作可以自己搭配(注意参数维度要对应),这里推荐阅读Pytorch官方文档详细了解个函数功能。
实现了卷积类之后,就可以调用训练集进行训练,然后在测试集上得到最终训练结果:

# 训练集,参数分别为数据集路径、是否为训练集、进行的transform转换、是否需要在线下载
train_set=torchvision.datasets.CIFAR10(root='../dataset',train=True,transform=transforms.ToTensor(),download=False)
# 测试集
test_set=torchvision.datasets.CIFAR10(root='../dataset',train=False,transform=transforms.ToTensor(),download=False)# 加载训练集,参数依次为数据集、批次、是否打乱顺序
train_data=DataLoader(train_set,64,shuffle=True)
# 加载测试集
test_data=DataLoader(test_set,64,shuffle=True)
# 实例化卷积类
model=Model()
# 迭代次数
epoch_time=5
# 学习率
learn_rate=1e-2
# 交叉熵验证损失
loss=torch.nn.CrossEntropyLoss()
# 优化器,变量依次为待优化参数。学习率、动量
optim=torch.optim.SGD(model.parameters(),learn_rate,momentum=0.5)
for epoch in range(epoch_time):
    print(f"---第{epoch+1}轮训练开始---")
    # 训练步数
    total_train_step = 0
    # 测试精度
    total_accuracy=0
    # 训练集前固定写法(不写也无妨)
    model.train()
    for data in train_data:
      images,targets=data
      output=model(images)
      # 计算损失
      res_loss=loss(output,targets)
      # 清零梯度
      optim.zero_grad()
      # 反向传播
      res_loss.backward()
      # 更新参数
      optim.step()
      total_train_step+=1
      if total_train_step%100==0:
          print(f"训练次数:{total_train_step},损失值:{res_loss}")
    # 测试集固定写法
    model.eval()
    # 测试集不需要梯度下降,加快计算效率
    with torch.no_grad():
     for data in test_data:
        images, targets = data
        output = model(images)
        accuracy=(output.argmax(1)==targets).sum()
        total_accuracy+=accuracy
        res_loss = loss(output, targets)
    print(f"精确度={total_accuracy/len(test_set)}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

如果电脑有GPU的话还可以使用cuda()函数加快运算,这里不在赘述。
接下来实现稍微复杂一点的CNN结果,这是GoogleNet中的一个inception模块,主要是使用1x1的卷积来进行升降维,然后在多个尺寸上同时进行卷积再聚合。

在这里插入图片描述
实现过程如下,首先定义inception模块:

class Inception(nn.Module):
    def __init__(self,input):
      super().__init__()
      self.block1=nn.Sequential(
          # 最大池化,参数依次为核大小、步长、填充
          nn.MaxPool2d(3,stride=1,padding=1),
          nn.Conv2d(input,24,1)
      )
      self.block2=nn.Conv2d(input,16,1)
      self.block3=nn.Sequential(
          nn.Conv2d(input,16,1),
          nn.Conv2d(16,24,5,padding=2)
      )
      self.block4=nn.Sequential(
          nn.Conv2d(input,16,1),
          nn.Conv2d(16,24,3,padding=1),
          nn.Conv2d(24,24,3,padding=1),
      )
    def forward(self,x):
        output1 = self.block1(x)
        output2 = self.block2(x)
        output3 = self.block3(x)
        output4 = self.block4(x)
        outputs=[output1,output2,output3,output4]
        # 合并这几个卷积结构处理得到的结果
        return torch.cat(outputs,dim=1)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

然后在主干网络上调用该模块:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.model1=nn.Sequential(
            nn.Conv2d(3,10,5),
            nn.MaxPool2d(2),
            nn.ReLU())
        self.inc1=Inception(10)
        self.model2=nn.Sequential(
            nn.Conv2d(88,20,5),
            nn.MaxPool2d(2),
            nn.ReLU())
        self.inc2=Inception(20)
        self.model3=nn.Sequential(
            nn.Flatten(),
            nn.Linear(2200,10)
        )

    def forward(self,x):
         x=self.model1(x)
         x=self.inc1(x)
         x=self.model2(x)
         x=self.inc2(x)
         x=self.model3(x)
         return x
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

最后是ResNet,主要使用跳跃连接来解决深层神经网络中出现的梯度消失问题。
在这里插入图片描述
首先实现残差结构:

class Res(nn.Module):
    def __init__(self,input) -> None:
        super().__init__()
        self.model1=nn.Sequential(
            nn.Conv2d(input,input,3,padding=1),
            nn.ReLU(),
            nn.Conv2d(input, input, 3, padding=1)
        )
        self.model2=nn.ReLU()
    def forward(self,x):
        y=self.model1(x)
        y=x+y
        return self.model2(y)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

然后调用该结构形成完整的神经网络:

class Net(nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.model=nn.Sequential(
            nn.Conv2d(3,16,5),
            nn.ReLU(),
            Res(16),
            nn.Conv2d(16,32,5),
            nn.ReLU(),
            Res(32),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(4608,10)
        )
    def forward(self,x):
        return self.model(x)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这里在测试时需要注意图片尺寸和卷积处理大小要对应。
如果对自己实现的模型比较满意,也可以使用如下代码保存调用模型:

# 两个参数分别为模型、保存路径
torch.save(model,"mymodel.pth")
# 加载保存的模型
model=torch.load("mymodel.pth")
  • 1
  • 2
  • 3
  • 4

时间仓促,如有纰漏,请多指教。
以上。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/194162
推荐阅读
相关标签
  

闽ICP备14008679号