Views
No views yet
./gemma3-finetuned.1pip install torch transformers datasets evaluate nltk psutil pynvml pandas tqdm scikit-learn
2
3
4
5# ==============================================================================
6# 1. Setup and Memory Optimization
7# This command must be run in the shell/environment *before* starting the script
8# for it to take effect, but it's included here for documentation.
9# If running this inside a Jupyter/Colab notebook, use: %env PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128
10# ==============================================================================
11# export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128
12
13# ==============================================================================
14# 2. Download Required NLTK Data
15# ==============================================================================
16import nltk
17try:
18 nltk.data.find('tokenizers/punkt')
19except nltk.downloader.DownloadError:
20 print("Downloading 'punkt' NLTK data...")
21 nltk.download('punkt')
22try:
23 nltk.data.find('corpora/wordnet')
24except nltk.downloader.DownloadError:
25 print("Downloading 'wordnet' NLTK data...")
26 nltk.download('wordnet')
27
28# ==============================================================================
29# 3. Model Loading (Requires model files in './gemma3-finetuned')
30# ==============================================================================
31from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments, DataCollatorForLanguageModeling
32import torch
33import psutil
34try:
35 import pynvml
36except ImportError:
37 print("Warning: pynvml not found. GPU metrics will be skipped. Install with: pip install pynvml")
38 pynvml = None
39
40# --- Configuration ---
41model_path = "./gemma3-finetuned"
42# --- End Configuration ---
43
44print(f"Loading model from {model_path}...")
45try:
46 tokenizer = AutoTokenizer.from_pretrained(model_path)
47 # Using device_map="auto" and torch_dtype="auto" for memory-efficient loading
48 model = AutoModelForCausalLM.from_pretrained(
49 model_path,
50 device_map="auto",
51 torch_dtype="auto"
52 )
53 print("Model loaded successfully.")
54except Exception as e:
55 print(f"Error loading model: {e}")
56 # Exit or mock model for demonstration if loading fails
57 # raise e
58
59# ==============================================================================
60# 4. Running Inference
61# ==============================================================================
62print("\n" + "="*50)
63print("Starting Inference Example")
64print("="*50)
65
66query = "Why do people put ice in drinks?"
67prompt = f"### Query:\n{query}\n\n### Answer:\n"
68print(f"Prompt: {prompt.strip()}")
69
70if 'model' in locals():
71 # Ensure model and inputs are on the same device
72 inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
73
74 # Note: pad_token_id and eos_token_id are often the same for Causal LMs like Gemma
75 outputs = model.generate(
76 **inputs,
77 max_new_tokens=128,
78 do_sample=False,
79 pad_token_id=tokenizer.pad_token_id,
80 eos_token_id=tokenizer.eos_token_id
81 )
82
83 # Decode only the newly generated tokens
84 answer = tokenizer.decode(outputs[0][inputs['input_ids'].shape[-1]:], skip_special_tokens=True)
85 print("\nAnswer:", answer)
86else:
87 print("Skipping inference: Model not loaded.")
88
89# ==============================================================================
90# 5. Metrics & System Information
91# ==============================================================================
92print("\n" + "="*50)
93print("Collecting System Metrics")
94print("="*50)
95
96def get_system_metrics():
97 metrics = {}
98 if torch.cuda.is_available() and pynvml:
99 try:
100 pynvml.nvmlInit()
101 handle = pynvml.nvmlDeviceGetHandleByIndex(0)
102 mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
103 util = pynvml.nvmlDeviceGetUtilizationRates(handle)
104 metrics.update({
105 "gpu_memory_used_GB": round(mem_info.used / 1e9, 2),
106 "gpu_memory_total_GB": round(mem_info.total / 1e9, 2),
107 "gpu_utilization_%": util.gpu
108 })
109 pynvml.nvmlShutdown()
110 except Exception as e:
111 metrics["gpu_error"] = str(e)
112 print(f"Error collecting GPU metrics: {e}")
113 if pynvml: pynvml.nvmlShutdown()
114
115 metrics.update({
116 "cpu_usage_%": psutil.cpu_percent(interval=0.1),
117 "memory_usage_%": psutil.virtual_memory().percent
118 })
119 return metrics
120
121system_metrics = get_system_metrics()
122for key, value in system_metrics.items():
123 print(f"{key}: {value}")
124
125
126# ==============================================================================
127# 6. Standalone Evaluation (Requires 'eval_dataset')
128# Evaluation is decoupled from training to prevent OOM.
129# ==============================================================================
130print("\n" + "="*50)
131print("Starting Standalone Evaluation (Requires 'eval_dataset')")
132print("="*50)
133
134def run_standalone_evaluation(model, tokenizer, eval_dataset):
135 model.eval()
136 # Limiting evaluation to a subset (e.g., first 50 samples) to save time and memory
137 eval_subset = eval_dataset.select(range(min(50, len(eval_dataset))))
138 total_loss = 0
139 for i, sample in enumerate(eval_subset):
140 if i % 10 == 0:
141 print(f"Evaluating sample {i}/{len(eval_subset)}...")
142 try:
143 with torch.no_grad():
144 # Assuming 'eval_dataset' provides 'input_ids', 'attention_mask', 'labels'
145 inputs = {
146 'input_ids': torch.tensor(sample['input_ids']).unsqueeze(0).to(model.device),
147 'attention_mask': torch.tensor(sample['attention_mask']).unsqueeze(0).to(model.device),
148 'labels': torch.tensor(sample['labels']).unsqueeze(0).to(model.device)
149 }
150 outputs = model(**inputs)
151 total_loss += outputs.loss.item()
152 except Exception as e:
153 print(f"Skipping sample {i} due to error: {e}")
154 continue
155
156 if len(eval_subset) > 0:
157 avg_loss = total_loss / len(eval_subset)
158 perplexity = torch.exp(torch.tensor(avg_loss)).item()
159 return {"eval_loss": avg_loss, "perplexity": perplexity}
160 else:
161 return {"eval_loss": 0, "perplexity": 0}
162
163# --- Placeholder for loading datasets ---
164# NOTE: 'eval_dataset' and 'train_dataset' must be defined and loaded
165# using the Hugging Face 'datasets' library before this section can run.
166# Example: from datasets import load_dataset; dataset = load_dataset('some_data'); eval_dataset = dataset['test']
167if 'eval_dataset' in locals() and 'model' in locals():
168 eval_results = run_standalone_evaluation(model, tokenizer, eval_dataset)
169 print("\nEvaluation Results:", eval_results)
170else:
171 print("Skipping evaluation: 'eval_dataset' or 'model' not defined/loaded.")
172
173
174# ==============================================================================
175# 7. Training (Requires 'train_dataset')
176# This section sets up the Trainer but does not execute training unless
177# 'train_dataset' is available.
178# ==============================================================================
179print("\n" + "="*50)
180print("Setting up Memory-Efficient Training (Requires 'train_dataset')")
181print("="*50)
182
183# --- Training Configuration ---
184training_output_dir = "./gemma3-finetuned"
185training_checkpoints_dir = "./training_checkpoints"
186# --- End Training Configuration ---
187
188if 'train_dataset' in locals() and 'model' in locals():
189 print("Initializing Trainer...")
190 data_collator = DataCollatorForLanguageModeling(tokenizer, mlm=False)
191
192 training_args = TrainingArguments(
193 output_dir=training_output_dir,
194 overwrite_output_dir=True,
195 per_device_train_batch_size=2, # Low batch size to save memory
196 gradient_accumulation_steps=8, # Effective batch size is 16 (2 * 8)
197 num_train_epochs=2,
198 learning_rate=2e-5,
199 weight_decay=0.01,
200 logging_steps=100,
201 save_strategy="steps",
202 save_steps=200,
203 save_total_limit=2,
204 fp16=True, # Enables mixed precision
205 dataloader_num_workers=0
206 )
207
208 trainer = Trainer(
209 model=model,
210 args=training_args,
211 train_dataset=train_dataset,
212 eval_dataset=None, # Evaluation is run standalone (Section 6)
213 tokenizer=tokenizer,
214 data_collator=data_collator
215 )
216
217 print("Trainer initialized. Starting training...")
218 try:
219 # Resume from a checkpoint if one is found/specified
220 # Replace 'checkpoint-XXX' with the actual checkpoint directory name
221 trainer.train(resume_from_checkpoint=f"{training_checkpoints_dir}/checkpoint-XXX")
222 trainer.save_model(training_output_dir)
223 print(f"Training complete. Final model saved to: {training_output_dir}")
224 except FileNotFoundError:
225 print("Starting training from scratch (no checkpoint found/specified)...")
226 trainer.train()
227 trainer.save_model(training_output_dir)
228 print(f"Training complete. Final model saved to: {training_output_dir}")
229 except Exception as e:
230 print(f"An error occurred during training: {e}")
231else:
232 print("Skipping training setup: 'train_dataset' or 'model' not defined/loaded.")
233
234# ==============================================================================
235# 8. Logs & Checkpoints (Documented)
236# ==============================================================================
237# Training logs saved to: training_logs.csv
238# Final metrics saved to: final_metrics.csv
239# Checkpoints directory: ./training_checkpoints
240# ==============================================================================