tiny-transformers / scripts /train_qna.py
zeguru's picture
Upload folder using huggingface_hub
1717c0c verified
Raw History Blame Contribute Delete
3.89 kB
from pathlib import Path
import torch
import json
from src.infra.dataset.util import split_tokens, get_batch
from src.infra.tokenizer import CharacterTokenizer
from src.infra.dataset.answering import QuestionAnsweringDataset
from torch.utils.data import random_split
from src.task.config import ModelConfig,TrainingConfig
from src.task.model import TinyAnsweringModel
from src.task.training.question_answering import train
from src.task.training.util import TrainingLogger, count_parameters, separator
logger = TrainingLogger(
"logs/question_answering.log"
)
checkpoint = "tiny_answering.pt"
# Configs
separator("Configuration")
torch.manual_seed(42)
# Configs
model_config = ModelConfig()
training_config = TrainingConfig()
# Overrides
model_config.context_length=512
training_config.num_steps = 300
training_config.eval_interval = 10
logger.log(model_config)
logger.log(training_config)
# Load the corpus
separator("Corpus")
torch.manual_seed(42)
SQUAD_PATH = Path("data/squad/dev-v1.1.json")
QA_TOKENIZER_PATH = Path("checkpoints/qa_tokenizer.json")
print(f"Squad file: {SQUAD_PATH}")
print(f"Tokenizer file: {QA_TOKENIZER_PATH}")
if not SQUAD_PATH.exists():
raise FileNotFoundError(f"Squad file not found: {SQUAD_PATH}")
if not QA_TOKENIZER_PATH.exists():
raise FileNotFoundError(f"Tokenizer file not found: {QA_TOKENIZER_PATH}")
tokenizer = CharacterTokenizer.load(QA_TOKENIZER_PATH)
vocab_size = tokenizer.vocab_size
with SQUAD_PATH.open("r", encoding="utf-8") as file:
squad = json.load(file)
# Tokens
records = []
article = next(
article
for article in squad["data"]
if article["title"] == "Kenya"
)
# for index, article in enumerate(squad["data"]): #when we need all the data
for paragraph in article["paragraphs"] :
context = paragraph["context"]
for qa in paragraph["qas"]:
for answer in qa["answers"]:
records.append(
{
"question": qa["question"],
"context": context,
"answer": answer["text"],
"answer_start": answer["answer_start"],
}
)
print(f"Number of records: {len(records)}")
print("\n=== Sample record ===")
question = records[0]["question"]
context = records[0]["context"]
answer_text = records[0]["answer"]
answer_start = records[0]["answer_start"]
answer_end = answer_start + len(answer_text)
print("Context:", context)
print("Question:", question)
print("Answer:", answer_text)
print("Answer Start:", answer_start)
print("Answer End:", answer_end)
separator("Dataset")
dataset = QuestionAnsweringDataset(
records=records,
tokenizer=tokenizer,
max_length=model_config.context_length, #to manage truncation and padding
)
n = len(dataset)
train_size = int(0.90 * n)
val_size = int(0.05 * n)
test_size = n - train_size - val_size
train_dataset, val_dataset, test_dataset = random_split(
dataset,
[train_size, val_size, test_size],
generator=torch.Generator().manual_seed(42),
)
logger.log(f"Train examples: {len(train_dataset):,}")
logger.log(f"Val examples: {len(val_dataset):,}")
logger.log(f"Test examples: {len(test_dataset):,}")
# Models
separator("Model")
model = TinyAnsweringModel(
config=model_config,
vocab_size=tokenizer.vocab_size,
)
logger.log(model)
# Train........
separator("Training")
model = train(
model=model,
train_dataset=train_dataset,
val_dataset=val_dataset,
training_config=training_config,
)
logger.log(f"Parameters: {count_parameters(model):,}")
separator("Saving")
checkpoint_dir = Path("checkpoints")
checkpoint_dir.mkdir(parents=True, exist_ok=True)
checkpoint_path = (
checkpoint_dir / checkpoint
)
torch.save(
model.state_dict(),
checkpoint_path,
)
print(f"Checkpoint saved to: {checkpoint_path}")