Conhecimento introdutório
Este documento é baseado no tutorial introdutório de 60 minutos do site oficial
"O que é PyTprch"
"PyTorch Deep Learning: 60 Minutes Quick Start (Official Website Translation)" Por Huang
Haiguang Parte do conteúdo vem de "PyTorch Machine Learning From Entry to Actual Combat" - Imprensa da indústria de máquinas
Operações numéricas comumente usadas e características do Numpy
Existem muitas operações na biblioteca pytorch que podem ser comparadas e usadas como referência no processamento na biblioteca numpy, e numpy também é uma biblioteca de processamento numérico muito importante e poderosa no aprendizado de máquina. Recomenda-se que os leitores primeiro entendam as operações comuns em numpy.
ps Aqui estão alguns mapas mentais da biblioteca numpy. Os leitores podem verificar se há vazamentos. Se você nunca usou o numpy antes, pode clicar no link abaixo para começar rapidamente ~
"tutorial numpy | tutorial novato"
E como uma das estruturas de dados mais importantes na biblioteca numpy é uma matriz multidimensional chamada ndarray, muitos de seus recursos e operações também podem ser emprestados dos tipos de lista em python, e alguns conceitos de lista também são organizados a seguir.
ps é muito simples de organizar e só pode ser usado para classificação simples.
O que é PyTorch
PyTorch é um pacote de software de computação científica baseado em Python, principalmente para os dois grupos de públicos a seguir:
- Para usar a função de computação GPU, use-a em vez de numpy
- Plataforma de pesquisa de aprendizado profundo buscando flexibilidade e velocidade
Autograd: derivação automática
- Tensor e ndarray
O relacionamento entre tensor e pytorch pode ser comparado ao relacionamento entre ndarray baseado em numpy, e os dois têm grandes semelhanças em tipos, declarações, definições e operações.
[Operações semelhantes] (exemplo)
x = torch.empty(m,n)#构造一个未初始化的mxn的矩阵
x = torch.rand(m,n)#构造一个随机初始化的mxn的矩阵
x = torch.zeros(m,n,dtype = torch.long)#用零填充一个mxn的矩阵,且元素为long类型
x = torch.tensor([1,2,3]) #通过已知数据来构造张量
[Operações ligeiramente diferentes] (exemplo)
x = torch.rand(m,n)
y = x.view(s,t)#将mxn的矩阵x变成sxt维度的矩阵,且是新建改变
x = torch.rand(1)
x.item() #用.item()方法使单个元素张量作为python数字来获得
- Tensor e gradiente (gradiente)
A caixa rosa na imagem acima é o local que precisa de atenção extra, e algumas explicações serão fornecidas a seguir.
[1]: O atributo .grad_fn indica cada tensor e sua função de cálculo correspondente.
- O objeto tensor criado pelo usuário não possui este atributo porque não é obtido por cálculos relacionados
- De acordo com diferentes tipos de cálculos, os atributos grad_fn também são diferentes
- Se o atributo require_grad não estiver definido como True, você não obterá o atributo grad_fn correspondente porque você não permite que ele rastreie os registros de cálculo.
import torch
x = torch.ones(2,2)
y = x + 2
z = x * 3
print(x.grad_fn)
print(y.grad_fn)
print(z.grad_fn)
#None
#None
#None
x = torch.ones(2,2,requires_grad = True)
y = x + 2
z = x * 3
print(x.grad_fn)
print(y.grad_fn)
print(z.grad_fn)
#None
#<AddBackward0 object at 0x000002392660F240>
#<MulBackward0 object at 0x000002392660F2B0>
[2]: Evita o histórico de cálculos de rastreamento de tensor e uso de memória
- Ao inicializar um tensor, a propriedade .requires_grad não é explicitamente definida como True
- Use torch.no_grad () para embrulhar blocos de código
import torch
x = torch.ones(2,2,requires_grad = True)
print(x.requires_grad)
print((x*2).requires_grad)
with torch.no_grad():
print((x*2).requires_grad)
#True
#True
#False
Redes neurais
As redes neurais são diferentes de acordo com sua profundidade e estrutura. Uma rede neural feedforward simples com camada de entrada oculta camada de saída, só precisa descobrir sobre cálculo progressivo, retropropagação, função de perda, ativação O conhecimento da função é suficiente.
Para obter detalhes, consulte a postagem do blog "[PyTorch] Deep Learning Foundation: Neural Network"
1. Implementação PyTorch de rede neural de camada única
Com base em alguns conhecimentos básicos da postagem anterior do blog, construiremos e treinaremos uma rede neural com apenas uma camada linear oculta.
As etapas do treinamento da rede neural:
- preparação de dados
Preparação de dados - converta os dados que queremos usar em um formato que o PyTorch possa manipular: encapsule o conjunto de dados e divida os dados estruturados em lotes.
① Fornecetorch.utils.data.Dataset
encapsulamento de dados.
Esta categoria é a classe pai de todos os conjuntos de dados que precisam ser carregados. Ao definir subclasses, você precisa sobrecarregar_len_
e_getitem_
duas funções. A primeira retorna o tamanho do conjunto de dados e a última implementa o índice de subscrito do conjunto de dados.
② Usotorch.utils.data.DataLoader
de carregamento de dados, amostragem e geração de iterador
class torch.utils.data.DataLoader(dataset,batch_size = 1,shuffle = False, sampler = None,batch_sampler = None,num_workers = 0,collate_fn = <function default_collate>, pin_memory = False,drop_last = False)
dataset
O tipo de conjunto de dados, indicando o conjunto de dados a ser carregadobatch_size
Indique quantas amostras precisam ser carregadas para cada lote, o valor padrão é 1shuffle
Indique se os dados precisam ser misturados em cada épocasampler
Estratégias para amostragem de amostras de conjuntos de dadosbatch_sampler
Semelhante ao amostrador, exceto que um lote de indicadores será retornado por veznum_workers
O número de processos filho usados ao carregar dados. O valor padrão é 0, o que significa carregar dados no processo principalcollate_fn
Defina uma lista de amostras mescladas para formar um mini_batchpin_memory
Se definido como verdadeiro, o carregador de dados copiará os tensores para a memória fixa CUDA e os retornará.drop_last
Se definido como verdadeiro, o último lote incompleto será descartado.
- Construir a estrutura da rede e inicializar os pesos
- Determinar a função de ativação
- Executar cálculo progressivo
- Determine a função de perda e calcule o valor da perda
- Parâmetros de retropropagação e atualização
Repita o processo de cálculo progressivo e de retropropagação mencionado acima até que a convergência ou a condição de término seja alcançada.
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
from sklearn.datasets import load_iris
from torch.autograd import Variable
from torch.optim import SGD
#动态判断GPU是否可用,方便在不同类型的处理器上进行迁移
use_cuda = torch.cuda.is_available()
print("use_cuda: ",use_cuda)
#加载数据集,因为是模块里封装好的数据集,只需加载即可使用
iris = load_iris()
print(iris.keys())
#数据预处理,从数据集中将输入输出的信息分离出来并封装成Variable形式
x=iris['data']
y = iris['target']
x = torch.FloatTensor(x)
y = torch.LongTensor(y)
x,y = Variable(x),Variable(y)
#定义神经网络模型
'''
PyTorch中自定义的模型都需要继承Module,并重写forward方法完成前向计算
'''
class Net(torch.nn.Module):
#初始化函数接受自定义额输入特征维数、隐含层特征维数和输出层的特征维数
def __init__(self,n_feature,n_hidden,n_output):
super(Net,self).__init__()
self.hidden = torch.nn.Linear(n_feature,n_hidden)#线性隐含层
self.predict = torch.nn.Linear(n_hidden,n_output)#线性输出层
#重写前向传播过程
def forward(self,x):
x = F.sigmoid(self.hidden(x))
x = self.predict(x)
out = F.log_softmax(x,dim = 1)
return out
#网络实例化并打印查看网络结构
net = Net(n_feature = 4,n_hidden = 5,n_output = 4)
print(net)
#根据iris数据集,输入特征必须是4维的,其余两层的特征维数可以自行选择
#判断GPU是否可用,可以灵活调整数据计算
if use_cuda:
x = x.cuda()
y = y.cuda()
net = net.cuda()
#定义神经网络训练的优化器,并设置学习率为0.5
optimizer = SGD(net.parameters(),lr = 0.5)
#进行训练
px,py = [],[]#用于记录要绘制的数据
for i in range(1000):
#数据传入网络并进行前向计算
prediction = net(x)
#计算loss
loss = F.nll_loss(prediction,y)
#清除网络状态
optimizer.zero_grad()
#loss反向传播
loss.backward()
#更新参数
optimizer.step()
#在训练过程中打印每次迭代的损失情况
print(i," loss: ",loss.data.item())
px.append(i)
py.append(loss.data.item())
#每10次迭代绘制训练动态
if i % 10 == 0:
plt.cla()
plt.plot(px,py,'r-',lw = 1)
plt.text(0,0,'Loss = %.4f' % loss.data.item(),fontdict = {
'size':20,'color':'red'})
plt.pause(0.1)
2. O mecanismo de chamada de rede neural em
PyTorch 3. PyTorch constrói classificador de rede neural
Para obter detalhes sobre a função de perda, função objetivo e otimizador, consulte a seguinte postagem do blog
"[PyTorch] Rede Neural Profunda e Treinamento"
Use o PyTorch para construir uma rede neural que consiste em uma camada de entrada, uma camada oculta totalmente conectada e uma camada de saída para classificar o conjunto de dados MNIST.
Os leitores podem usar o código a seguir para se familiarizar com as características e configuração dos parâmetros da rede neural
(1) Parâmetros de configuração
'''
配置库和配置参数
'''
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
#配置超参数
torch.manual_seed(1)#设置随机数种子,确保结果可能会重复
input_size = 784
hidden_size = 500
num_classes = 10
num_epochs = 5#训练次数
batch_size = 100#批处理大小
learning_rate = 0.001
(2) Carregue o conjunto de dados
'''
加载MINST数据集
'''
train_dataset = dsets.MNIST(root= './data',train = True,transform = transforms.ToTensor(),download = True)
#将数据集下载(download)作为训练集(train),其中指定数据保持的位置(root),并且将取值范围从[0,255]转换成[0,1.0](transform)
test_dataset = dsets.MNIST(root = './data',train = False,transform = transforms.ToTensor())
#另保存一份测试集,同样需要进行数值转换
(3) Configurações de processamento em lote
'''
数据批处理设置
'''
#DataLoader(Input Pipeline)
#在训练集中,shuffle必须设置为True,表示次序是随机的
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,batch_size = batch_size,shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,batch_size = batch_size,shuffle = False)
(4) Construir modelo DNN
'''
创建DNN模型
'''
class Net(nn.Module):
def __init__(self,input_size,hidden_size,num_classes):
super(Net,self).__init__()
self.fc1 = nn.Linear(input_size,hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size,num_classes)
def forward(self,x):
out = self.fc1(x)
out = self.relu(out)
out = self.fc2(out)
return out
net = Net(input_size,hidden_size,num_classes)
#打印模型,呈现网络结构
print(net)
【输出 结果】
Net (
(fc1): Linear (in_features = 784, out_features = 500, bias = True)
(relu): ReLU ()
(fc2): Linear (in_features = 500, out_features = 10, bias = True)
)
(5) Treinamento de modelo
'''
模型训练,将图像和标签都用Variable类进行包装,然后放入模型中进行输出
'''
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(),lr = learning_rate)
#开始训练
for epoch in range(num_epochs):
for i,(images,labels) in enumerate(train_loader):#进行批处理
#将tensor类型转换成Variable类型
images = Variable(images.view(-1,28*28))
Labels = Variable(labels)
#前向计算+反向传播+使用优化器
optimizer.zero_grad()#梯度清零
outputs = net(images)
loss = criterion(outputs,labels)
loss.backward()#后向传播,计算梯度
optimizer.step()#梯度更新
if(i+1)%100 == 0:
print('Epoch [%d/%d],Step[%d/%d],Loss: %.4f'%(epoch+1,num_epochs,i+1,len(train_dataset)//batch_size,loss.data.item()))
【输出 结果】
Época [1/5], Etapa [100/600], Perda: 0,1175
Época [1/5], Etapa [200/600], Perda: 0,1390
Época [1/5], Etapa [300/600 ], Perda: 0,2715
Época [1/5], Etapa [400/600], Perda: 0,1825
Época [1/5], Etapa [500/600], Perda: 0,1173
Época [1/5], Etapa [600 / 600], Perda: 0,1280
Época [2/5], Etapa [100/600], Perda: 0,1060
Época [2/5], Etapa [200/600], Perda: 0,0543
Época [2/5], Etapa [300 / 600], Perda: 0,1447
Época [2/5], Etapa [400/600], Perda: 0,1715
Época [2/5], Etapa [500/600], Perda: 0,0646
Época [2/5], Etapa [ 600/600], Perda: 0,0643
Época [3/5], Etapa [100/600], Perda: 0,1027
Época [3/5], Etapa [200/600], Perda: 0,0191
Época [3/5], Etapa [300/600], Perda: 0,0442
Época [3/5], Etapa [400/600], Perda: 0,0599
Época [3/5], Etapa [500/600], Perda: 0,0470
Época [3/5], Etapa [600/600], Perda: 0,0422
Época [4/5], Etapa [100/600], Perda: 0,0448
Época [4/5], Etapa [200/600], Perda: 0,1024
Época [4/5], Etapa [300/600], Perda: 0,0436
Época [4/5], Etapa [400/600], Perda : 0,0686
Época [4/5], Etapa [500/600], Perda: 0,0393
Época [4/5], Etapa [600/600], Perda: 0,0179
Época [5/5], Etapa [100/600], Perda: 0,0292
Época [5/5], Etapa [200/600], Perda: 0,0473
Época [5/5], Etapa [300/600], Perda: 0,0563
Época [5/5], Etapa [400/600] , Perda: 0,0552
Época [5/5], Etapa [500/600], Perda: 0,0352
Época [5/5], Etapa [600/600], Perda: 0,0244
(6) Verificação no conjunto de teste
'''
在测试集测试识别率
'''
correct = 0
total = 0
for images,labels in test_loader:
images = Variable(images.view(-1,28*28))
outputs = net(images)
_,predicted = torch.max(outputs.data,1)#得到预测结果
total += labels.size(0)#正确结果
correct += (predicted == labels).sum()#正确结果总数
print('Accuracy of the network on the 10000 test images: %d %%' % (100*correct // total))
[Resultado de saída]
Precisão da rede nas 10.000 imagens de teste: 97%