Entrenaremos al modelo, para lo cual crearemos una clase, Net. Esta clase, a su vez, hereda de la clase nn.Module. El siguiente paso es definir las capas de nuestra red neural profunda. Empezamos definiendo los parámetros para las capas totalmente conectadas con el método __init__().
En nuestro caso, tenemos cuatro capas. Cada una de nuestras capas espera que el primer parámetro sea el tamaño de entrada, que en nuestro caso es de 28 por 28. Esto resulta en 64 conexiones, que se convertirán en la entrada de la segunda capa. Repetimos el mismo paso para la tercera y la cuarta capa. El único cambio en la cuarta capa será que la salida es de 10 neuronas, representando diez clases de las imágenes.
Hemos definido las capas, pero también necesitamos definir cómo interactúan entre sí. Esto se hace con la función def forward(self, x) de abajo. Hemos construido una red neuronal totalmente conectada, de alimentación hacia adelante, lo que significa que pasamos de la entrada a la salida de una manera hacia adelante. El paso adelante comienza con la función de activación, que es relu o Activación Lineal Rectificada.
ReLu es la función de activación más utilizada en las redes neuronales profundas debido a sus ventajas de ser no lineal, así como de tener la capacidad de no activar todas las neuronas al mismo tiempo. En términos sencillos, esto significa que a la vez, sólo se activan unas pocas neuronas, haciendo que la red sea escasa y muy eficiente.
Para la capa de salida, usaremos la función softmax, a menudo usada para un problema de clasificación de múltiples clases.
123456789101112131415classNet(nn.Module):def__init__(self):super(Net, self).__init__() self.fc1 = nn.Linear(28*28,64) self.fc2 = nn.Linear(64,64) self.fc3 = nn.Linear(64,64) self. fc4 = nn.Lineal(64,10)defforward(self, x): x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = F.relu(self.fc3(x)) x = self.fc4(x)return F.log_softmax(x, dim=1)
pitón
Habiendo entrenado al modelo, echemos un vistazo con el código de abajo.
12net = Net()print(net)
pitón
Salida:
123456Net( (fc1): Lineal(in_features=784, out_features=64, bias=True) (fc2): Lineal(in_features=64, out_features=64, bias=True) (fc3): Lineal(in_features=64, out_features=64, sesgo=Verdad) (fc4): Lineal(in_features=64, out_features=10, bias=True) )
Construimos la red neuronal completamente conectada (llamada red) en el paso anterior, y ahora predecimos las clases de dígitos. Usaremos el optimizador adam para optimizar la red, y teniendo en cuenta que se trata de un problema de clasificación, usaremos la entropía cruzada como función de pérdida. Esto se hace usando las líneas de código que se muestran a continuación. El argumento lr especifica la tasa de aprendizaje de la función del optimizador.
12loss_criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(net.parameters(), lr=0.005)
pitón
El siguiente paso es completar un paso adelante en la red neural usando los datos de entrada. Tendremos cinco pases completos sobre los datos.
La función net.zero_grad() establece los gradientes a cero antes del cálculo de la pérdida. La función net(X.view(-1,784)) pasa en el lote remodelado. El número 784 es el resultado de las dimensiones de la imagen de 28 por 28.
La función loss_criterion(output, y) calcula el valor de la pérdida. Los siguientes pasos implican el cálculo de los gradientes de los pesos usando la propagación trasera, y luego el cambio de los pesos usando el optimizador adam. La última línea del código imprime la pérdida para las cinco pasadas.
123456789para la época en rango(5):para los datos en el tren: X, y = datos netos.cero_grad() salida = neta(X.view(-1,784)) pérdida = criterio_pérdida(salida, y) pérdida.retroceso() optimizador.paso()impresión(pérdida)
pitón
Salida:
12345 tensor(0.1360, grad_fn=<NllLossBackward>) tensor(0.1455, grad_fn=<NllLossBackward>) tensor(0. 1776, grad_fn=<NllLossBackward>) tensor(0.2263, grad_fn=<NllLossBackward>) tensor(0.0365, grad_fn=<NllLossBackward>)