• 深度学习与Pytorch入门实战(六)定义MLP&GPU加速&测试【数字识别实例】


    笔记摘抄

    • Pytorch定义网络结构识别手写数字,可以对网络中的参数w和b进行手动定义的(参考上一节)

    • 也可以直接用 nn.Linear 定义层的方式来定义

    • 更加方便的方式是直接继承 nn.Module 来定义自己的网络结构。

    1. nn.Linear方式

    import torch
    import  torch.nn as nn
    import  torch.nn.functional as F
    
    # 模拟 一张 28*28 的图片摊平
    x = torch.randn(1, 784)            #shape=[1,784]
    
    # 定义三个全连接层
    layer1 = nn.Linear(784, 200)         # (in, out)
    layer2 = nn.Linear(200, 200)
    layer3 = nn.Linear(200, 10)
    
    x = layer1(x)                        # shape=[1,200]
    x = F.relu(x, inplace=True)          # inplace=True在原对象基础上修改,可以节省内存
    print(x.shape)
    
    x = layer2(x)                        # shape=[1,200]
    x = F.relu(x, inplace=True)
    
    x = layer3(x)                        # shape=[1,10]
    x = F.relu(x, inplace=True)
    

    2. 继承nn.Module方式

    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=200
    learning_rate=0.01
    epochs=10
    
    #获取训练数据
    train_loader = torch.utils.data.DataLoader(
        datasets.MNIST('../data', train=True, download=True,          #train=True则得到的是训练集
                       transform=transforms.Compose([                 #transform进行数据预处理
                           transforms.ToTensor(),                     #转成Tensor类型的数据
                           transforms.Normalize((0.1307,), (0.3081,)) #进行数据标准化(减去均值除以方差)
                       ])),
        batch_size=batch_size, shuffle=True)                          #按batch_size分出一个batch维度在最前面,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 MLP(nn.Module):
    
        def __init__(self):
            super(MLP, self).__init__()
            
            # 定义网络的每一层,nn.ReLU可以换成其他激活函数,比如nn.LeakyReLU()
            self.model = nn.Sequential(     
                nn.Linear(784, 200),
                nn.ReLU(inplace=True),
                nn.Linear(200, 200),
                nn.ReLU(inplace=True),
                nn.Linear(200, 10),
                nn.ReLU(inplace=True),
            )
    
        def forward(self, x):
            x = self.model(x)
            return x
    
    net = MLP()
    # 定义sgd优化器,指明优化参数、学习率
    # net.parameters()得到这个类所定义的网络的参数[[w1,b1,w2,b2,...]
    optimizer = optim.SGD(net.parameters(), lr=learning_rate)
    criteon = nn.CrossEntropyLoss()
    
    for epoch in range(epochs):
    
        for batch_idx, (data, target) in enumerate(train_loader):
            data = data.view(-1, 28*28)          # 将二维的图片数据摊平[样本数,784]
    
            logits = net(data)                   # 前向传播
            loss = criteon(logits, target)       # nn.CrossEntropyLoss()自带Softmax
    
            optimizer.zero_grad()                # 梯度信息清空
            loss.backward()                      # 反向传播获取梯度
            optimizer.step()                     # 优化器更新
    
            if batch_idx % 100 == 0:             # 每100个batch输出一次信息
                print('Train Epoch: {} [{}/{} ({:.0f}%)]	Loss: {:.6f}'.format(
                    epoch, batch_idx * len(data), len(train_loader.dataset),
                           100. * batch_idx / len(train_loader), loss.item()))
    
    
        test_loss = 0
        correct = 0                                         # correct记录正确分类的样本数
        for data, target in test_loader:
            data = data.view(-1, 28 * 28)
            logits = net(data)
            test_loss += criteon(logits, target).item()     # 其实就是criteon(logits, target)的值,标量
    
            pred = logits.data.max(dim=1)[1]                # 也可以写成pred=logits.argmax(dim=1)
            correct += pred.eq(target.data).sum()
    
        test_loss /= len(test_loader.dataset)
        print('
    Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)
    '.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))
    
    view result
    Train Epoch: 0 [0/60000 (0%)] Loss: 2.307840
    Train Epoch: 0 [20000/60000 (33%)] Loss: 2.022810
    Train Epoch: 0 [40000/60000 (67%)] Loss: 1.342542
    
    Test set: Average loss: 0.0038, Accuracy: 8374/10000 (84%)
    
    Train Epoch: 1 [0/60000 (0%)] Loss: 0.802759
    Train Epoch: 1 [20000/60000 (33%)] Loss: 0.627895
    Train Epoch: 1 [40000/60000 (67%)] Loss: 0.482087
    
    Test set: Average loss: 0.0020, Accuracy: 8926/10000 (89%)
    
    Train Epoch: 2 [0/60000 (0%)] Loss: 0.496279
    Train Epoch: 2 [20000/60000 (33%)] Loss: 0.420009
    Train Epoch: 2 [40000/60000 (67%)] Loss: 0.429296
    
    Test set: Average loss: 0.0017, Accuracy: 9069/10000 (91%)
    
    Train Epoch: 3 [0/60000 (0%)] Loss: 0.304612
    Train Epoch: 3 [20000/60000 (33%)] Loss: 0.356296
    Train Epoch: 3 [40000/60000 (67%)] Loss: 0.405541
    
    Test set: Average loss: 0.0015, Accuracy: 9149/10000 (91%)
    
    Train Epoch: 4 [0/60000 (0%)] Loss: 0.304062
    Train Epoch: 4 [20000/60000 (33%)] Loss: 0.406027
    Train Epoch: 4 [40000/60000 (67%)] Loss: 0.385962
    
    Test set: Average loss: 0.0014, Accuracy: 9201/10000 (92%)
    
    Train Epoch: 5 [0/60000 (0%)] Loss: 0.186269
    Train Epoch: 5 [20000/60000 (33%)] Loss: 0.196249
    Train Epoch: 5 [40000/60000 (67%)] Loss: 0.228671
    
    Test set: Average loss: 0.0013, Accuracy: 9248/10000 (92%)
    
    Train Epoch: 6 [0/60000 (0%)] Loss: 0.364886
    Train Epoch: 6 [20000/60000 (33%)] Loss: 0.295816
    Train Epoch: 6 [40000/60000 (67%)] Loss: 0.244240
    
    Test set: Average loss: 0.0012, Accuracy: 9290/10000 (93%)
    
    Train Epoch: 7 [0/60000 (0%)] Loss: 0.228807
    Train Epoch: 7 [20000/60000 (33%)] Loss: 0.192547
    Train Epoch: 7 [40000/60000 (67%)] Loss: 0.223399
    
    Test set: Average loss: 0.0012, Accuracy: 9329/10000 (93%)
    
    Train Epoch: 8 [0/60000 (0%)] Loss: 0.176273
    Train Epoch: 8 [20000/60000 (33%)] Loss: 0.346954
    Train Epoch: 8 [40000/60000 (67%)] Loss: 0.253838
    
    Test set: Average loss: 0.0011, Accuracy: 9359/10000 (94%)
    
    Train Epoch: 9 [0/60000 (0%)] Loss: 0.246411
    Train Epoch: 9 [20000/60000 (33%)] Loss: 0.201452
    Train Epoch: 9 [40000/60000 (67%)] Loss: 0.162228
    
    Test set: Average loss: 0.0011, Accuracy: 9377/10000 (94%)
    

    区别nn.ReLU()F.relu()

    • nn.ReLU()是类风格的API(大写开头,必须 先实例化再调用;参数w、b是内部成员,通过.parameters来访问)

    • F.relu()是函数风格的API(自己管理)

    import  torch
    import  torch.nn as nn
    import  torch.nn.functional as F
    
    x = torch.randn(1,10)
    
    # 方法一
    # F.relu: 直接调用函数 并传入参数
    print(F.relu(x, inplace=True))   
    # tensor([[0.2846, 0.6158, 0.0000, 0.0000, 0.0000, 1.7980, 0.6466, 0.4263, 0.0000, 0.0000]])
    
    # 方法二
    # nn.Relu: 必须先实例化,如:创建layer, 
    layer = nn.ReLU(inplace=True)
    print(layer(x))    
    # tensor([[0.2846, 0.6158, 0.0000, 0.0000, 0.0000, 1.7980, 0.6466, 0.4263, 0.0000, 0.0000]])
    

    3. GPU加速

    • Pytorch中使用torch.device()选取并返回抽象出的设备

    • 然后,在定义的网络模块 或者 Tensor后面加上 .to(device变量)就可以将它们搬到设备上了。

    • .cuda()默认用gpu,不推荐.

    device = torch.device('cpu:0')                     #使用第一张显卡
    
    net = MLP().to(device)                             # 定义的网络
    
    criteon = nn.CrossEntropyLoss().to(device)         # 损失函数
    
    • 每次取出的训练集 和 验证集的 batch数据放到GPU上:
    data, target = data.to(device), target.cuda()     # 两种方式, .cuda()不推荐
    
    • 应用上面的案例 添加GPU加速,完整代码:
    view code
    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=200
    learning_rate=0.01
    epochs=10
    
    # 获取训练数据
    train_loader = torch.utils.data.DataLoader(
        datasets.MNIST('../data', train=True, download=True,         # train=True则得到的是训练集
                       transform=transforms.Compose([                 # transform进行数据预处理
                           transforms.ToTensor(),                     # 转成Tensor类型的数据
                           transforms.Normalize((0.1307,), (0.3081,)) # 进行数据标准化(减去均值除以方差)
                       ])),
        batch_size=batch_size, shuffle=True)                          # 按batch_size分出一个batch维度在最前面,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 MLP(nn.Module):
    
        def __init__(self):
            super(MLP, self).__init__()
    
            self.model = nn.Sequential(         # 定义网络的每一层,
                nn.Linear(784, 200),
                nn.ReLU(inplace=True),
                nn.Linear(200, 200),
                nn.ReLU(inplace=True),
                nn.Linear(200, 10),
                nn.ReLU(inplace=True),
            )
    
        def forward(self, x):
            x = self.model(x)
            return x
    
    device = torch.device('cuda:0')  # 使用第一张显卡
    net = MLP().to(device)
    # 定义sgd优化器,指明优化参数、学习率,net.parameters()得到这个类所定义的网络的参数[[w1,b1,w2,b2,...]
    optimizer = optim.SGD(net.parameters(), lr=learning_rate)
    criteon = nn.CrossEntropyLoss().to(device)
    
    
    for epoch in range(epochs):
    
        for batch_idx, (data, target) in enumerate(train_loader):
            data = data.view(-1, 28*28)          # 将二维的图片数据摊平[样本数,784]
            data, target = data.to(device), target.cuda()
    
            logits = net(data)                   # 前向传播
            loss = criteon(logits, target)       # nn.CrossEntropyLoss()自带Softmax
    
            optimizer.zero_grad()                # 梯度信息清空
            loss.backward()                      # 反向传播获取梯度
            optimizer.step()                     # 优化器更新
    
            if batch_idx % 100 == 0:             # 每100个batch输出一次信息
                print('Train Epoch: {} [{}/{} ({:.0f}%)]	Loss: {:.6f}'.format(
                    epoch, batch_idx * len(data), len(train_loader.dataset),
                           100. * batch_idx / len(train_loader), loss.item()))
    
    
        test_loss = 0
        correct = 0                                         # correct记录正确分类的样本数
        for data, target in test_loader:
            data = data.view(-1, 28 * 28)
            data, target = data.to(device), target.cuda()
    
            logits = net(data)
            test_loss += criteon(logits, target).item()     # 其实就是criteon(logits, target)的值,标量
    
            pred = logits.data.max(dim=1)[1]                # 也可以写成pred=logits.argmax(dim=1)
            correct += pred.eq(target.data).sum()
    
        test_loss /= len(test_loader.dataset)
        print('
    Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)
    '.format(
            test_loss, correct, len(test_loader.dataset),
            100. * correct / len(test_loader.dataset)))
    

    4. 多分类测试

    • 下面的例子中logits是一个 4*10 的Tensor

      • 可以理解成4张图片,每张图片有10维向量的预测

      • 然后对每一张照片的输出值执行softmaxargmax(dim=1),得出预测标签,与真实标签比较,得出准确率。

    import  torch
    import  torch.nn.functional as F
    
    logits = torch.rand(4, 10)
    pred = F.softmax(logits, dim=1)
    print(pred.shape)     # torch.Size([4, 10])
    
    pred_label = pred.argmax(dim=1)     # 每行最大值的下标      
    print(pred_label)  
    # tensor([8, 0, 7, 2]) 和 logits.argmax(dim=1)结果一样
    
    # 定义标签(真实值)
    label = torch.tensor([5, 0, 2, 7])
    
    # 与真实标签比较
    correct = torch.eq(pred_label, label)               
    print(correct)
    # tensor([False,  True, False, False]) 和 pred_label.eq(label)结果一样
    
    # 准确率
    print(correct.sum().float().item() / len(logits))   # 0.25
    
  • 相关阅读:
    18C 新的发行版和补丁模型
    单机数据库193000 升级到195000
    Mycat学习-单独启动mycat
    dstat 监控工具
    基于FTP 的本地Yum服务器配置
    记一次SQL PLUS 不能登录的异常处理
    FastDFS---分布式文件存储系统安装与使用
    ERROR
    记:一次安装Nginx的过程
    连接阿里RDS数据库
  • 原文地址:https://www.cnblogs.com/douzujun/p/13323078.html
Copyright © 2020-2023  润新知