Technical Documentation

Comprehensive technical guide for developers and researchers

Getting Started

Prerequisites

Before setting up the project, ensure you have the following installed:

# Python 3.8 or higher
python --version

# CUDA-capable GPU (recommended)
nvidia-smi

# Git for cloning the repository
git --version

Installation

# Clone the repository
git clone https://github.com/patelchaitany/Guj_eng.git
cd Guj_eng

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install transformers datasets sentencepiece pillow wandb tqdm matplotlib seaborn

Project Structure

Guj_eng/
├── train.py                 # Main training script
├── validate.py              # Validation script
├── README.md               # Project documentation
├── model/                  # Model implementations
│   ├── transformer.py      # Main Transformer model
│   ├── config.py          # Configuration dataclass
│   ├── encoder.py         # Text encoder
│   ├── decoder.py         # Text decoder
│   ├── visionenc.py       # Vision encoder wrapper
│   └── STN.py             # Spatial Transformer Network
├── dataset/               # Dataset handling
│   ├── dataset.py         # Text translation dataset
│   ├── dataset_image.py   # Image translation datasets
│   ├── ocr_dataset.py     # OCR dataset
│   └── prepare_image.py   # Image preprocessing
├── tokenizer/             # Tokenization
│   └── tokenizer.py       # SentencePiece wrapper
└── learning/              # Learning utilities
    ├── utils.py           # Training utilities
    └── tokenizer.py       # Tokenizer training

Model Architecture

Core Components

The model consists of three main components working together:

1. Vision Encoder (CLIP)

from transformers import CLIPVisionModel

class VisionEncoder(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.clip_model = CLIPVisionModel.from_pretrained("openai/clip-vit-base-patch32")
        self.projection = nn.Linear(768, config.comman_embedding_dim)
        
    def forward(self, images):
        # Extract visual features
        vision_outputs = self.clip_model(pixel_values=images)
        image_features = vision_outputs.last_hidden_state
        
        # Project to common embedding space
        projected_features = self.projection(image_features)
        return projected_features

2. Text Encoder

class TextEncoder(nn.Module):
                    def __init__(self, config):
                        super().__init__()
                        self.embedding = nn.Embedding(config.vocab_size, config.comman_embedding_dim)
                        self.transformer_layers = nn.ModuleList([
                            EncoderBlock(config) for _ in range(config.num_encoder_layers)
                        ])
                        self.layer_norm = nn.LayerNorm(config.num_embeddings_encoder)
                        
                    def forward(self, input_ids):
                        # Token embeddings
                        embeddings = self.embedding(input_ids)
                        
                        # Apply transformer layers
                        hidden_states = embeddings
                        for layer in self.transformer_layers:
                            hidden_states = layer(hidden_states)
                            
                        return self.layer_norm(hidden_states)

3. Cross-Attention Decoder

class CrossAttentionDecoder(nn.Module):
                    def __init__(self, config):
                        super().__init__()
                        self.layers = nn.ModuleList([
                            DecoderBlock(config) if i % 2 == 0 else Decoder_Cross(config) 
                            for i in range(config.num_decoder_layers * 2)
                        ])
                        
                    def forward(self, target_ids, encoder_outputs, encoder_mask=None):
                        hidden_states = self.embedding(target_ids)
                        
                        for i, layer in enumerate(self.layers):
                            if i % 2 == 0:  # Self-attention layer
                                hidden_states = layer(hidden_states)
                            else:  # Cross-attention layer
                                hidden_states = layer(hidden_states, encoder_outputs, encoder_mask)
                                
                        return hidden_states

Dataset Preparation

Data Format

The project expects data in specific formats for different tasks:

Text Translation Data

{
  "src": "Hello, how are you?",
  "tgt": "હેલો, તમે કેમ છો?",
  "src_lang": "en",
  "tgt_lang": "gu"
}

Image Translation Data

# Image dataset structure
data/
├── images/
│   ├── img_001.jpg
│   ├── img_002.jpg
│   └── ...
└── annotations/
    ├── train.tsv
    └── val.tsv

# TSV format: image_path \t gujarati_text \t english_text
img_001.jpg	આ એક ઉદાહરણ છે	This is an example

Data Preprocessing

import torchvision.transforms as transforms
from PIL import Image

# Image preprocessing pipeline
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.48145466, 0.4578275, 0.40821073],
        std=[0.26862954, 0.26130258, 0.27577711]
    )  # CLIP normalization
])

# Text preprocessing
def preprocess_text(text, tokenizer, max_length=512):
    tokens = tokenizer.encode(text)
    if len(tokens) > max_length:
        tokens = tokens[:max_length]
    return tokens

Training Process

Multi-Task Training

The model is trained on three tasks simultaneously:

# Training configuration
config = {
    'mt_lambda': 0.5,    # Machine Translation weight
    'tit_lambda': 1.2,   # Text Image Translation weight  
    'ocr_lambda': 0.5,   # OCR weight
    'batch_size': 128,
    'learning_rate': 6e-4,
    'warmup_steps': 1000,
    'max_steps': 10000
}

