当前位置:   article > 正文

PyTorch 学习笔记(五):多层全连接网络实现MNIST手写数字分类_torch.nn.crossentropyloss mnist

torch.nn.crossentropyloss mnist

先来介绍几个比较重要的函数

1. torch.nn.CrossEntropyLoss()函数

交叉熵损失函数,在pytorch中若模型使用CrossEntropyLoss这个loss函数,则不应该在最后一层再使用softmax进行激活,因为CrossEntropyLoss函数包括了softmax和计算交叉熵两个过程。

分析实例:https://www.jianshu.com/p/e184663e2f8a

2. torchvision.transforms函数

这个类提供了很多图片预处理的方法
transforms.ToTensor()是将图片转换成PyTorch中处理的对象Tensor,并且转化的过程中PyTorch自动将图片标准化了,也就是Tensor的范围是0-1;transforms.Normalize()需要传入两个参数:第一个参数是均值,第二个参数是方差,做的处理就是减均值,再除以方差。

transforms.Compose()将各种预处理操作组合在一起,如在下面的代码中先利用transforms.ToTensor将像素点的值由0-255转换到0-1,transforms.Normalize([0.5], [0.5])表示减去0.5再除以0.5,这样可以将图片转化到了-1到1之间,注意这是因为图片是灰度图,所以只有一个通道,如果是彩色图,有三个通道,那么用transforms.Normalize([a, b, c], [d, e, f])来表示每个通道对应的均值和方差。

3. torch.utils.data.DataLoader函数

torch.utils.data.DataLoader建立一个数据迭代器,先看看 dataloader.py脚本是怎么写的:

init(构造函数)中的几个重要的属性:

  • dataset:(数据类型 dataset)
    输入的数据类型。看名字感觉就像是数据库,C#里面也有dataset类,理论上应该还有下一级的datatable。这应当是原始数据的输入。PyTorch内也有这种数据结构。这里先不管,估计和C#的类似,这里只需要知道是输入数据类型是dataset就可以了。
  • batch_size:(数据类型 int)
    每次输入数据的行数,默认为1。PyTorch训练模型时调用数据不是一行一行进行的(这样太没效率),而是一捆一捆来的。这里就是定义每次喂给神经网络多少行数据,如果设置成1,那就是一行一行进行(个人偏好,PyTorch默认设置是1)。
  • shuffle:(数据类型 bool)
    洗牌。默认设置为False。在每次迭代训练时是否将数据洗牌,默认设置是False。将输入数据的顺序打乱,是为了使数据更有独立性,但如果数据是有序列特征的,就不要设置成True了。
  • collate_fn:(数据类型 callable,没见过的类型)
    将一小段数据合并成数据列表,默认设置是False。如果设置成True,系统会在返回前会将张量数据(Tensors)复制到CUDA内存中。(不太明白作用是什么,就暂时默认False)
  • batch_sampler:(数据类型 Sampler)
    批量采样,默认设置为None。但每次返回的是一批数据的索引(注意:不是数据)。其和batch_size、shuffle 、sampler and drop_last参数是不兼容的。我想,应该是每次输入网络的数据是随机采样模式,这样能使数据更具有独立性质。所以,它和一捆一捆按顺序输入,数据洗牌,数据采样,等模式是不兼容的。
  • sampler:(数据类型 Sampler)
    采样,默认设置为None。根据定义的策略从数据集中采样输入。如果定义采样规则,则洗牌(shuffle)设置必须为False。
  • num_workers:(数据类型 Int)
    工作者数量,默认是0。使用多少个子进程来导入数据。设置为0,就是使用主进程来导入数据。注意:这个数字必须是大于等于0的,负数估计会出错。
  • pin_memory:(数据类型 bool)
    内存寄存,默认为False。在数据返回前,是否将数据复制到CUDA内存中。
  • drop_last:(数据类型 bool)
    丢弃最后数据,默认为False。设置了 batch_size 的数目后,最后一批数据未必是设置的数目,有可能会小些。这时你是否需要丢弃这批数据。
  • timeout:(数据类型 numeric)
    超时,默认为0。是用来设置数据读取的超时时间的,但超过这个时间还没读取到数据的话就会报错。 所以,数值必须大于等于0。
  • worker_init_fn(数据类型 callable,没见过的类型)
    子进程导入模式,默认为Noun。在数据导入前和步长结束后,根据工作子进程的ID逐个按顺序导入数据。

脚本分析:https://blog.csdn.net/u014380165/article/details/79058479

多层全连接网络实现MNIST手写数字分类的代码如下:

import torch
from torch import optim, nn
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import numpy as np

# 加载数据集
def get_data():
    # 定义数据预处理操作, transforms.Compose将各种预处理操作组合在一起
    data_tf = transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])])
    train_dataset = datasets.MNIST(root='./data', train=True, transform=data_tf, download=True)
    test_dataset = datasets.MNIST(root='./data', train=False, transform=data_tf, download=True)

    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, drop_last=True)
    #test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, drop_last=True)
    return train_loader, test_dataset

# 构建模型,三层神经网络
class batch_net(nn.Module):
    def __init__(self, in_dim, hidden1_dim, hidden2_dim, out_dim):
        super(batch_net, self).__init__()
        self.layer1 = nn.Sequential(nn.Linear(in_dim, hidden1_dim), nn.BatchNorm1d(hidden1_dim), nn.ReLU(True))
        self.layer2 = nn.Sequential(nn.Linear(hidden1_dim, hidden2_dim), nn.BatchNorm1d(hidden2_dim), nn.ReLU(True))
        self.layer3 = nn.Sequential(nn.Linear(hidden2_dim, out_dim))
    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        return x



if __name__ == "__main__":
    # 超参数配置
    batch_size = 64
    learning_rate = 1e-2
    num_epoches = 5
    # 加载数据集
    train_dataset, test_dataset = get_data()
    # 导入网络,并定义损失函数和优化器
    model = batch_net(28*28, 300, 100, 10)
    if torch.cuda.is_available():
        model = model.cuda()
    criterion = nn.CrossEntropyLoss()
    opitimizer = optim.SGD(model.parameters(), lr=learning_rate)
    # 开始训练
    for i in range(num_epoches):
        for img, label in train_dataset:
            img = img.view(64, -1)
            img = Variable(img)
            #print(img.size())
            label = Variable(label)
            # forward
            out = model(img)
            loss = criterion(out, label)
            # backward
            opitimizer.zero_grad()
            loss.backward()
            opitimizer.step()
            # 打印
            print("epoches= {},loss is {}".format(i, loss))
    # 测试
    model.eval()
    count = 0
    for data in test_dataset:
        img, label = data
        img = img.view(img.size(0), -1)
        img = Variable(img, volatile=True)
        #label = Variable(label, volatile=True)
        out = model(img)
        _, predict = torch.max(out, 1)
        if predict == label:
            count += 1
    print("acc = {}".format(count/len(test_dataset)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

运行结果:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/235356
推荐阅读
相关标签
  

闽ICP备14008679号