pytorch入门03--lenet网络

pytorch入门03--lenet网络_第1张图片

pytorch入门03--lenet网络_第2张图片

模型构建部分

import  torch
from    torch import nn
from    torch.nn import functional as F

class Lenet5(nn.Module):  #定义Lenet网络结构类
    """
    for cifar10 dataset.
    """
    def __init__(self):
        super(Lenet5, self).__init__()  #调用类的方法初始化父类
        self.conv_unit = nn.Sequential(   #nn.Sequential包含很多子类,快速上手卷积网络
            # x: [b,3,32,32] => [b,16,28,28 ],先卷积 输入3层,输出16层,卷积核大小为5*5,步长为1
            nn.Conv2d(3, 16, kernel_size=5, stride=1, padding=0),
            #[b,16,14,14]第二层经过池化,卷积核大小为2*2步长为2,层数还是16,输出形状变为1/4,14*14
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
            #[b,32,10,10]第三层又是经过卷积,16层输入,32层输出
            nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=0),
            #[b,32,5,5]第四层经过池化,32层输出,输出形状变为1/4,8*8
            nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
        )
        # # [b, 3, 32, 32] 以下代码可以用于计算结果卷积层输入与输出的维度
        # tmp = torch.randn(2, 3, 32, 32)
        # out = self.conv_unit(tmp)
        # # [b, 32, 5, 5]
        # print('conv out:', out.shape)

        # flatten
        # fc unit 定义全连接层
        self.fc_unit = nn.Sequential(
            nn.Linear(32*5*5, 32),    #从卷积网络输出到全连接层的数据是已经平铺为1维了
            nn.ReLU(), #使用激活函数ReLU
            nn.Linear(32, 10) #输入32层,输出10层
        )

        # # use Cross Entropy Loss
        # self.criteon = nn.CrossEntropyLoss()
    def forward(self, x): #定义前向传播,后向传播不需要定义,自动生成

        batchsz = x.size(0)   #相当于获取图片张数
        # [b, 3, 32, 32] => [b, 16, 5, 5]
        x = self.conv_unit(x)   #将输入图片传入卷积网络
        # [b, 16, 5, 5] => [b, 16*5*5]
        x = x.view(batchsz, 32*5*5)  #平铺为一维
        # [b, 16*5*5] => [b, 10]
        logits = self.fc_unit(x)   #经过全连接层
        # # [b, 10]
        # pred = F.softmax(logits, dim=1) 分类函数
        # loss = self.criteon(logits, y) 计算损失
        return logits
def main():
    net = Lenet5()
    tmp = torch.randn(2, 3, 32, 32)  #输入数据
    out = net(tmp)  #传进lenet网络
    print('lenet out:', out.shape)  #打印输出结果
if __name__ == '__main__':
    main()

主函数部分:

import  torch
from    torch.utils.data import DataLoader    #导入下载功能通道
from    torchvision import datasets      #加载数据使用
from    torchvision import transforms    #对数据做变换使用
from    torch import nn, optim   #导入nn网络和optim优化器

from    lenet5 import Lenet5     #引进类
# from    resnet import ResNet18

def main():
    batchsz = 128   #每次投喂的数据量
       #datasets加载CIFAR10数据集到本地,命名为cifar,transform对数据做变换,32*32的大小,自动下载数据集
    cifar_train = datasets.CIFAR10('cifar', True, transform=transforms.Compose([
        transforms.Resize((32, 32)),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ]), download=True)
    cifar_train = DataLoader(cifar_train, batch_size=batchsz, shuffle=True)  #每次导入batchsz那么多的数据
#定义测试集与训练集一样
    cifar_test = datasets.CIFAR10('cifar', False, transform=transforms.Compose([
        transforms.Resize((32, 32)),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ]), download=True)
    cifar_test = DataLoader(cifar_test, batch_size=batchsz, shuffle=True)


    x, label = iter(cifar_train).next()   #打印训练集数据和标签形状
    print('x:', x.shape, 'label:', label.shape)

    device = torch.device('cuda')   #调用cuda加速
    model = Lenet5().to(device)    #将进入的Lenet5也使用cuda加速

    criteon = nn.CrossEntropyLoss().to(device)     #调用损失函数
    optimizer = optim.Adam(model.parameters(), lr=1e-3)   #调用Adam优化器,
    print(model)   #打印类的实例

    for epoch in range(1000):
        model.train()  #变成训练模式
        for batchidx, (x, label) in enumerate(cifar_train):  #获取数据
            # [b, 3, 32, 32]
            x, label = x.to(device), label.to(device)  #cuda加速
            logits = model(x)  #通过lenet5训练
            # logits: [b, 10]   # label:  [b]
            # loss: tensor scalar
            loss = criteon(logits, label) #计算损失
            # backprop
            optimizer.zero_grad()  #优化器把梯度清零 防梯度累加
            loss.backward()
            optimizer.step()  #运行优化器走流程
        print(epoch, 'loss:', loss.item())  #打印每次损失,item表示转化成numpy类型


        model.eval()  #变成测试模式
        with torch.no_grad():   #这里告诉pytorch运算时不需计算图的
            # test
            total_correct = 0
            total_num = 0
            for x, label in cifar_test:   #获取测试集数据
                # [b, 3, 32, 32]
                # [b]
                x, label = x.to(device), label.to(device)   #调用cuda

                # [b, 10]
                logits = model(x)
                # [b]
                pred = logits.argmax(dim=1)  #在第2个维度上索引最大的值的下标
                # [b] vs [b] => scalar tensor  比较预测值与真实值预测对的数量 eq是否相等
                correct = torch.eq(pred, label).float().sum().item()
                total_correct += correct
                total_num += x.size(0)  #统计输入总数
                # print(correct)

            acc = total_correct / total_num  #计算平均准确率
            print(epoch, 'test acc:', acc)



if __name__ == '__main__':
    main()

 

你可能感兴趣的:(torch)