Pytorch多分类问题实战

多分类问题实战

定义一个简单的神经网络模型,并使用SGD优化算法进行训练和测试MNIST数据集

import torch
import torch.nn.functional as F
import torch.optim as optim

"""
torchvision 可以帮助简化计算机视觉任务的实现,包括图像分类、目标检测、语义分割等。它提供了一些预训练的模型(如 ResNet、VGG、AlexNet 等)和用于训练和测试这些模型的数据集。此外,torchvision 还提供了数据转换操作,如图像预处理、数据增强和归一化等,用于准备数据以供模型使用。

在代码中,torchvision.datasets 模块用于加载 MNIST 数据集,并且 torchvision.transforms 模块用于定义数据转换操作,如将图像转换为张量、归一化等。这些模块都是 torchvision 库的一部分,可以帮助处理计算机视觉任务中的数据集和数据转换操作。
"""
from torchvision import datasets, transforms

# 每个训练批次的样本数量
batch_size = 200

# 学习率
learning_rate = 0.01

#批次的数量
epochs = 10

# 创建一个名为train_loader的数据加载器对象
train_loader = torch.utils.data.DataLoader(
    # 加载MNIST数据集。该类会检查指定路径'../data'是否存在MNIST数据集,如果不存在,则会下载数据集到该路径。
    # 当train=True时,datasets.MNIST会加载MNIST数据集的训练集部分,并返回一个包含训练图像和对应标签的数据集对象。这样我们可以使用这个数据集对象来训练模型。
    # 当train=False时,datasets.MNIST会加载MNIST数据集的测试集部分,并返回一个包含测试图像和对应标签的数据集对象。这样我们可以使用这个数据集对象来评估模型的性能。
    datasets.MNIST('../data',train=True,download=True,
                   
                   # 使用transforms.Compose函数将多个预处理操作组合在一起。
                   transform=transforms.Compose([
                       
                       # MNIST数据集中的图像最初是PIL图像对象,通过该操作将其转换为张量形式,便于后续的计算和训练。
                       transforms.ToTensor(), 
                       
                       # 对数据进行标准化处理。这里使用了均值和标准差进行标准化,均值为0.1307,标准差为0.3081。这样做                          的目的是将数据的分布调整为均值为0,标准差为1的标准正态分布,有助于提高模型的训练效果。
                       transforms.Normalize((0.1307,),(0.3081,))
                   ])
                  ),
    # 在每个训练批次之前对数据进行洗牌,以增加训练的随机性。这样做可以避免模型仅仅学习到样本的固定顺序,提高模型的泛化能力。
    batch_size=batch_size,shuffle=True
)

test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data',train=False,download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,),(0.3081,))
                   ]
                   )),
    batch_size=batch_size,shuffle=True
)

w1, b1 = torch.randn(200, 784,requires_grad=True),\
        torch.zeros(200, requires_grad=True)
w2, b2 = torch.randn(200, 200,requires_grad=True),\
        torch.zeros(200, requires_grad=True)
w3, b3 = torch.randn(10, 200,requires_grad=True),\
        torch.zeros(10, requires_grad=True)

"""
是PyTorch中的一个函数,用于对张量进行Kaiming正态分布初始化。在给定的张量上应用Kaiming初始化方法,可以初始化具有较好初始权重的神经网络模型,以便更有效地进行训练。

具体地说,torch.nn.init.kaiming_normal_()函数采用以下方式初始化张量:

它从一个均值为0,标准差为gain / sqrt(fan_in)的正态分布中,随机地抽取值来填充输入张量。其中,fan_in是输入张量的扇入(输入单元的数量),gain是一个可选的缩放因子,通常取sqrt(2)。
Kaiming初始化方法(也称为"He初始化"或"He正态分布初始化)是为了解决深度神经网络中梯度消失或梯度爆炸问题而提出的。通过使用合适的初始权重,可以更好地保持梯度在网络层之间传播,从而提高网络的训练效果。
"""
torch.nn.init.kaiming_normal_(w1)
torch.nn.init.kaiming_normal_(w2)
torch.nn.init.kaiming_normal_(w3)


def forward(x):
    x = x@w1.t() + b1
    x = F.relu(x)
    x = x@w2.t() + b2
    x = F.relu(x)
    x = x @ w3.t() + b3
    x = F.relu(x)
    return x

# 创建一个使用随机梯度下降算法的优化器对象
optimizer = optim.SGD([w1,b1,w2,b2,w3,b3],lr=learning_rate)
criteon = torch.nn.CrossEntropyLoss()

