美文网首页
mnist简易分类网络(pytorch)

mnist简易分类网络(pytorch)

作者: ClarenceHoo | 来源:发表于2019-03-28 14:58 被阅读0次

    网上找了一个代码,阅读代码,加上了相应的注释

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    import torch.optim as optim
    from torchvision import datasets, transforms
    
    BATCH_SIZE=512 #大概需要2G的显存
    EPOCHS=20 # 总共训练批次
    DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 让torch判断是否使用GPU
    #获取数据
    train_loader = torch.utils.data.DataLoader(
            datasets.MNIST('data', train=True, download=True, #有数据集后改为download=False
                           transform=transforms.Compose([
                               transforms.ToTensor(),
                               transforms.Normalize((0.1307,), (0.3081,))
                           ])),
            batch_size=BATCH_SIZE, shuffle=True)
    test_loader = torch.utils.data.DataLoader(
            datasets.MNIST('data', train=False, transform=transforms.Compose([
                               transforms.ToTensor(),
                               transforms.Normalize((0.1307,), (0.3081,))
                           ])),
            batch_size=BATCH_SIZE, shuffle=True)
    
    #定义模型
    class ConvNet(nn.Module):
        def __init__(self):
            super().__init__()
            # 1,28x28
            self.conv1=nn.Conv2d(1,10,5) # 10, 24x24
            self.conv2=nn.Conv2d(10,20,3) # 128, 10x10
            self.fc1 = nn.Linear(20*10*10,500)
            self.fc2 = nn.Linear(500,10)
        def forward(self,x):
            in_size = x.size(0)
            out = self.conv1(x) #24
            out = F.relu(out)
            out = F.max_pool2d(out, 2, 2)  #12
            out = self.conv2(out) #10
            out = F.relu(out)
            out = out.view(in_size,-1)#展开成一维,方便进行FC
            out = self.fc1(out)
            out = F.relu(out)
            out = self.fc2(out)
            out = F.log_softmax(out,dim=1)
            return out
    model = ConvNet().to(DEVICE)
    optimizer = optim.Adam(model.parameters())
    #训练过程
    '''
    1 获取loss:输入图像和标签,通过infer计算得到预测值,计算损失函数;
    2 optimizer.zero_grad() 清空过往梯度;
    3 loss.backward() 反向传播,计算当前梯度;
    4 optimizer.step() 根据梯度更新网络参数
    链接:https://www.zhihu.com/question/303070254/answer/573037166
    '''
    def train(model, device, train_loader, optimizer, epoch):
        model.train()
        for batch_idx, (data, target) in enumerate(train_loader):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()#梯度置零,清空过往梯度,这种操作模式的好处可参考https://www.zhihu.com/question/303070254
            output = model(data)
            loss = F.nll_loss(output, target)#调用内置函数
            loss.backward()#反向传播,计算当前梯度
            optimizer.step()#根据梯度更新网络参数
            if(batch_idx+1)%30 == 0: 
                print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                    epoch, batch_idx * len(data), len(train_loader.dataset),
                    100. * batch_idx / len(train_loader), loss.item()))#Use torch.Tensor.item() to get a Python number from a tensor containing a single value:
    #测试过程
    def test(model, device, test_loader):
        model.eval()
        test_loss = 0
        correct = 0
        with torch.no_grad():
            for data, target in test_loader:
                data, target = data.to(device), target.to(device)
                output = model(data)#正向计算预测值
                test_loss += F.nll_loss(output, target, reduction='sum').item() # 将一批的损失相加
                pred = output.max(1, keepdim=True)[1] # 找到概率最大的下标
                correct += pred.eq(target.view_as(pred)).sum().item()#找到正确的预测值
        test_loss /= len(test_loader.dataset)
        print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))
    #运行,这里也可以改成main的形式
    for epoch in range(1, EPOCHS + 1):
        train(model, DEVICE, train_loader, optimizer, epoch)
        test(model, DEVICE, test_loader)
    

    代码部分比较简单
    1、数据读取
    2、构建网络模型 ConvNet(nn.Module)
    3、构建训练函数train
    4、构建测试函数test
    5、关于代码中的model.train(),model.eval()的说明:
    参考 PyTorch进行训练和测试时指定实例化的model模式为:train/eval
    eval即evaluation模式,train即训练模式。仅仅当模型中有Dropout和BatchNorm是才会有影响。因为训练时dropout和BN都开启,而一般而言测试时dropout被关闭,BN中的参数也是利用训练时保留的参数,所以测试时应进入评估模式。
    (在训练时,𝜇和𝜎2是在整个mini-batch 上计算出来的包含了像是64 或28 或其它一定数量的样本,但在测试时,你可能需要逐一处理样本,方法是根据你的训练集估算𝜇和𝜎2,估算的方式有很多种,理论上你可以在最终的网络中运行整个训练集来得到𝜇和𝜎2,但在实际操作中,我们通常运用指数加权平均来追踪在训练过程中你看到的𝜇和𝜎2的值。还可以用指数加权平均,有时也叫做流动平均来粗略估算𝜇和𝜎2,然后在测试中使用𝜇和𝜎2的值来进行你所需要的隐藏单元𝑧值的调整。在实践中,不管你用什么方式估算𝜇和𝜎2,这套过程都是比较稳健的,因此我不太会担心你具体的操作方式,而且如果你使用的是某种深度学习框架,通常会有默认的估算𝜇和𝜎2的方式,应该一样会起到比较好的效果)
    6、损失函数,这是torch的loss function,这里用的是负对数似然,推导可以参考负对数似然

    相关文章

      网友评论

          本文标题:mnist简易分类网络(pytorch)

          本文链接:https://www.haomeiwen.com/subject/bgyqbqtx.html