CoolFace
Datasetpublic

ysn-rfd/text-dataset-tiny-code-script-py-format

USED of tahamajs/medicine_ds_persian for .parquet file USED of Alijafarixcs2/persian-it-llama2-2k for .parquet file USED of Abirate/english_quotes for .jsonl file NEW FILES (05/12/2025) NEW FILES (12/26/2025) NEW FILES (02/15/2026)

sourceHugging Faceapache-2.0updated 4mo agoView on Hugging Face
3likes1.6kdownloads
1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4from torch.utils.data import Dataset, DataLoader, random_split
5from torch.cuda.amp import autocast, GradScaler
6from torch.utils.tensorboard import SummaryWriter
7import numpy as np
8from tqdm import tqdm
9import json
10import argparse
11from datetime import datetime
12
13# Configuration with Transformer-specific parameters
14CONFIG = {
15    "FILE_PATH": 'dataset.txt',
16    "SEQ_LENGTH": 32,
17    "BATCH_SIZE": 8,
18    "EPOCHS": 1,
19    "EMBEDDING_DIM": 64,
20    "N_HEADS": 1,
21    "FFN_DIM": 64,
22    "NUM_LAYERS": 3,
23    "DROPOUT": 0.1,
24    "LEARNING_RATE": 0.0005,
25    "WEIGHT_DECAY": 0.01,
26    "CLIP_GRAD": 1.0,
27    "LABEL_SMOOTHING": 0.1,
28    "GRAD_ACCUM_STEPS": 2,
29    "VAL_SPLIT": 0.1,
30    "EARLY_STOP_PATIENCE": 3,
31    "MODEL_SAVE_PATH": "transformer_lm_model.pth",
32    "TEMPERATURE": 0.7,
33    "TOP_K": 50,
34    "TOP_P": 0.9,
35    "LOG_DIR": "runs"
36}
37
38# Device configuration
39device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
40scaler = GradScaler(enabled=device.type == 'cuda')
41
42# Handle command-line arguments
43parser = argparse.ArgumentParser()
44parser.add_argument('--config', type=str, help='Path to config JSON file')
45args = parser.parse_args()
46
47if args.config:
48    with open(args.config) as f:
49        CONFIG.update(json.load(f))
50
51# Initialize TensorBoard
52writer = SummaryWriter(f"{CONFIG['LOG_DIR']}/{datetime.now().strftime('%Y%m%d-%H%M%S')}")
53
54# Read and process text
55with open(CONFIG["FILE_PATH"], 'r', encoding='utf-8') as f:
56    text = f.read()
57
58# Vocabulary setup
59chars = sorted(list(set(text)))
60vocab_size = len(chars)
61char_to_idx = {ch: i for i, ch in enumerate(chars)}
62idx_to_char = {i: ch for i, ch in enumerate(chars)}
63
64# Encode text
65encoded_text = np.array([char_to_idx[ch] for ch in text])
66
67# Dataset class with memory mapping
68class TextDataset(Dataset):
69    def __init__(self, data, seq_length):
70        self.data = torch.from_numpy(data).long()
71        self.seq_length = seq_length
72        
73    def __len__(self):
74        return len(self.data) - self.seq_length - 1
75    
76    def __getitem__(self, idx):
77        x = self.data[idx:idx+self.seq_length]
78        y = self.data[idx+1:idx+self.seq_length+1]
79        return x, y
80
81dataset = TextDataset(encoded_text, CONFIG["SEQ_LENGTH"])
82val_size = int(len(dataset) * CONFIG["VAL_SPLIT"])
83train_size = len(dataset) - val_size
84train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
85
86train_loader = DataLoader(train_dataset, batch_size=CONFIG["BATCH_SIZE"], 
87                         shuffle=True, pin_memory=True, num_workers=4)
88val_loader = DataLoader(val_dataset, batch_size=CONFIG["BATCH_SIZE"], 
89                       pin_memory=True, num_workers=4)
90
91# Transformer-based Language Model
92class TransformerLM(nn.Module):
93    def __init__(self):
94        super().__init__()
95        self.embedding = nn.Embedding(vocab_size, CONFIG["EMBEDDING_DIM"])
96        self.pos_embed = nn.Embedding(CONFIG["SEQ_LENGTH"], CONFIG["EMBEDDING_DIM"])
97        
98        self.transformer = nn.TransformerEncoder(
99            nn.TransformerEncoderLayer(
100                d_model=CONFIG["EMBEDDING_DIM"],
101                nhead=CONFIG["N_HEADS"],
102                dim_feedforward=CONFIG["FFN_DIM"],
103                dropout=CONFIG["DROPOUT"],
104                activation='gelu',
105                batch_first=True
106            ),
107            num_layers=CONFIG["NUM_LAYERS"]
108        )
109        
110        self.ln = nn.LayerNorm(CONFIG["EMBEDDING_DIM"])
111        self.fc = nn.Linear(CONFIG["EMBEDDING_DIM"], vocab_size)
112        
113        self.apply(self._init_weights)
114        
115    def _init_weights(self, module):
116        if isinstance(module, nn.Linear):
117            nn.init.xavier_uniform_(module.weight)
118            if module.bias is not None:
119                nn.init.constant_(module.bias, 0)
120        elif isinstance(module, nn.Embedding):
121            nn.init.xavier_uniform_(module.weight)
122            
123    def forward(self, x, mask=None):
124        batch_size, seq_len = x.size()
125        positions = torch.arange(seq_len, device=device).expand(batch_size, seq_len)
126        x = self.embedding(x) + self.pos_embed(positions)
127        
128        if mask is None:
129            mask = nn.Transformer.generate_square_subsequent_mask(seq_len).to(device)
130            
131        x = self.transformer(x, mask)
132        x = self.ln(x)
133        return self.fc(x), None  # Return None for compatibility with generation code
134
135model = TransformerLM().to(device)
136optimizer = torch.optim.AdamW(model.parameters(), 
137                             lr=CONFIG["LEARNING_RATE"], 
138                             weight_decay=CONFIG["WEIGHT_DECAY"])
139scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
140    optimizer, mode='min', factor=0.5, patience=2)
141
142# Training loop with advanced features
143best_val_loss = float('inf')
144patience_counter = 0
145
146for epoch in range(CONFIG["EPOCHS"]):
147    model.train()
148    train_loss = 0
149    progress_bar = tqdm(train_loader, desc=f'Epoch {epoch+1}/{CONFIG["EPOCHS"]}')
150    
151    for i, (inputs, targets) in enumerate(progress_bar):
152        inputs, targets = inputs.to(device), targets.to(device)
153        
154        with autocast(enabled=device.type == 'cuda'):
155            outputs, _ = model(inputs)
156            logits = outputs.view(-1, vocab_size)
157            targets = targets.view(-1)
158            
159            if CONFIG["LABEL_SMOOTHING"]:
160                loss = F.cross_entropy(logits, targets, 
161                                      label_smoothing=CONFIG["LABEL_SMOOTHING"])
162            else:
163                loss = F.cross_entropy(logits, targets)
164            
165            loss = loss / CONFIG["GRAD_ACCUM_STEPS"]
166        
167        scaler.scale(loss).backward()
168        
169        if (i + 1) % CONFIG["GRAD_ACCUM_STEPS"] == 0:
170            scaler.unscale_(optimizer)
171            nn.utils.clip_grad_norm_(model.parameters(), CONFIG["CLIP_GRAD"])
172            scaler.step(optimizer)
173            scaler.update()
174            optimizer.zero_grad()
175            
176            lr = optimizer.param_groups[0]['lr']
177            progress_bar.set_postfix({'loss': loss.item() * CONFIG["GRAD_ACCUM_STEPS"], 'lr': lr})
178        
179        train_loss += loss.item() * CONFIG["GRAD_ACCUM_STEPS"]
180    
181    # Validation phase
182    model.eval()
183    val_loss = 0
184    with torch.no_grad():
185        for inputs, targets in val_loader:
186            inputs, targets = inputs.to(device), targets.to(device)
187            outputs, _ = model(inputs)
188            loss = F.cross_entropy(outputs.view(-1, vocab_size), targets.view(-1))
189            val_loss += loss.item()
190    
191    avg_train_loss = train_loss / len(train_loader)
192    avg_val_loss = val_loss / len(val_loader)
193    scheduler.step(avg_val_loss)
194    
195    # Log metrics
196    writer.add_scalar('Loss/train', avg_train_loss, epoch)
197    writer.add_scalar('Loss/val', avg_val_loss, epoch)
198    writer.add_scalar('Learning Rate', optimizer.param_groups[0]['lr'], epoch)
199    writer.add_scalar('Perplexity/train', np.exp(avg_train_loss), epoch)
200    writer.add_scalar('Perplexity/val', np.exp(avg_val_loss), epoch)
201    
202    print(f'Epoch {epoch+1} | Train Loss: {avg_train_loss:.4f} | Val Loss: {avg_val_loss:.4f}')
203    
204    # Early stopping and checkpointing
205    if avg_val_loss < best_val_loss:
206        best_val_loss = avg_val_loss
207        torch.save({
208            'epoch': epoch,
209            'model_state_dict': model.state_dict(),
210            'optimizer_state_dict': optimizer.state_dict(),
211            'scheduler_state_dict': scheduler.state_dict(),
212            'config': CONFIG
213        }, CONFIG["MODEL_SAVE_PATH"])
214        patience_counter = 0
215    else:
216        patience_counter += 1
217        if patience_counter >= CONFIG["EARLY_STOP_PATIENCE"]:
218            print("Early stopping triggered")
219            break
220
221writer.close()
222print(f'Best model saved to {CONFIG["MODEL_SAVE_PATH"]} with validation loss: {best_val_loss:.4f}')
223
224# Advanced generation with multiple sampling strategies
225def generate_text(model, start_str, length=200, temperature=CONFIG["TEMPERATURE"],
226                 top_k=CONFIG["TOP_K"], top_p=CONFIG["TOP_P"]):
227    model.eval()
228    chars = list(start_str)
229    input_seq = torch.tensor([char_to_idx[ch] for ch in chars], device=device).unsqueeze(0)
230    
231    with torch.no_grad():
232        for _ in tqdm(range(length), desc="Generating text"):
233            mask = nn.Transformer.generate_square_subsequent_mask(input_seq.size(1)).to(device)
234            outputs, _ = model(input_seq[:, -CONFIG["SEQ_LENGTH"]:], mask)
235            logits = outputs[:, -1] / temperature
236            
237            # Apply nucleus sampling first
238            if top_p > 0:
239                sorted_logits, sorted_indices = torch.sort(logits, descending=True)
240                cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
241                sorted_indices_to_remove = cumulative_probs > top_p
242                sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
243                sorted_indices_to_remove[..., 0] = 0
244                indices_to_remove = sorted_indices_to_remove.scatter(1, sorted_indices, sorted_indices_to_remove)
245                logits = logits.masked_fill(indices_to_remove, float('-inf'))
246            
247            # Then apply top-k filtering
248            if top_k > 0:
249                top_k = min(top_k, logits.size(-1))
250                indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None]
251                logits = logits.masked_fill(indices_to_remove, float('-inf'))
252            
253            probs = F.softmax(logits, dim=-1)
254            next_char = torch.multinomial(probs, num_samples=1)
255            chars.append(idx_to_char[next_char.item()])
256            input_seq = torch.cat([input_seq, next_char], dim=1)
257    
258    return ''.join(chars)
259
260# Generate examples with different parameters
261print("\nConservative sampling:")
262print(generate_text(model, "The ", temperature=0.5, top_p=0))
263
264print("\nCreative sampling:")
265print(generate_text(model, "Once ", temperature=1.2, top_p=0.9))
266
267print("\nTop-k sampling:")
268print(generate_text(model, "In ", top_k=50))
269
270print("\nCombined sampling:")
271print(generate_text(model, "Artificial intelligence ", temperature=0.8, top_k=50, top_p=0.9))