刘二大人-《PyTorch深度学习实践》-lecture9-多分类问题-课程代码讲解-其中有自我理解的部分

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as func
import torch.optim as optim

# PIL(Python Image Library)-Python第三方图像处理库
batch_size = 64
transform = transforms.Compose([  # Compose是对图像变换,也就是对transforms.Totensor、Normalize等函数等一系列操作进行整合
    transforms.ToTensor(),  # ToTensor()能够把灰度范围从0-255变换到0-1之间,并且将28*28的单通道变成1*28*28的多通道
    transforms.Normalize((0.1307, ), (0.3081, ))
    # 首先我们要知道:标准正态分布--μ(期望=均值)=0, σ(标准差)=1
    # 用均值和标准差归一化张量图像,对每个通道而言,Normalize执行以下操作:
    # image=(image-mean)/std,image=0到1,mean=平均数,std=标准差
    # 通过此方法可以进一步调整Totensor之后的0-1范围,这样的分布可以让像素点的数值更均衡。
    # 其中均值0.1307就代表着标准正态分布里面的μ,标准差0.3081就相当于标准正态分布中的σ
])

train_dataset = datasets.MNIST(root='./MINIST',
                               train=True,  # train=True意味着载入该数据集的训练集部分
                               download=True,  # 如果没有提前下载,那么设置为True会进行自动下载并放入root=后面的文件夹中
                               transform=transform)
train_loader = DataLoader(train_dataset,
                          shuffle=True,
                          batch_size=batch_size)
test_dataset = datasets.MNIST(root='./MINIST',
                              train=False,  # train=False意味着载入该数据集的测试集部分
                              download=True,
                              transform=transform)
test_loader = DataLoader(test_dataset,
                         shuffle=True,
                         batch_size=batch_size)


class Net(torch.nn.Module):  # 定义神经网络
    def __init__(self):
        super(Net, self).__init__()
        self.l1 = torch.nn.Linear(784, 512)  # 将784列线性转换成512列,下面依次类推
        self.l2 = torch.nn.Linear(512, 256)
        self.l3 = torch.nn.Linear(256, 128)
        self.l4 = torch.nn.Linear(128, 64)
        self.l5 = torch.nn.Linear(64, 10)  # 最终将(N, 28, 28)转换成(N, 1, 10)的格式,N是batch_size

    def forward(self, x):
        x = x.view(-1, 784)  # 修饰输入层,-1代表当你不确定行数的时候,你只需要输入确定的列数,计算机会为你自动计算行数,也等同于此代码中计算N的个数
        x = func.relu(self.l1(x))
        x = func.relu(self.l2(x))
        x = func.relu(self.l3(x))
        x = func.relu(self.l4(x))
        return self.l5(x)


model = Net()  # 神经模型

criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# 因为此时的网络模型已经有点大了,所以选择一个更好一点的带冲量(momentum)学习器,来更好地进行梯度下降


def train(epoch):  # 因为我们在这个过程中要反复地进行训练、测试、训练、测试...如果一直写for循环cycl的话很不方便,所以我们在这里给他封装成一个函数
    running_loss = 0.0
    for batch_idx, (inputs, target) in enumerate(train_loader, 0):  # 此处加enumerate函数的而测试集不加的原因是:这个函数可以赋予索引号码012..
        optimizer.zero_grad()  # 优化器清零也就是梯度清零
        # forward + backward + update
        outputs = model(inputs)
        # print(target)
        # print(outputs.shape)
        loss = criterion(outputs, target)  # inputs就是线性变换完的x输入,target就是Y标签
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if batch_idx % 300 == 299:  # % 为取余操作,当余数为299时,输出batch_idx(batch索引号)+1,所以是每300个batch输出一次
            print('[%d, %4d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0  # 清除掉第一次300个batch的loss值总和,这样再次输出的时候就是301~600batch的loss值了


def test():
    correct = 0
    total = 0
    with torch.no_grad():  # 在test的过程中我们是不需要计算梯度的
        for data in test_loader:
            images, labels = data
            # print(labels)
            outputs = model(images)
            # print(outputs)
            _, predicted = torch.max(outputs.data, dim=1)
            # torch.max()函数会返回两个值,第一个值是具体的value(我们用下划线表示),第二个值是value所对应的索引号index(也就是predicted)
            # dim=1也可以写成数字1,都可识别,表示输出所在行的最大值;dim=0表示输出所在列的最大值
            # print(predicted)
            total += labels.size(0)  # .size(0)表示lable这个标签元组(N,1)的N位置的元素是多少,也就是行数,这样可以计算出总数
            correct += (predicted == labels).sum().item()
            # 当perdicted与labels完全相等的时候,那么就代表真,将会变成数字1,否则变成0,用于后面的.sum()求完全正确的次数,从而/total得出准确率
    print('Accuracy on test set: %d %%' % (100 * correct / total))


if __name__ == '__main__':  

    for epoch in range(10):  # 这里就是训练一轮,就测试一轮,一共重复10次
        train(epoch)

        test()

建议大家好好看我写的灰色字体部分,老师一嘴带过的地方我基本都有具体解释,希望能够帮到大家。

你可能感兴趣的:(深度学习,pytorch,分类,python)