artha-ml / scripts /train.py
LikhinMN's picture
Upload folder using huggingface_hub
c617d00 verified
Raw
History Blame Contribute Delete
4.79 kB
import os
import time
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, random_split
import sys
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, project_root)
from arthaml.data.vocabulary import Vocabulary
from arthaml.data.dataset import TranslationDataset
from arthaml.models.encoder import Encoder
from arthaml.models.decoder import Attention, Decoder
from arthaml.models.seq2seq import Seq2Seq
from arthaml.evaluation.bleu import compute_bleu
def train(model, iterator, optimizer, criterion, clip, device):
model.train()
epoch_loss = 0
for i, batch in enumerate(iterator):
src = batch['src'].to(device)
tgt = batch['tgt'].to(device)
src_len = batch['src_len'].to(device)
optimizer.zero_grad()
output = model(src, src_len, tgt, teacher_forcing_ratio=0.5)
output_dim = output.shape[-1]
# Ignored t=0 since it's the <SOS> token
output = output[:, 1:].reshape(-1, output_dim)
tgt = tgt[:, 1:].reshape(-1)
loss = criterion(output, tgt)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), clip)
optimizer.step()
epoch_loss += loss.item()
return epoch_loss / len(iterator)
def evaluate(model, iterator, criterion, device):
model.eval()
epoch_loss = 0
with torch.no_grad():
for i, batch in enumerate(iterator):
src = batch['src'].to(device)
tgt = batch['tgt'].to(device)
src_len = batch['src_len'].to(device)
output = model(src, src_len, tgt, teacher_forcing_ratio=0)
output_dim = output.shape[-1]
output = output[:, 1:].reshape(-1, output_dim)
tgt = tgt[:, 1:].reshape(-1)
loss = criterion(output, tgt)
epoch_loss += loss.item()
return epoch_loss / len(iterator)
def main():
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"Using device: {device}")
os.makedirs(os.path.join(project_root, 'models'), exist_ok=True)
print("Loading vocabularies...")
vocab_en = Vocabulary("English")
vocab_en.load(os.path.join(project_root, 'data/processed/vocab_en.json'))
vocab_kn = Vocabulary("Kannada")
vocab_kn.load(os.path.join(project_root, 'data/processed/vocab_kn.json'))
print("Loading dataset...")
data_path = os.path.join(project_root, 'data/processed/clean_50k.json')
dataset = TranslationDataset(data_path, vocab_en, vocab_kn, max_len=50)
val_size = int(0.1 * len(dataset))
train_size = len(dataset) - val_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
train_iterator = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_iterator = DataLoader(val_dataset, batch_size=32, shuffle=False)
print("Initializing models...")
encoder = Encoder(vocab_size=21551, embed_dim=256, hidden_size=512, num_layers=2, dropout_p=0.3, padding_idx=0)
attention = Attention(hidden_size=512)
decoder = Decoder(attention, vocab_size=26802, embed_dim=256, hidden_size=512, num_layers=2, dropout_p=0.3, padding_idx=0)
model = Seq2Seq(encoder, decoder, device).to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss(ignore_index=0)
N_EPOCHS = 10
CLIP = 1.0
best_val_loss = float('inf')
best_bleu = 0.0
print("Starting training...")
for epoch in range(N_EPOCHS):
start_time = time.time()
train_loss = train(model, train_iterator, optimizer, criterion, CLIP, device)
val_loss = evaluate(model, val_iterator, criterion, device)
bleu_score = compute_bleu(model, val_dataset, vocab_kn, device, n=500)
end_time = time.time()
time_taken = int(end_time - start_time)
if val_loss < best_val_loss:
best_val_loss = val_loss
torch.save(model.state_dict(), os.path.join(project_root, 'models/best_model.pth'))
if bleu_score > best_bleu:
best_bleu = bleu_score
print(f"Epoch {epoch+1:02} | Train Loss: {train_loss:.3f} | Val Loss: {val_loss:.3f} | BLEU: {bleu_score:.2f} | Time: {time_taken}s")
torch.save(model.state_dict(), os.path.join(project_root, 'models/final_model.pth'))
print(f"\nTraining Complete!")
print(f"Best Val Loss: {best_val_loss:.3f}")
print(f"Best BLEU Score: {best_bleu:.2f}")
if __name__ == "__main__":
main()