Set Training Hyperparameters for LLMs
Set training hyperparameters for LLMs in this LLM Finetuning tutorial — practical steps, common pitfalls, and what to study next.
Focus: set training hyperparameters for llms
Training a large language model is a bit like teaching someone to cook a complex dish. You can have the finest ingredients (your data) and the best recipe (the model architecture), but if you bake at the wrong temperature or for too long, you'll end up with a flavorful disaster. The dreaded 'loss plateau', 'catastrophic forgetting', or a model that just spits out nonsense are all classic symptoms of poorly set hyperparameters. In this lesson, you'll learn how to systematically set training hyperparameters for LLMs — from learning rate to batch size to epochs — so you can transform your raw data into a finely-tuned assistant that actually follows your instructions.
The problem this lesson solves
Imagine you've spent days cleaning and formatting your dataset, only to watch your fine-tuning run produce a model that repeats itself, forgets the general knowledge it was pretrained with, or never seems to improve. You're not alone. This is the single most common frustration in LLM fine-tuning.
Without a solid grasp of hyperparameters, you're essentially gambling with your compute budget. Too high a learning rate and the loss explodes; too low and the model barely moves. Wrong batch size can cause unstable training, and too many epochs can lead to overfitting on your narrow dataset. This lesson gives you the mental framework and Python code to set these values with confidence, so your training runs are predictable, efficient, and effective.
Core concept / mental model
Think of your pretrained LLM as a skilled but stubborn chef. Fine-tuning is the process of teaching it your specific restaurant's special recipes. Hyperparameters are the knobs you control during this apprenticeship:
- Learning rate – how aggressively the model changes its weights per step. A small learning rate is like a cautious apprentice who takes tiny, careful steps. A large one is like a reckless one who might knock over the whole kitchen.
- Batch size – how many recipes (samples) the model reviews at once before adjusting. A larger batch gives a more stable gradient estimate but uses more memory.
- Epochs – how many times the model goes through your entire dataset.
- Weight decay – a regularizer that discourages the model from becoming too confident in its weights.
- Warmup steps – a gradual increase from a low learning rate to the target rate, which helps avoid early instability.
You can visualize the training process as navigating a loss landscape. Hyperparameters determine the size of your steps (learning rate), how often you look at the map (batch size), and how many laps you take (epochs).
How it works step by step
The process of setting hyperparameters follows a logical sequence. Let's walk through it.
- Initialize training arguments – You'll use the Hugging Face
TrainingArgumentsclass to define most hyperparameters. - Choose a learning rate – A common starting point for fine-tuning is 2e-5 for full fine-tuning and 1e-4 to 5e-4 for LoRA (Parameter-Efficient Fine-Tuning).
- Set batch size – Depending on your GPU memory, start with 8 or 16. Use gradient accumulation if you need a larger effective batch.
- Pick the number of epochs – 3 is a solid default, but you can monitor validation loss to detect overfitting.
- Enable warmup – 10% of total steps is a common ratio.
- Use weight decay – A value like 0.01 helps with regularization.
- Consider advanced optimizers – Options like
AdamWwith a cosine learning rate schedule are widely used.
Hands-on walkthrough
Let's put this into practice. We'll set hyperparameters for a QLoRA fine-tuning run using the Hugging Face transformers library. Here’s a complete example to get you started.
from transformers import TrainingArguments
args = TrainingArguments(
output_dir="./lora-llm",
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
num_train_epochs=3,
learning_rate=2e-4,
warmup_ratio=0.03,
weight_decay=0.01,
logging_steps=50,
save_strategy="epoch",
evaluation_strategy="epoch",
)
Expected behavior: The training loop will save a checkpoint after each epoch and log loss every 50 steps. The effective batch size is 4 * 4 = 16.
Now let's hook this into a real Trainer with a tiny LoRA model.
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model
from transformers import Trainer
# Load a small model (for demo)
model_name = "microsoft/phi-2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(model_name, load_in_4bit=True)
# Configure LoRA
lora_config = LoraConfig(
r=8,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05
)
model = get_peft_model(model, lora_config)
# Your datasets go here (dummy)
from transformers import DataCollatorForLanguageModeling
collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
# Assume train_dataset and eval_dataset are prepared
# Create the Trainer
trainer = Trainer(
model=model,
args=args,
data_collator=collator,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
# Start training
trainer.train()
Expected output: You'll see a progress bar with the loss decreasing per logging step. For example:
Step: 50, loss: 1.2345
Step: 100, loss: 1.0056
...
Always monitor the loss curve. A decreasing trend indicates healthy learning.
Compare options / when to choose what
Not all hyperparameter choices are equal. Here's a quick comparison table to help you decide.
| Hyperparameter | Full Fine-tuning | LoRA/QLoRA | When to Prefer Something Else |
|---|---|---|---|
| Learning rate | 2e-5 | 1e-4 to 5e-4 | For small datasets, use lower LR to avoid overfitting |
| Batch size | 16+ | 8–16 | If OOM, reduce batch size and increase gradient accumulation |
| Epochs | 3 | 3–5 | If early overfitting, reduce epochs |
| Weight decay | 0.01 | 0.01–0.1 | Use higher decay for noisy data |
| Optimizer | AdamW | AdamW (paged for QLoRA) | For memory, try AdaFactor |
Pro tip: When in doubt, start with the low end of the learning rate range. It's easier to recover from a slow start than from a diverged run.
Different optimizers also come with their own quirks. The paged AdamW in QLoRA offloads optimizer states to CPU, which helps big models fit into small GPUs but can slow training.
Troubleshooting & edge cases
Here are the most common issues and how to fix them:
- Loss spikes or NaN – Often caused by too high a learning rate. Lower it (e.g., from 2e-4 to 5e-5) and add gradient clipping.
- Model doesn't improve – Check if your learning rate is too low. Try increasing by a factor of 10 or use a cosine schedule with a higher peak.
- Out-of-memory (OOM) – Reduce batch size, enable gradient accumulation, or use LoRA with 4-bit quantization (QLoRA).
- Overfitting – If validation loss starts increasing after a few epochs, reduce epochs, increase weight decay, or add more dropout.
- Warmup too short – If training is unstable in the first few steps, increase the warmup ratio to 10% or more.
What you learned & what's next
You've learned how to set the core training hyperparameters for LLMs: learning rate, batch size, epochs, warmup, and weight decay. You can now configure a training run using Hugging Face's TrainingArguments and Trainer, and you know how to troubleshoot common issues like overfitting and OOM errors.
Your next lesson in the LLM Fine-Tuning track will take you through Evaluating Fine-Tuned Models — where you'll use metrics like perplexity and human evaluation to see if your hyperparameter choices actually produced a better model.
Practice recap
Try setting up a TrainingArguments for a LoRA fine-tuning run on your own dataset. Start with a small model like 'gpt2', use a batch size of 4, gradient accumulation of 4, and a learning rate of 2e-4. Run for 3 epochs and monitor the loss curve. If it diverges, lower the learning rate to 5e-5 and re-run.
Common mistakes
- Using a learning rate that's too high (e.g., > 1e-3) for fine-tuning, which causes the loss to explode or produce NaN values.
- Ignoring gradient accumulation and running out of memory, then crashing the training job instead of reducing batch size.
- Setting num_train_epochs=1 and expecting good results — underfitting is just as common as overfitting.
- Forgetting to set the pad token, which leads to cryptic tokenizer errors during training.
Variations
- Use the
SFTTrainerfrom thetrllibrary for a more high-level interface that handles padding and data collation automatically. - Try a learning rate scheduler like cosine or linear with warmup using the
lr_scheduler_typeparameter inTrainingArguments. - Experiment with different optimizers like AdamW (default) or AdaFactor for memory-constrained environments.
Real-world use cases
- Fine-tuning a small instruction-following model (like Llama-2-7b) on a domain-specific QA dataset with QLoRA and a learning rate of 2e-4.
- Training a sentiment-analysis model on a few thousand product reviews, using a low learning rate like 2e-5 and 3 epochs to avoid overfitting.
- Adapting a code-generation model to a proprietary API's syntax by using LoRA with per_device_batch_size=4 and gradient accumulation to fit on a 16GB GPU.
Key takeaways
- Hyperparameters control how fast and how well your model learns — think of them as the speed and temperature of your training oven.
- Start with common defaults: learning rate 2e-5 (full) or 2e-4 (LoRA), batch size 8-16, and 3 epochs.
- Use gradient accumulation to simulate larger batches without blowing up GPU memory.
- Always monitor loss curves — a flat or explosive loss signals a problem with your hyperparameters.
- Warmup steps prevent early instability, and weight decay helps prevent overfitting.
- Experiment systematically: change one hyperparameter at a time and track validation metrics.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.