Què són les Xarxes Neuronals Recurrents (RNNs)?

Les Xarxes Neuronals Recurrents (RNNs) són un tipus de xarxa neuronal especialment dissenyada per treballar amb dades seqüencials. A diferència de les xarxes neuronals tradicionals, les RNNs tenen connexions recurrents que permeten que la informació persisteixi. Això les fa ideals per a tasques on l'ordre de les dades és important, com ara el processament del llenguatge natural (NLP), la predicció de sèries temporals i el reconeixement de veu.

Característiques Clau de les RNNs:

  • Memòria: Les RNNs poden recordar informació de passos anteriors en la seqüència, cosa que les fa adequades per a dades seqüencials.
  • Pesos Compartits: Els mateixos pesos i biaixos s'apliquen a cada element de la seqüència, reduint la complexitat del model.
  • Capacitat de Processar Seqüències de Longitud Variable: Les RNNs poden manejar seqüències de diferents longituds, cosa que és útil per a moltes aplicacions reals.

Arquitectura Bàsica d'una RNN

Una RNN típica consisteix en una capa recurrent que processa una seqüència d'entrades. Cada unitat recurrent pren una entrada de la seqüència i l'estat ocult de l'últim pas de temps per produir una sortida i un nou estat ocult.

Fórmules Clau:

  • Estat Ocult: \( h_t = \sigma(W_{hx} x_t + W_{hh} h_{t-1} + b_h) \)
  • Sortida: \( y_t = W_{hy} h_t + b_y \)

On:

  • \( x_t \) és l'entrada en el pas de temps \( t \).
  • \( h_t \) és l'estat ocult en el pas de temps \( t \).
  • \( W_{hx} \), \( W_{hh} \), i \( W_{hy} \) són matrius de pesos.
  • \( b_h \) i \( b_y \) són biaixos.
  • \( \sigma \) és una funció d'activació, com ara tanh o ReLU.

Implementació Bàsica d'una RNN amb PyTorch

A continuació, es mostra un exemple bàsic d'implementació d'una RNN utilitzant PyTorch.

Exemple de Codi:

import torch
import torch.nn as nn

class SimpleRNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleRNN, self).__init__()
        self.hidden_size = hidden_size
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    
    def forward(self, x):
        h0 = torch.zeros(1, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.rnn(x, h0)
        out = self.fc(out[:, -1, :])
        return out

# Paràmetres del model
input_size = 10
hidden_size = 20
output_size = 1

# Creació del model
model = SimpleRNN(input_size, hidden_size, output_size)

# Mostra del model
print(model)

Explicació del Codi:

  1. Definició de la Classe: Definim una classe SimpleRNN que hereta de nn.Module.
  2. Inicialització: En el mètode __init__, inicialitzem la capa RNN i una capa lineal per a la sortida.
  3. Forward Pass: En el mètode forward, inicialitzem l'estat ocult h0 amb zeros, passem l'entrada a través de la capa RNN i després a través de la capa lineal per obtenir la sortida final.

Exercici Pràctic

Exercici:

Implementa una RNN per predir la següent paraula en una seqüència de text. Utilitza un conjunt de dades de text senzill i entrena la RNN per predir la següent paraula donada una seqüència de paraules.

Solució:

import torch
import torch.nn as nn
import torch.optim as optim
from torchtext.legacy.data import Field, TabularDataset, BucketIterator

# Definició del camp de text
TEXT = Field(tokenize='spacy', lower=True)

# Creació del conjunt de dades
datafields = [("text", TEXT)]
train_data, valid_data = TabularDataset.splits(
    path=".", train="train.csv", validation="valid.csv", format="csv", fields=datafields
)

# Construcció del vocabulari
TEXT.build_vocab(train_data, min_freq=2)

# Creació dels iteradors
train_iterator, valid_iterator = BucketIterator.splits(
    (train_data, valid_data), batch_size=32, device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
)

class TextRNN(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim):
        super(TextRNN, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.rnn = nn.RNN(embedding_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, output_dim)
    
    def forward(self, x):
        embedded = self.embedding(x)
        h0 = torch.zeros(1, x.size(0), self.hidden_dim).to(x.device)
        out, _ = self.rnn(embedded, h0)
        out = self.fc(out[:, -1, :])
        return out

# Paràmetres del model
vocab_size = len(TEXT.vocab)
embedding_dim = 100
hidden_dim = 256
output_dim = vocab_size

# Creació del model
model = TextRNN(vocab_size, embedding_dim, hidden_dim, output_dim)

# Definició de la pèrdua i l'optimitzador
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters())

# Entrenament del model
for epoch in range(10):
    model.train()
    for batch in train_iterator:
        optimizer.zero_grad()
        predictions = model(batch.text)
        loss = criterion(predictions, batch.text[:, 1:].contiguous().view(-1))
        loss.backward()
        optimizer.step()
    print(f'Epoch {epoch+1}, Loss: {loss.item()}')

print("Entrenament completat!")

Explicació del Codi:

  1. Preparació del Conjunt de Dades: Utilitzem torchtext per carregar i processar el conjunt de dades de text.
  2. Definició del Model: Definim una classe TextRNN que inclou una capa d'embeddings, una capa RNN i una capa lineal.
  3. Entrenament: Entrenem el model utilitzant l'optimitzador Adam i la pèrdua de cross-entropy.

Conclusió

En aquesta secció, hem introduït les Xarxes Neuronals Recurrents (RNNs) i hem vist com implementar una RNN bàsica amb PyTorch. Les RNNs són molt potents per a tasques que impliquen dades seqüencials, i la seva capacitat de recordar informació passada les fa ideals per a aplicacions com el processament del llenguatge natural i la predicció de sèries temporals. En la següent secció, explorarem com construir una RNN des de zero amb més detall.

© Copyright 2024. Tots els drets reservats