pytorch / obsolete /shakespeare.py
eaglelandsonce's picture
Create obsolete/shakespeare.py
9beed27 verified
raw
history blame
5.29 kB
import streamlit as st
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# Define the RNN or LSTM Model
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(LSTMModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x, h):
out, h = self.lstm(x, h)
out = self.fc(out[:, -1, :])
return out, h
# Text generation function
def generate_text(model, start_str, length, char_to_int, int_to_char, num_layers, hidden_size):
model.eval()
input_seq = [char_to_int[c] for c in start_str]
input_seq = torch.tensor(input_seq, dtype=torch.float32).unsqueeze(0).unsqueeze(-1)
h = (torch.zeros(num_layers, 1, hidden_size), torch.zeros(num_layers, 1, hidden_size))
generated_text = start_str
for _ in range(length):
output, h = model(input_seq, h)
_, predicted = torch.max(output, 1)
predicted_char = int_to_char[predicted.item()]
generated_text += predicted_char
input_seq = torch.tensor([char_to_int[predicted_char]], dtype=torch.float32).unsqueeze(0).unsqueeze(-1)
return generated_text
# Streamlit interface
st.title("RNN/LSTM Text Generation")
# Inputs
text_data = st.text_area("Enter your text data for training:", "To be, or not to be, that is the question:\nWhether 'tis nobler in the mind to suffer\nThe slings and arrows of outrageous fortune,\nOr to take arms against a sea of troubles\nAnd by opposing end them. To die: to sleep;\nNo more; and by a sleep to say we end\nThe heart-ache and the thousand natural shocks\nThat flesh is heir to, 'tis a consummation\nDevoutly to be wish'd. To die, to sleep;\nTo sleep: perchance to dream: ay, there's the rub;\nFor in that sleep of death what dreams may come\nWhen we have shuffled off this mortal coil,\nMust give us pause: there's the respect\nThat makes calamity of so long life;")
start_string = st.text_input("Enter the start string for text generation:")
seq_length = st.number_input("Sequence length:", min_value=10, value=100)
hidden_size = st.number_input("Hidden size:", min_value=50, value=256)
num_layers = st.number_input("Number of layers:", min_value=1, value=2)
learning_rate = st.number_input("Learning rate:", min_value=0.0001, value=0.003, format="%.4f")
num_epochs = st.number_input("Number of epochs:", min_value=1, value=20)
generate_length = st.number_input("Generated text length:", min_value=50, value=500)
if st.button("Train and Generate"):
# Data Preparation
text = text_data
if len(text) <= seq_length:
st.error("Text data is too short for the given sequence length. Please enter more text data.")
else:
chars = sorted(list(set(text)))
char_to_int = {c: i for i, c in enumerate(chars)}
int_to_char = {i: c for i, c in enumerate(chars)}
# Prepare input-output pairs
dataX = []
dataY = []
for i in range(0, len(text) - seq_length):
seq_in = text[i:i + seq_length]
seq_out = text[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
if len(dataX) == 0:
st.error("Not enough data to create input-output pairs. Please provide more text data.")
else:
X = np.reshape(dataX, (len(dataX), seq_length, 1))
X = X / float(len(chars))
Y = np.array(dataY)
# Convert to PyTorch tensors
X_tensor = torch.tensor(X, dtype=torch.float32)
Y_tensor = torch.tensor(Y, dtype=torch.long)
# Model initialization
model = LSTMModel(input_size=1, hidden_size=hidden_size, output_size=len(chars), num_layers=num_layers)
# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# Training the model
for epoch in range(num_epochs):
h = (torch.zeros(num_layers, 1, hidden_size), torch.zeros(num_layers, 1, hidden_size))
epoch_loss = 0
for i in range(len(dataX)):
inputs = X_tensor[i].unsqueeze(0) # Shape: (1, seq_length, 1)
targets = Y_tensor[i].unsqueeze(0) # Shape: (1,)
# Forward pass
outputs, h = model(inputs, (h[0].detach(), h[1].detach()))
loss = criterion(outputs, targets)
# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch_loss += loss.item()
avg_loss = epoch_loss / len(dataX)
st.write(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {avg_loss:.4f}')
# Text generation
generated_text = generate_text(model, start_string, generate_length, char_to_int, int_to_char, num_layers, hidden_size)
st.subheader("Generated Text")
st.write(generated_text)