zoukankan      html  css  js  c++  java
  • Pytorch Mnist手写数字识别

    import torch 
    import torch.nn as nn
    import torchvision
    import torchvision.transforms as transforms
    
    
    # Device configuration
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    
    # Hyper parameters
    num_epochs = 5
    num_classes = 10
    batch_size = 100
    learning_rate = 0.001
    
    # MNIST dataset
    train_dataset = torchvision.datasets.MNIST(root='../../data/',
                                               train=True, 
                                               transform=transforms.ToTensor(),
                                               download=True)
    
    test_dataset = torchvision.datasets.MNIST(root='../../data/',
                                              train=False, 
                                              transform=transforms.ToTensor())
    
    # Data loader #dataloader 已经在一个数据前又加了一个维度,batch_size维度,表示每批训练用的照片数目,乘上批次数目等于data总数.
    #而epoch指的是迭代数,一共迭代5次,每批处理100个图片,每迭代一次都要讲train_data 走完,所以计算的批次数
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                               batch_size=batch_size, 
                                               shuffle=True)
    
    test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                              batch_size=batch_size, 
                                              shuffle=False) 
    
    # Convolutional neural network (two convolutional layers)
    class ConvNet(nn.Module):
        def __init__(self, num_classes=10):
            super(ConvNet, self).__init__()
            self.layer1 = nn.Sequential(
                nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2), 
                #1代表只有一个通道数,16代表有16个卷积神经元,每一个卷积神经元由一个kernel组成,也就是说有16个kernel,
                #每个kernel的大小是5, 步长为1, padding = 2说明每一侧有两条边补0,(M-F+1)/S表示每一维有多少个0,这里计算得到4
                #所以左边2右边2,上边2下边2,所以padding要设为2
                #1个通道的图片通过16个kernel卷积变换后得到16个通道的图片,这里的1可以指二维数据的input_size,第二个就相当于二维的output_size,
                #只是每一个二维数据都是一个二维张量,整体看待
                nn.BatchNorm2d(16),#对卷积得到的16个二维张量进行一个BatchNormalize
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=2, stride=2)) #图片长宽缩小一半 14*14
            self.layer2 = nn.Sequential(
                nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),#16个输入神经元,32个输出神经元
                nn.BatchNorm2d(32),
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=2, stride=2)) #7*7,但通道数变成了32
            self.fc = nn.Linear(7*7*32, num_classes) #最表层fc,输出一个长度为10的值,可以代表属于这十个类别的概率,输入值就是将这个
            
        def forward(self, x):
            out = self.layer1(x)
            out = self.layer2(out)
            #print('out.size:{}'.format(out.size())) #原来out的size为100,3277
            out = out.reshape(out.size(0), -1) #第一个维度长其实就等于batch_size的大小,将输出转为batch_size个链数据,
            #相当于把每一张32通道的输出图片都摊平,形状变化对卷积会产生影响,但是对回归不产生影响,之后再加上一个线性回归层
            out = self.fc(out)
            return out
    
    model = ConvNet(num_classes).to(device)
    
    # Loss and optimizer
    criterion = nn.CrossEntropyLoss() #交叉熵:先对out分布归一化(转化为概率分布,一般用softmax函数),根据实际值计算交叉熵
    #交叉熵其实表示的
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
    
    # Train the model
    total_step = len(train_loader)
    for epoch in range(num_epochs):
        for i, (images, labels) in enumerate(train_loader):
            images = images.to(device)
            labels = labels.to(device)
            
            # Forward pass
            outputs = model(images)
            #if i == 1:
             #   print('outputs.size:{},labels.size:{}'.format(outputs.size(),labels.size()))
            loss = criterion(outputs, labels) 
            #交叉熵需要预测为概率值(每一张图片的概率分布)一批有100张,因此对于每一张图片要有num_classes个表示每一类概率的值
            #outputs为概率分布,outputs.size: 100x10 ; labels.size: 10
            #与
            
            # Backward and optimize
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            
            if (i+1) % 100 == 0:
                print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                       .format(epoch+1, num_epochs, i+1, total_step, loss.item()))
    
    # Test the model
    model.eval()  # eval mode (batchnorm uses moving mean/variance instead of mini-batch mean/variance)
    with torch.no_grad(): 
        #因为没有优化器,所以得自己将grad设为无,也就是梯度参数不保存,不然每次调用model函数都会产生grad参数,浪费内存
        correct = 0
        total = 0
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1) #选择最大的(概率)值所在的列数就是他所对应的类别数,
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
        print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))
    
    # Save the model checkpoint
    torch.save(model.state_dict(), 'model.ckpt')

    学习这段代码对卷积神经网络的建立很有帮助。

  • 相关阅读:
    排序sort (一)
    c++实现二叉树笔记(模板实现)(三)
    树(二叉树)的建立和遍历算法(二)
    IO流之字节流
    计算机基础知识
    计算机启动过程
    2020软考报名计划表
    2020软件工程作业02
    初来乍到 20200904
    关于考研
  • 原文地址:https://www.cnblogs.com/raiuny/p/13281177.html
Copyright © 2011-2022 走看看