9.4 KiB
Executable File
9.4 KiB
Executable File
In [1]:
# Corpus simple
corpus = [
"el gato come pescado",
"el perro come hueso",
"el gato juega con el perro",
"el pez nada en el agua",
"el perro corre rápido"
]
def tokenize_corpus(corpus):
tokens = []
for sentence in corpus:
tokens.extend(sentence.lower().split())
return tokens
tokens = tokenize_corpus(corpus)
print("Tokens:", tokens)Tokens: ['el', 'gato', 'come', 'pescado', 'el', 'perro', 'come', 'hueso', 'el', 'gato', 'juega', 'con', 'el', 'perro', 'el', 'pez', 'nada', 'en', 'el', 'agua', 'el', 'perro', 'corre', 'rápido']
In [2]:
vocab = sorted(set(tokens))
word_to_idx = {word: i for i, word in enumerate(vocab)}
idx_to_word = {i: word for word, i in word_to_idx.items()}
print("Vocabulario:", vocab)Vocabulario: ['agua', 'come', 'con', 'corre', 'el', 'en', 'gato', 'hueso', 'juega', 'nada', 'perro', 'pescado', 'pez', 'rápido']
In [3]:
def create_sequences(tokens, seq_length):
inputs = []
targets = []
for i in range(len(tokens) - seq_length):
seq_in = tokens[i:i+seq_length]
seq_out = tokens[i+seq_length]
inputs.append([word_to_idx[w] for w in seq_in])
targets.append(word_to_idx[seq_out])
return inputs, targets
seq_length = 3
inputs, targets = create_sequences(tokens, seq_length)
print("Ejemplo de entrada (índices):", inputs[0])
print("Ejemplo de objetivo (índice):", targets[0])Ejemplo de entrada (índices): [4, 6, 1] Ejemplo de objetivo (índice): 11
In [4]:
import torch
import torch.nn as nn
class LSTMWordPredictor(nn.Module):
def __init__(self, vocab_size, embedding_dim, hidden_dim):
super(LSTMWordPredictor, self).__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.lstm = nn.LSTM(embedding_dim, hidden_dim, batch_first=True)
self.linear = nn.Linear(hidden_dim, vocab_size)
def forward(self, x):
embeds = self.embedding(x) # x shape: (batch, seq_length)
lstm_out, _ = self.lstm(embeds) # lstm_out shape: (batch, seq_length, hidden_dim)
# COMPLETAR: Tomar la salida del último timestep
last_out = lstm_out[:, -1, :] # COMPLETAR
out = self.linear(last_out) # out shape: (batch, vocab_size)
return out
embedding_dim = 10
hidden_dim = 20
vocab_size = len(vocab)
model = LSTMWordPredictor(vocab_size, embedding_dim, hidden_dim)
print(model)LSTMWordPredictor( (embedding): Embedding(14, 10) (lstm): LSTM(10, 20, batch_first=True) (linear): Linear(in_features=20, out_features=14, bias=True) )
In [5]:
import torch.optim as optim
def train(model, inputs, targets, epochs=100, lr=0.01):
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=lr)
for epoch in range(epochs):
total_loss = 0
for i in range(len(inputs)):
input_seq = torch.tensor([inputs[i]], dtype=torch.long) # batch_size=1
target = torch.tensor([targets[i]], dtype=torch.long)
model.zero_grad()
output = model(input_seq)
loss = loss_function(output, target)
loss.backward()
optimizer.step()
total_loss += loss.item()
if (epoch+1) % 20 == 0:
print(f"Epoch {epoch+1}, Loss: {total_loss/len(inputs):.4f}")
train(model, inputs, targets)Epoch 20, Loss: 0.0294 Epoch 40, Loss: 0.0075 Epoch 60, Loss: 0.0035 Epoch 80, Loss: 0.0020 Epoch 100, Loss: 0.0013
In [6]:
def predict_next_word(model, input_words, word_to_idx, idx_to_word):
model.eval()
with torch.no_grad():
input_idx = torch.tensor([[word_to_idx[w] for w in input_words]], dtype=torch.long)
output = model(input_idx)
predicted_idx = output.argmax(dim=1).item()
return idx_to_word[predicted_idx]
# Prueba
input_seq = ["el", "gato", "come"]
print(f"Dada la secuencia {input_seq}, la siguiente palabra predicha es: {predict_next_word(model, input_seq, word_to_idx, idx_to_word)}")Dada la secuencia ['el', 'gato', 'come'], la siguiente palabra predicha es: pescado