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

主要是定义一个继承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)}")

如果电脑有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)

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

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

最后是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)

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

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)

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

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

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

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值