LeNet的实现已经过程中的问题

首先是LeNet网络类的实现

from torchvision import datasets, transforms
import torch
from torch.utils.data import DataLoader
import torch.nn as nn
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv_layers = nn.Sequential(
            # [b, 3, 32, 32] batch, rgb3个channel
            nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5, stride=1, padding=0),
            # [b, 3, 32, 32] 经过卷积层-> [b, 6, 28,28]
            nn.AvgPool2d(kernel_size=2, stride=2, padding=0),
            # [b,6,28,28] 经过pooling层 -> [b,6, 14,14]
            nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0),
            # [b,6,14,14] 经过卷积层 -> [b,16,10,10]
            nn.AvgPool2d(kernel_size=2,stride=2,padding=0)
            # [b,16,10,10] 经过pooling层 -> [b,16,5,5]
        )
        # flatten # [b,16,5,5] -> [16*5*5]
        # FC
        self.fc_layers = nn.Sequential(
            nn.Linear(in_features=16*5*5, out_features=120),
            nn.ReLU(),
            nn.Linear(120,84),
            nn.ReLU(),
            nn.Linear(84, 10)
        )
    def forward(self, x):
        batchsz = x.size(0)
        x = self.conv_layers(x)
        x = x.reshape(batchsz, 16*5*5)
        # [b,16,5,5] -> [b, 16*5*5]
        logit = self.fc_layers(x)
        return logit

中间遇到的问题有,

  1. 没写super(LeNet, self).init() 原因: 不理解super的作用,其作用是先创建一个LeNet类的实例,然后将这个对象转换为其父类nn.Module的实例,然后调用这个父类实例的__init__()方法进行初始化
  2. 最后一个pooling层连接fc层不会计算 原因:不理解网络中的batch维度是超脱网络其他超参数的,实际上网络中的参数都是对于一张32x32图片而言的,而batch就是有多少张图片同时在训练。而pooling的16个channel,每个channel 5x5转到 120的fc层就是[16,5,5] 打平到[1655] 或者说是[batchsize,16,5,5] -》 [batchsize,1655]
  3. 获取网络某一层第一维度的长度可以用 x.size(0)

下面是训练的代码

from torchvision import datasets, transforms
import torch
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.nn.functional as F
from lenet import LeNet

batchsz = 32
cifar_train = datasets.CIFAR10('../cifar', train=True, transform=transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.ToTensor()
]), download=True)
cifar_train = DataLoader(cifar_train, batch_size=batchsz, shuffle=True)
cifar_test = datasets.CIFAR10('../cifar', train=False, transform=transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.ToTensor()
]), download=True)
cifar_test = DataLoader(cifar_test, batch_size=batchsz, shuffle=True)
model = LeNet()
# device = torch.device('cuda')
# model = LeNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr=1e-3)
print(model)
model.train()
for epoch in range(10):
    for batchidx, (x, label) in enumerate(cifar_train):
        # x [b,3,32,32] label [b]
        # x, label = x.to(device), label.to(device)
        # 注意CrossEntropyLoss() 包括softmax,所以输入肯定是logits,不是pred
        logits = model(x)
        loss = criterion(logits, label)
        # label [b] logits [b,10]
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    print("epoch", epoch, "loss:", loss.item())
    #test
    model.eval()
    correct_num = 0
    total_num = 0
    with torch.no_grad():
        for (x, label) in cifar_test:
            # x[b,3,32,32] label [b]
            logits = model(x)
            # logits [b,10]
            pred = torch.argmax(logits, dim=1)
            correct_num += torch.eq(pred, label).float().sum().item()
            total_num += x.size(0)
        print('test accuarcy:', correct_num/total_num)

出现过的问题有

  1. 导包写的 import LeNet,那样的话下面就应该写model=lenet.Lenet(). 如果写 from lenet import LeNet 下面就可以写model=LeNet()
  2. 错写成loss = criterion(label, logits) CrossEntorpyLoss()顺序是重要的,预测值应该在前
  3. test里的 with torch.no_grad() 错写成 with model.zero_grad()

最后,运行结果

D:\Anaconda\envs\pytorch\python.exe "D:/PycharmProjects/pythonProjecet_pytorch/LeNet & ResNet/LeNet/train.py"
Files already downloaded and verified
Files already downloaded and verified
LeNet(
  (conv_layers): Sequential(
    (0): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
    (1): AvgPool2d(kernel_size=2, stride=2, padding=0)
    (2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
    (3): AvgPool2d(kernel_size=2, stride=2, padding=0)
  )
  (fc_layers): Sequential(
    (0): Linear(in_features=400, 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)
  )
)
epoch 0 loss: 1.37169349193573
test accuarcy: 0.4542
epoch 1 loss: 1.9433141946792603
test accuarcy: 0.4866
epoch 2 loss: 2.1775083541870117
test accuarcy: 0.5228
epoch 3 loss: 1.9912444353103638
test accuarcy: 0.5261
epoch 4 loss: 1.410996913909912
test accuarcy: 0.5381
epoch 5 loss: 0.9067156314849854
test accuarcy: 0.5481
epoch 6 loss: 1.1418999433517456
test accuarcy: 0.53
epoch 7 loss: 1.032881498336792
test accuarcy: 0.5518
epoch 8 loss: 1.4319336414337158
test accuarcy: 0.5499
epoch 9 loss: 0.9463621377944946
test accuarcy: 0.5431

Process finished with exit code 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值