[PyTorch] Primeiros passos

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"

Insira a descrição da imagem aqui

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.

Insira a descrição da imagem aqui


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

Insira a descrição da imagem aqui


Autograd: derivação automática

  1. 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数字来获得
  1. Tensor e gradiente (gradiente)
    Insira a descrição da imagem aqui

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.
① Fornece torch.utils.data.Datasetencapsulamento 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.

② Uso torch.utils.data.DataLoaderde 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)

  • datasetO tipo de conjunto de dados, indicando o conjunto de dados a ser carregado
  • batch_sizeIndique quantas amostras precisam ser carregadas para cada lote, o valor padrão é 1
  • shuffleIndique se os dados precisam ser misturados em cada época
  • samplerEstratégias para amostragem de amostras de conjuntos de dados
  • batch_samplerSemelhante ao amostrador, exceto que um lote de indicadores será retornado por vez
  • num_workersO número de processos filho usados ​​ao carregar dados. O valor padrão é 0, o que significa carregar dados no processo principal
  • collate_fnDefina uma lista de amostras mescladas para formar um mini_batch
  • pin_memorySe definido como verdadeiro, o carregador de dados copiará os tensores para a memória fixa CUDA e os retornará.
  • drop_lastSe 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
Insira a descrição da imagem aqui
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%

Acho que você gosta

Origin blog.csdn.net/kodoshinichi/article/details/109276291
Recomendado
Clasificación