pytorch训练神经网络详细讲解,初学者入门血荐!!!!

本文使用代码加注释的方式,解释一个简单的Pytorch搭建运行神经网络的详细步骤。然后对归一化,数据集等问题专门解释。有什么问题可以随时和博主讨论哦。

代码

pytorch训练神经网络

# coding=utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torchvision
import torchvision.transforms as transforms
import torch.optim as optim
import numpy as np

# torchvision输出的是PILImage,值的范围是[0, 1].
# 我们将其转化为tensor数据,并归一化为[-1, 1]。
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize(mean = (0.5, 0.5, 0.5), std = (0.5, 0.5, 0.5)),
                                ])
 
# 训练集,将相对目录./data下的cifar-10-batches-py文件夹中的全部数据(50000张图片作为训练数据)加载到内存中
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,transform=transform)
 
# 将训练集的50000张图片划分成12500份,每份4张图,用于mini-batch输入。shffule=True在表示不同批次的数据遍历时,打乱顺序。num_workers=2表示使用两个子进程来加载数据
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=False, num_workers=2)
 
#测试集,将相对目录./data下的cifar-10-batches-py文件夹中的全部数据(10000张图片作为测试数据)加载到内存中
testset = torchvision.datasets.CIFAR10(root='./data', train=False, transform=transform)
 
# 将测试集的10000张图片划分成2500份,每份4张图,用于mini-batch输入。
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)
 
 
class Net(nn.Module):
    # 定义Net的初始化函数,这个函数定义了该神经网络的基本结构
    def __init__(self):
        super(Net, self).__init__()  # 复制并使用Net的父类的初始化方法,即先运行nn.Module的初始化函数
        self.conv1 = nn.Conv2d(3, 6, 5)  # 定义conv1函数的是图像卷积函数:输入为图像(3个通道),输出为 6张特征图, 卷积核为5x5正方形
        self.conv2 = nn.Conv2d(6, 16, 5)  # 定义conv2函数的是图像卷积函数:输入为6张特征图,输出为16张特征图, 卷积核为5x5正方形
        
        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 定义fc1(fullconnect)全连接函数1为线性函数:y = Wx + b,并将16*5*5个节点连接到120个节点上。
        self.fc2 = nn.Linear(120, 84)  # 定义fc2(fullconnect)全连接函数2为线性函数:y = Wx + b,并将120个节点连接到84个节点上。
        self.fc3 = nn.Linear(84, 10)  # 定义fc3(fullconnect)全连接函数3为线性函数:y = Wx + b,并将84个节点连接到10个节点上。
    # 定义该神经网络的向前传播函数,该函数必须定义,一旦定义成功,向后传播函数也会自动生成(autograd)
    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))  # 输入x经过卷积conv1之后,经过激活函数ReLU,使用2x2的窗口进行最大池化Max pooling,然后更新到x。
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)  # 输入x经过卷积conv2之后,经过激活函数ReLU,使用2x2的窗口进行最大池化Max pooling,然后更新到x。
        x = x.view(-1, self.num_flat_features(x))  # view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备。
        x = F.relu(self.fc1(x))  # 输入x经过全连接1,再经过ReLU激活函数,然后更新x
        x = F.relu(self.fc2(x))  # 输入x经过全连接2,再经过ReLU激活函数,然后更新x
        x = self.fc3(x)  # 输入x经过全连接3,然后更新x
        return x
 
    # 使用num_flat_features函数计算张量x的总特征量(把每个数字都看出是一个特征,即特征总量),比如x是4*2*2的张量,那么它的特征总量就是16。
    def num_flat_features(self, x):
        size = x.size()[1:]  # 这里为什么要使用[1:],是因为pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。
        # 【1:】让我们把注意力放在后3维上面,是因为 x.size() 会 return [nSamples, nChannels, Height, Width]。我们只需要展开后三项成为一个一维的 tensor。
        num_features = 1
        for s in size:
            num_features *= s
        return num_features   
    
net = Net()

#====================================================================================
 
criterion = nn.CrossEntropyLoss()#交叉熵损失函数
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)#使用SGD(随机梯度下降)优化,学习率为0.001,动量为0.9
for epoch in range(10):  # 遍历数据集10次
 
    running_loss = 0.0
    #对trainloader遍历,i为trainloader的下标,data为trainloader的值,0为i下标的起始点
    for i, data in enumerate(trainloader, 0):

        inputs, labels = data  # data的结构是:[4x3x32x32的张量,长度4的张量]
        inputs, labels = Variable(inputs), Variable(labels)  # 把input数据从tensor转为variable
        optimizer.zero_grad()  # 将参数的grad值初始化为0
 
        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)  # 将output和labels使用叉熵计算损失
        loss.backward()  # 反向传播
        optimizer.step()  # 用SGD更新参数
 
        # 每2000批数据打印一次平均loss值
        running_loss += loss.item()  # loss本身为Variable类型,所以要使用data获取其Tensor,因为其为标量,所以取0  或使用loss.item()
        if i % 2000 == 1999:  # 每2000批打印一次
            print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0
print('Finished Training')
 
correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(Variable(images))
        value, predicted = torch.max(outputs.data, 1)  # outputs.data是一个4x10张量,将每一行的最大的那一列的值和序号各自组成一个一维张量返回,第一个是值的张量,第二个是序号的张量。
        #label.size(0) 是一个数
        total += labels.size(0)
        correct += (predicted == labels).sum()  # 两个一维张量逐行对比,相同的行记为1,不同的行记为0,再利用sum(),求总和,得到相同的个数。
 
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

关于归一化(待续)

归一化操作就是把一系列数据的值等价变为【0,1】之间的小数。归一化的意义是把各个特征统一化,无差别化对待。 比如一张图片有两个特征,特征A的范围是【1,10】,特征B的范围是【1,1000】。如果不归一化,那么对他们的操作,例如对不同特征的提取,会出现尺度上的不统一,一个特征已经学好了,另一个特征还没怎么学习。通过归一化对特征,无差别话对待,可以提高模型准确度,提升模型收敛速度。

关于数据集

如果每次都从网上下载cifar10数据集,耗时且浪费时间。
本文在官网下载数据保存在本地C:\Users\10615\data下,其中C:\Users\10615\为python的主目录所以代码中使用相对路径./data。cifar10数据集-官网

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值