for epoch in range(epochs):
    # 使用enumerate函数对train_loader进行迭代,同时获取索引和对应的数据。
    # batch_idx:这是一个索引变量,用于表示当前批次的索引号。
    # (data, target):一个元组,data表示图像数据,target表示标签。
    for batch_idx,(data,target) in enumerate(train_loader):
        # data是一个图像数据的张量,其形状为(batch_size, 1, 28, 28),表示每个批次中有batch_size个图像,每个图像大小为28x28像素。
        # -1:它表示在给定维度上自动计算对应的大小。在这里,将其用于第一个维度,即批次维度,以便根据剩余的维度自动计算批次大小。28*28:这是新的形状,表示将每个图像展平为一个大小为784的向量。通过将28x28像素的图像展开为一维向量,可以将图像数据作为特征输入到模型中。
        data = data.view(-1,28*28)  # view()函数对张量进行形状变换

        logits = forward(data)
        
        # CrossEntropyLoss已包含Softmax
        loss = criteon(logits,target)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (batch_idx % 100) == 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()
            ))

    test_loss = 0
    correct = 0
    for data,target in test_loader:
        data = data.view(-1,28 * 28)
        logits = forward(data)
        test_loss += criteon(logits,target).item()

        pred = logits.data.max(1)[1]
        correct += pred.eq(target.data).sum()

    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)
    ))

输出结果

Train Epoch:0 [0/60000 (0%)]	Loss: 3.088388
Train Epoch:0 [20000/60000 (33%)]	Loss: 0.587288
Train Epoch:0 [40000/60000 (67%)]	Loss: 0.374099

Test set: Average loss: 0.0017, Accuracy: 8983/10000 (90%)

Train Epoch:1 [0/60000 (0%)]	Loss: 0.276809
Train Epoch:1 [20000/60000 (33%)]	Loss: 0.418936
Train Epoch:1 [40000/60000 (67%)]	Loss: 0.340238

Test set: Average loss: 0.0013, Accuracy: 9190/10000 (92%)

Train Epoch:2 [0/60000 (0%)]	Loss: 0.284477
Train Epoch:2 [20000/60000 (33%)]	Loss: 0.260783
Train Epoch:2 [40000/60000 (67%)]	Loss: 0.228615

Test set: Average loss: 0.0012, Accuracy: 9312/10000 (93%)

Train Epoch:3 [0/60000 (0%)]	Loss: 0.233259
Train Epoch:3 [20000/60000 (33%)]	Loss: 0.155293
Train Epoch:3 [40000/60000 (67%)]	Loss: 0.229180

Test set: Average loss: 0.0010, Accuracy: 9388/10000 (94%)

Train Epoch:4 [0/60000 (0%)]	Loss: 0.144686
Train Epoch:4 [20000/60000 (33%)]	Loss: 0.216506
Train Epoch:4 [40000/60000 (67%)]	Loss: 0.146811

Test set: Average loss: 0.0010, Accuracy: 9430/10000 (94%)

Train Epoch:5 [0/60000 (0%)]	Loss: 0.197008
Train Epoch:5 [20000/60000 (33%)]	Loss: 0.276877
Train Epoch:5 [40000/60000 (67%)]	Loss: 0.247613

Test set: Average loss: 0.0009, Accuracy: 9462/10000 (95%)

Train Epoch:6 [0/60000 (0%)]	Loss: 0.162596
Train Epoch:6 [20000/60000 (33%)]	Loss: 0.138650
Train Epoch:6 [40000/60000 (67%)]	Loss: 0.180352

Test set: Average loss: 0.0008, Accuracy: 9503/10000 (95%)

Train Epoch:7 [0/60000 (0%)]	Loss: 0.141457
Train Epoch:7 [20000/60000 (33%)]	Loss: 0.113807
Train Epoch:7 [40000/60000 (67%)]	Loss: 0.112289

Test set: Average loss: 0.0008, Accuracy: 9517/10000 (95%)

Train Epoch:8 [0/60000 (0%)]	Loss: 0.171669
Train Epoch:8 [20000/60000 (33%)]	Loss: 0.182690
Train Epoch:8 [40000/60000 (67%)]	Loss: 0.207414

Test set: Average loss: 0.0008, Accuracy: 9554/10000 (96%)

Train Epoch:9 [0/60000 (0%)]	Loss: 0.175700
Train Epoch:9 [20000/60000 (33%)]	Loss: 0.130695
Train Epoch:9 [40000/60000 (67%)]	Loss: 0.074462

Test set: Average loss: 0.0007, Accuracy: 9551/10000 (96%)
posted @ 2023-05-30 20:55  同淋雪  阅读(151)  评论(0)    收藏  举报