[Marco de Pytorch] 2.1.3 Paquete de red neuronal nn y optimizador optm

Conceptos básicos de PyTorch: paquete de red neuronal nn y optimizador optm

torch.nn es una interfaz modular especialmente diseñada para redes neuronales. nn se basa en Autograd y se puede utilizar para definir y ejecutar redes neuronales.
Aquí presentamos principalmente algunas clases de uso común.

Convención: antorcha.nn Por conveniencia, le asignaremos un alias como nn. En este capítulo, existen otras convenciones de denominación además de nn

# 首先要引入相关的包
import torch
# 引入torch.nn并指定别名
import torch.nn as nn
#打印一下版本
torch.__version__
'1.0.0'

Además del alias nn, también citamos nn.functional. Este paquete contiene algunas funciones de uso común que se utilizan en redes neuronales. Las características de estas funciones son que no tienen parámetros que se puedan aprender (como ReLU, pool, DropOut, etc. La función se puede colocar en el constructor o no, pero no se recomienda aquí.

En circunstancias normales, estaríamos nn.functional configurados en mayúscula F , por lo que la abreviatura easy call

import torch.nn.functional as F

Definir una red

PyTorch nos ha preparado un modelo de red listo para usar, siempre que herede nn.Module e implemente su método de avance, PyTorch implementará automáticamente la función de retroceso de acuerdo con autograd. En la función de avance, se puede usar cualquier función soportada por tensor Use la sintaxis de Python como if, for loop, print, log, etc., y la escritura es consistente con la escritura estándar de Python.

class Net(nn.Module):
    def __init__(self):
        # nn.Module子类的函数必须在构造函数中执行父类的构造函数
        super(Net, self).__init__()
        
        # 卷积层 '1'表示输入图片为单通道, '6'表示输出通道数,'3'表示卷积核为3*3
        self.conv1 = nn.Conv2d(1, 6, 3) 
        #线性层,输入1350个特征,输出10个特征
        self.fc1   = nn.Linear(1350, 10)  #这里的1350是如何计算的呢?这就要看后面的forward函数
    #正向传播 
    def forward(self, x): 
        print(x.size()) # 结果:[1, 1, 32, 32]
        # 卷积 -> 激活 -> 池化 
        x = self.conv1(x) #根据卷积的尺寸计算公式,计算结果是30,具体计算公式后面第二章第四节 卷积神经网络 有详细介绍。
        x = F.relu(x)
        print(x.size()) # 结果:[1, 6, 30, 30]
        x = F.max_pool2d(x, (2, 2)) #我们使用池化层,计算结果是15
        x = F.relu(x)
        print(x.size()) # 结果:[1, 6, 15, 15]
        # reshape,‘-1’表示自适应
        #这里做的就是压扁的操作 就是把后面的[1, 6, 15, 15]压扁,变为 [1, 1350]
        x = x.view(x.size()[0], -1) 
        print(x.size()) # 这里就是fc1层的的输入1350 
        x = self.fc1(x)        
        return x

net = Net()
print(net)
Net(
  (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
  (fc1): Linear(in_features=1350, out_features=10, bias=True)
)

Los parámetros de la red que se pueden aprender son devueltos por net.parameters ()

for parameters in net.parameters():
    print(parameters)
Parameter containing:
tensor([[[[ 0.2745,  0.2594,  0.0171],
          [ 0.0429,  0.3013, -0.0208],
          [ 0.1459, -0.3223,  0.1797]]],

        [[[ 0.1847,  0.0227, -0.1919],
          [-0.0210, -0.1336, -0.2176],
          [-0.2164, -0.1244, -0.2428]]],

        [[[ 0.1042, -0.0055, -0.2171],
          [ 0.3306, -0.2808,  0.2058],
          [ 0.2492,  0.2971,  0.2277]]],

        [[[ 0.2134, -0.0644, -0.3044],
          [ 0.0040,  0.0828, -0.2093],
          [ 0.0204,  0.1065,  0.1168]]],

        [[[ 0.1651, -0.2244,  0.3072],
          [-0.2301,  0.2443, -0.2340],
          [ 0.0685,  0.1026,  0.1754]]],

        [[[ 0.1691, -0.0790,  0.2617],
          [ 0.1956,  0.1477,  0.0877],
          [ 0.0538, -0.3091,  0.2030]]]], requires_grad=True)
Parameter containing:
tensor([ 0.2355,  0.2949, -0.1283, -0.0848,  0.2027, -0.3331],
       requires_grad=True)
Parameter containing:
tensor([[ 2.0555e-02, -2.1445e-02, -1.7981e-02,  ..., -2.3864e-02,
          8.5149e-03, -6.2071e-04],
        [-1.1755e-02,  1.0010e-02,  2.1978e-02,  ...,  1.8433e-02,
          7.1362e-03, -4.0951e-03],
        [ 1.6187e-02,  2.1623e-02,  1.1840e-02,  ...,  5.7059e-03,
         -2.7165e-02,  1.3463e-03],
        ...,
        [-3.2552e-03,  1.7277e-02, -1.4907e-02,  ...,  7.4232e-03,
         -2.7188e-02, -4.6431e-03],
        [-1.9786e-02, -3.7382e-03,  1.2259e-02,  ...,  3.2471e-03,
         -1.2375e-02, -1.6372e-02],
        [-8.2350e-03,  4.1301e-03, -1.9192e-03,  ..., -2.3119e-05,
          2.0167e-03,  1.9528e-02]], requires_grad=True)
Parameter containing:
tensor([ 0.0162, -0.0146, -0.0218,  0.0212, -0.0119, -0.0142, -0.0079,  0.0171,
         0.0205,  0.0164], requires_grad=True)

net.named_parameters puede devolver parámetros y nombres que se pueden aprender al mismo tiempo.

for name,parameters in net.named_parameters():
    print(name,':',parameters.size())
conv1.weight : torch.Size([6, 1, 3, 3])
conv1.bias : torch.Size([6])
fc1.weight : torch.Size([10, 1350])
fc1.bias : torch.Size([10])

La entrada y la salida de la función de reenvío son ambas Tensor

input = torch.randn(1, 1, 32, 32) # 这里的对应前面fforward的输入是32
out = net(input)
out.size()
torch.Size([1, 1, 32, 32])
torch.Size([1, 6, 30, 30])
torch.Size([1, 6, 15, 15])
torch.Size([1, 1350])





torch.Size([1, 10])
input.size()
torch.Size([1, 1, 32, 32])

Antes de la propagación hacia atrás, primero borre el gradiente de todos los parámetros

net.zero_grad() 
out.backward(torch.ones(1,10)) # 反向传播的实现是PyTorch自动实现的,我们只要调用这个函数即可

Nota : torch.nn solo admite mini lotes y no admite el ingreso de una muestra a la vez, es decir, se debe ingresar un lote a la vez.

Es decir, incluso si ingresamos una muestra, la muestra se dividirá en lotes. Por lo tanto, todas las entradas aumentarán en una dimensión. Comparemos la entrada ahora mismo. Nn se define como 3 dimensiones, pero agregamos más cuando lo creamos manualmente. Una dimensión se convierte en 4 dimensiones, la primera 1 es tamaño de lote

Función de pérdida

En nn, PyTorch también prefabricado la función de pérdida de uso común, a continuación usamos MSELoss para calcular el error cuadrático medio

y = torch.arange(0,10).view(1,10).float()
criterion = nn.MSELoss()
loss = criterion(out, y)
#loss是个scalar,我们可以直接用item获取到他的python类型的数值
print(loss.item()) 
28.92203712463379

Optimizador

Después de que la retropropagación calcula los gradientes de todos los parámetros, también se necesitan métodos de optimización para actualizar los pesos y parámetros de la red. Por ejemplo, la estrategia de actualización del descenso de gradiente estocástico (SGD) es la siguiente:

peso = peso - tasa de aprendizaje * gradiente

Implemente la mayoría de los métodos de optimización en torch.optim, como RMSProp, Adam, SGD, etc. A continuación, usamos SGD como un ejemplo simple.

import torch.optim
out = net(input) # 这里调用的时候会打印出我们在forword函数中打印的x的大小
criterion = nn.MSELoss()
loss = criterion(out, y)
#新建一个优化器,SGD只需要要调整的参数和学习率
optimizer = torch.optim.SGD(net.parameters(), lr = 0.01)
# 先梯度清零(与net.zero_grad()效果一样)
optimizer.zero_grad() 
loss.backward()

#更新参数
optimizer.step()
torch.Size([1, 1, 32, 32])
torch.Size([1, 6, 30, 30])
torch.Size([1, 6, 15, 15])
torch.Size([1, 1350])

De esta manera, se ha logrado una diseminación completa de los datos de la red neuronal a través de PyTorch. El siguiente capítulo presentará las herramientas de carga y procesamiento de datos proporcionadas por PyTorch, que pueden usarse para procesar convenientemente los datos requeridos.

Después de leer esta sección, es posible que aún tenga dudas sobre los métodos de cálculo de algunos parámetros en el modelo de red neuronal. Esta parte se presentará en detalle en el Capítulo 2, Sección 4, Redes neuronales convolucionales, y en el Capítulo 3, Sección 2 Datos MNIST Hay notas detalladas en el código práctico para el reconocimiento de números escritos a mano.


Supongo que te gusta

Origin blog.csdn.net/yegeli/article/details/113524471
Recomendado
Clasificación