Esta entrada es parte del curso de Deep learning con PyTorch.
El paquete torch.nn de PyTorch contiene multitud de clases que nos permiten crear de una manera intuitiva redes neuronales y a la vez tener un nivel de detalle y control de los componentes de las mismas.
Una de las clases más importantes de torch.nn es torch.nn.Module ya que es muy útil que los modelos que definamos hereden esta clase. Para ello es necesario definir el constructor del modelo en init() instanciando los componentes que deseemos y sobreescribir el método forward, que realiza las operaciones forward del modelo y calcula la salida. Con super.init() inicializamos la superclase nn.Module. El método forward se ejecuta directamente al llamar al modelo gracias al método call.
En el siguiente ejemplo creamos un modelo basándonos en la clase nn.Module, instanciamos los componentes del modelo usando las clases del paquete torch.nn nn.Linear para la capa lineal y nn.Relu para la función de activacíon ReLU y definimos el flujo de las operaciones en el método forward. In [0]:
import torch import torch.nn as nn 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
In [3]:
#Creamos una instancia del modelo modelo1=Net(100,200,10) #Calculamos la salida con una entrada ejemplo x=torch.rand(100) output=modelo1(x) print(output)
tensor([-0.1491, -0.1181, 0.0409, 0.1655, -0.0919, 0.0808, -0.1437, 0.0978, 0.3534, -0.0696], grad_fn=<AddBackward0>)
Debido a que el modelo extiende la clase base nn.Module, es posible usar la gran cantidad de métodos y atributos de esta clase. In [4]:
#Vemos la estructura del modelo print(modelo1)
Net( (fc1): Linear(in_features=100, out_features=200, bias=True) (relu): ReLU() (fc2): Linear(in_features=200, out_features=10, bias=True) )
In [6]:
#Movemos todos los parámetros del modelo a la GPU modelo1.cuda()
Out[6]:
Net( (fc1): Linear(in_features=100, out_features=200, bias=True) (relu): ReLU() (fc2): Linear(in_features=200, out_features=10, bias=True) )
In [8]:
#El método named_parameters() devuelve un iterador a los parámetros del modelo, mostrando el nombre del parámetro y el parámetro. for name, param in modelo1.named_parameters(): if param.requires_grad: if name in ['fc2.weight']: print (name, param.data)
fc2.weight tensor([[-0.0143, 0.0591, -0.0423, ..., -0.0119, -0.0161, -0.0214], [-0.0036, -0.0298, -0.0684, ..., -0.0279, 0.0139, -0.0181], [ 0.0083, 0.0487, 0.0115, ..., 0.0361, -0.0298, -0.0320], ..., [ 0.0614, 0.0489, -0.0314, ..., 0.0177, -0.0035, 0.0170], [-0.0631, 0.0340, 0.0433, ..., -0.0262, -0.0472, -0.0106], [-0.0349, -0.0609, 0.0234, ..., 0.0660, 0.0404, 0.0082]], device='cuda:0')
In [16]:
#El método apply(fn) aplica la función fn recursivamente en cada submódulo del modelo. #Vamos a crear una función que inicializa los parámetros de las capas lineales y aplicarlo al modelo. def init_w(m): if type(m) == nn.Linear: m.weight.data.fill_(1.0) modelo1.apply(init_w) #Vemos los parámetros de la segunda capa lineal después de aplicarles la función de inicialización. for name, param in modelo1.named_parameters(): if param.requires_grad: if name in ['fc2.weight']: print (name, param.data)
fc2.weight tensor([[1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], ..., [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.]], device='cuda:0')
In [22]:
#El módulo torch.nn también nos ofrece gran variedad de clases que definen las principales arquitecturas de deep learning. #Un ejemplo es torch.nn.LSTM() que se inicializa con los parámetros (input_size, hidden_size, num_layers). # Tiene como entrada (input,h_0,c_0) donde la forma de la entrada es (seq_len, batch, input_size). # La forma de los estados iniciales h_0 y c_0 es (num_layers * num_directions, batch, hidden_size) LSTM1 = nn.LSTM(10, 6, 2) input = torch.randn(5, 2, 10) h0 = torch.randn(2, 2, 6) c0 = torch.randn(2, 2, 6) output, (hn, cn) = LSTM1(input, (h0, c0)) #La salida output tiene la forma (seq_len, batch, num_directions * hidden_size) y contiene la salida h_t para todos los intantes de tiempo. print(output) #La salida hn tiene la forma (num_layers * num_directions, batch, hidden_size) y contiene h_t para el último intantes de tiempo en cada capa. print(hn)
tensor([[[-0.2011, 0.1655, -0.2477, 0.1799, 0.1487, 0.0927], [ 0.0904, 0.1733, 0.1654, -0.4293, 0.1613, 0.2302]], [[-0.1106, -0.0119, -0.2052, 0.1075, 0.0456, -0.0091], [ 0.0440, 0.1401, -0.0561, -0.3597, -0.0532, 0.0714]], [[-0.0146, -0.0703, -0.1875, -0.0116, -0.0348, -0.0276], [ 0.0055, 0.0685, -0.1641, -0.2310, -0.0926, 0.0364]], [[ 0.0490, -0.0809, -0.2023, -0.0706, -0.0991, -0.0177], [ 0.0049, -0.0237, -0.1936, -0.1757, -0.1100, -0.0086]], [[ 0.0987, -0.0947, -0.2116, -0.1135, -0.1484, -0.0041], [ 0.0066, -0.0227, -0.1991, -0.1505, -0.1113, -0.0345]]], grad_fn=<StackBackward>) tensor([[[ 0.0825, -0.0972, -0.0253, -0.3673, -0.1815, -0.2375], [-0.3572, -0.1458, -0.0946, -0.3145, -0.0119, 0.2615]], [[ 0.0987, -0.0947, -0.2116, -0.1135, -0.1484, -0.0041], [ 0.0066, -0.0227, -0.1991, -0.1505, -0.1113, -0.0345]]], grad_fn=<StackBackward>)
Deja una respuesta