# Training loop
for step in range(max_steps):
    # Machine Translation Task
    mt_loss = train_mt_batch(model, mt_dataloader, criterion)
    
    # Text Image Translation Task
    tit_loss = train_tit_batch(model, tit_dataloader, criterion)
    
    # OCR Task
    ocr_loss = train_ocr_batch(model, ocr_dataloader, criterion)
    
    # Combined loss
    total_loss = (config['mt_lambda'] * mt_loss + 
                  config['tit_lambda'] * tit_loss + 
                  config['ocr_lambda'] * ocr_loss)
    
    # Backpropagation
    optimizer.zero_grad()
    total_loss.backward()
    optimizer.step()

Learning Rate Scheduling

def get_lr(step, warmup_steps=1000, max_steps=10000, max_lr=6e-4, min_lr=6e-5):
    if step <= warmup_steps:
        # Linear warmup
        return max_lr * (step / warmup_steps)
    elif step > max_steps:
        return min_lr
    else:
        # Cosine annealing
        decay_ratio = (step - warmup_steps) / (max_steps - warmup_steps)
        return min_lr + 0.5 * (max_lr - min_lr) * (1 + math.cos(math.pi * decay_ratio))

Usage Examples

Training a Model

# Basic training
python train.py

# Training with custom config
python train.py --batch_size 64 --learning_rate 3e-4 --max_steps 5000

# Resume from checkpoint
python train.py --resume_from checkpoints/transformer_epoch_100.pt

Inference

import torch
from PIL import Image
from model.transformer import Transformer
from model.config import Config
from tokenizer.tokenizer import Tokenizer

# Load model and tokenizer
config = Config(vocab_size=32000)
model = Transformer(config)
model.load_state_dict(torch.load('checkpoints/best_model.pt'))
model.eval()

tokenizer = Tokenizer(["<en|gu>", "<gu|en>", "<en>", "<gu>"])
tokenizer.load('data/tokenizer.model')

# Translate image
def translate_image(image_path, source_lang='gu', target_lang='en'):
    # Load and preprocess image
    image = Image.open(image_path).convert('RGB')
    image = transform(image).unsqueeze(0)
    
    # Prepare decoder input
    lang_token = tokenizer.get_token_id(f"<{target_lang}>")
    bos_token = tokenizer.get_token_id("bos")
    decoder_input = torch.tensor([[lang_token, bos_token]])
    
    # Generate translation
    with torch.no_grad():
        for _ in range(50):  # max length
            output = model(decoder_input, image, is_image=True)
            next_token = output[:, -1, :].argmax(dim=-1)
            
            if next_token == tokenizer.get_token_id("eos"):
                break
                
            decoder_input = torch.cat([decoder_input, next_token.unsqueeze(0)], dim=1)
    
    # Decode result
    generated_ids = decoder_input[0, 2:].tolist()
    translation = tokenizer.decode(generated_ids)
    return translation

# Example usage
result = translate_image('path/to/gujarati_image.jpg')
print(f"Translation: {result}")

Evaluation

Validation Script

# Run validation
python validate.py --model_path checkpoints/best_model.pt --data_path data/validation/

# Compute BLEU scores
python validate.py --model_path checkpoints/best_model.pt --metric bleu

# Generate sample translations
python validate.py --model_path checkpoints/best_model.pt --sample_size 100

Metrics

The model is evaluated using standard translation metrics:

  • BLEU Score: Measures n-gram overlap between prediction and reference
  • METEOR: Considers synonyms and paraphrases
  • ChrF: Character-level F-score, good for morphologically rich languages
  • BERTScore: Semantic similarity using contextual embeddings

Configuration

Model Configuration

@dataclass
class Config:
    vocab_size: int                    # Vocabulary size
    d_model: int = 768                # Model dimension
    nhead: int = 8                    # Number of attention heads
    num_encoder_layers: int = 6       # Encoder layers
    num_decoder_layers: int = 6       # Decoder layers
    dim_feedforward: int = 768        # FFN dimension
    dropout: float = 0.1              # Dropout rate
    max_len: int = 1024              # Maximum sequence length
    num_embeddings_decoder: int = 768 # Decoder embedding dim
    num_embeddings_encoder: int = 768 # Encoder embedding dim
    comman_embedding_dim: int = 512   # Common embedding dim
    control_points: int = 20          # STN control points

Training Configuration

# Hyperparameters
BATCH_SIZE = 128
LEARNING_RATE = 6e-4
WARMUP_STEPS = 1000
MAX_STEPS = 10000
GRADIENT_ACCUMULATION = 32

# Task weights
MT_LAMBDA = 0.5      # Machine Translation
TIT_LAMBDA = 1.2     # Text Image Translation
OCR_LAMBDA = 0.5     # Optical Character Recognition

# Optimization
OPTIMIZER = 'AdamW'
BETAS = (0.9, 0.95)
EPS = 1e-8
WEIGHT_DECAY = 0.01