构建您的第一个 PyTorch 解决方案
介绍
考虑以下数字序列。它们对你来说有多难理解?
尽管分辨率失真且数字形状不规则,但计算出这个数字序列很容易。这要感谢我们的大脑,它让这个过程感觉很自然。当然,我们也应该感谢自己,多年来一直在学习和运用这些数字。
在 21 世纪,有可能模仿人脑吗?是的,通过人工智能或深度学习算法,计算机可以学习和执行对人脑来说非常自然和重复的任务,例如手写数字识别。
PyTorch
在本指南中,我们将使用神经网络 (NN)使用 PyTorch 从头开始开发手写数字分类器。
在 PyTorch 中,矩阵(数组)称为张量。张量是遵循确定的变换规则的数字或函数数组。PyTorch 张量类似于 NumPy 数组。它们只是用于数值计算的 n 维数组,与深度学习或梯度或计算图无关。向量是一维张量。矩阵是二维张量,具有三个索引的数组是三维张量(RGB 彩色图像)。
NumPy 数组和 Pytorch 张量之间的唯一区别在于 PyTorch 张量可以在 CPU 或 GPU 上工作,而 NumPy 数组没有 GPU 后端。要在 GPU 上工作,我们需要将张量转换为数据 CUDA 数据类型。
了解你的数据
如果你提出正确的问题,数据可以告诉你很多信息。
为了理解数据,数据科学家花费了大部分时间来收集数据集并对其进行预处理。进一步的任务相对容易。
在本指南中,我们将使用MNIST 数据库,该数据库包含 70,000 个手写数字,分为 60,000 张训练图像和 10,000 张测试图像。我们将使用 Pytorch,因为它提供了干净且准备好的数据,可以用最少的代码行来实现。
因此让我们开始进行以下导入。
import numpy as np
import torch
import torchvision
import matplotlib.pyplot as plt
from time import time
from torchvision import datasets, transforms
from torch import nn, optim
我们在这里遇到的一个常见问题是这些样本的大小不一样。神经网络需要图像具有固定大小。因此,我们需要在将数据输入管道之前定义对数据的转换。
我们使用torchvision库来实现这一点。它将帮助我们进行转换(使用torchvision.transform)并加载我们的数据集(使用torchvision.dataset)。
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)),
])
transforms.Compose():这会将所有提供给它的转换组合在一起。Compose 会逐一应用于输入。
transforms.ToTensor():这会将图像转换为数字,以便我们的系统可以理解。然后,它使用torch.ToTensor将PIL.Image (RGB) 或numpy.ndarray (H x W x C) 在\[0, 255\]范围内缩放到 (C x H x W) 在\[0, 1\]范围内。图像现在转换为Torch Tensor。
transforms.Normalize():这些值是估计的平均值和标准差。
探索您的数据
在要下载数据的目录中创建一个文件夹。下载数据后,将其加载到Dataloader中。在每个时期,dataloader都会对图像进行打乱,通过获得新的探索顺序使模型更加稳健。
batch_size表示每个生成的批次包含的样本数量。
我们将进行一些数据分析来检查我们的图像和标签形状是否匹配。
trainset = datasets.MNIST(r'..\input\MNIST', download=True, train=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
testset = datasets.MNIST(r'..\input\MNIST', download=True, train=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=True)
dataiter = iter(trainloader) # creating a iterator
images, labels = dataiter.next() # creating images for image and lables for image number (0 to 9)
print(images.shape)
print(labels.shape)
torch.Size([64, 1, 28, 28]):这表明每个批次中有 64 张图像,有 1 个颜色通道和 28x28 像素尺寸。
torch.Size([64]):64 张图像应该有 64 个与之关联的标签。
让我们显示训练集中的一个随机图像。
plt.imshow(images[0].numpy().squeeze(), cmap='gray_r');
太棒了!现在让我们显示数据集中的随机图像网格。在输入神经网络之前,您将大致了解数据集的样子。
figure = plt.figure()
num_of_images = 60
for index in range(1, num_of_images + 1):
plt.subplot(6, 10, index)
plt.axis('off')
plt.imshow(images[index].numpy().squeeze(), cmap='gray_r')
建立神经网络
神经网络只是一个适合某些数据的函数,通常称为神经元。每个神经元都有一定数量的加权输入。这些加权输入被相加(线性组合),然后通过激活函数得到单元的输出。单个神经元在深度学习中没有优势。因此,使用以下方程将多个神经元组合起来形成神经网络:
PyTorch 提供了一种构建此类网络的简单方法。通过使用nn.Sequential,张量可以按顺序通过操作。
它将网络包装成三个线性层,使用ReLu和Tanh激活函数。softmax 通常会产生接近 0 和 1 的概率,而浮点数无法表示值 0 和 1。因此,使用nn.LogSoftmax构建具有log-softmax输出的模型更为方便。
# Model creation with neural net Sequential model
model=nn.Sequential(nn.Linear(784,128), # 1 layer:- 784 input 128 o/p
nn.ReLU(), # Defining Regular linear unit as activation
nn.Linear(128,64), # 2 Layer:- 128 Input and 64 O/p
nn.Tanh(), # Defining Regular linear unit as activation
nn.Linear(64,10), # 3 Layer:- 64 Input and 10 O/P as (0-9)
nn.LogSoftmax(dim=1) # Defining the log softmax to find the probablities for the last output unit
)
print(model)
PyTorch 中的损失
为了在 PyTorch 中计算损失,我们将使用.nn 模块并定义负对数似然损失。似然是指某些计算参数产生某些已知数据的概率。请注意,criterion将nn.NLLLoss()和Logsoftmax()合并为一个类。输入包含每个类的分数(原始输出)。使用softmax函数,您可能会使用交叉熵损失。
要计算损失,首先定义标准,然后使用正确的标签传递网络的输出。
# defining the negative log-likelihood loss for calculating loss
criterion = nn.NLLLoss()
images, labels = next(iter(trainloader))
images = images.view(images.shape[0], -1)
logps = model(images) #log probabilities
loss = criterion(logps, labels) #calculate the NLL-loss
Autograd 和权重
print('Before backward pass: \n', model[0].weight.grad)
loss.backward() # to calculate gradients of parameter
print('After backward pass: \n', model[0].weight.grad)
训练神经网络(学习)
优化器将根据计算出的梯度更新参数。它将使用反向传播更新权重。结果可见,训练损失会随着每个时期逐渐减少。
# defining the optimiser with stochastic gradient descent and default parameters
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
print('Initial weights - ', model[0].weight)
images, labels = next(iter(trainloader))
images.resize_(64, 784)
# Clear the gradients, do this because gradients are accumulated
optimizer.zero_grad()
# Forward pass
output = model(images)
loss = criterion(output, labels)
# the backward pass and update weights
loss.backward()
print('Gradient -', model[0].weight.grad)
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~