Skip to content

Commit 32360de

Browse files
Merge pull request #2888 from mhall119/mhall/spark-finetuning
Add new Learning Path: Model Fine-Tuning on NVIDIA DGX Spark
2 parents 545dcfc + 2ce0cd2 commit 32360de

6 files changed

Lines changed: 640 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
title: Setup your NVIDIA DGX Spark
3+
weight: 2
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
The following section comes from the [NVIDIA Developer Program](https://build.nvidia.com/spark/pytorch-fine-tune/instructions) site.
10+
11+
## Configure Docker permissions
12+
13+
Before you can run containerized workloads, you need to ensure your user account has the necessary permissions to interact with Docker. By default, Docker requires root privileges in Ubuntu, which means you would need to prefix every Docker command with `sudo`. Adding your user to the `docker` group eliminates this requirement and streamlines your workflow.
14+
15+
Open a terminal and test your current Docker access:
16+
17+
```bash
18+
docker ps
19+
```
20+
21+
If you see a permission denied error (something like `permission denied while trying to connect to the Docker daemon socket`), you need to add your user to the docker group:
22+
23+
```bash
24+
sudo usermod -aG docker $USER
25+
newgrp docker
26+
```
27+
28+
The `usermod` command adds your user to the docker group, while `newgrp docker` activates the group membership immediately without requiring you to log out and back in. After running these commands, you should be able to execute Docker commands without sudo.
29+
30+
## Download PyTorch container
31+
32+
NVIDIA provides pre-built PyTorch containers that include all the necessary frameworks, libraries, and dependencies optimized for NVIDIA GPUs. These containers are regularly updated and maintained, ensuring you have access to the latest stable versions without the complexity of manual dependency management.
33+
34+
Pull the latest PyTorch container from NVIDIA's container registry:
35+
36+
```bash
37+
docker pull nvcr.io/nvidia/pytorch:25.11-py3
38+
```
39+
40+
This command downloads the November 2025 release of the PyTorch container, which includes PyTorch, CUDA libraries, cuDNN, and other essential tools pre-configured for optimal performance on NVIDIA hardware. The download size is several gigabytes, so this step might take a few minutes depending on your internet connection.
41+
42+
## Launch container instance
43+
44+
Now that you have the container image downloaded, you can launch an interactive container session. This creates an isolated environment where you'll perform all your fine-tuning work.
45+
46+
Run the following command to start the container:
47+
48+
```bash
49+
docker run --gpus all -it --rm --ipc=host \
50+
-v $HOME/.cache/huggingface:/root/.cache/huggingface \
51+
-v ${PWD}:/workspace -w /workspace \
52+
nvcr.io/nvidia/pytorch:25.11-py3
53+
```
54+
55+
This command includes several important flags:
56+
57+
- `--gpus all` gives the container access to all available GPUs on your system
58+
- `--ipc=host` enables shared memory between the host and container, which is essential for multi-GPU training and data loading
59+
- `-v $HOME/.cache/huggingface:/root/.cache/huggingface` mounts your Hugging Face cache directory, preventing repeated downloads of models and datasets
60+
- `-v ${PWD}:/workspace -w /workspace` mounts your current directory into the container and sets it as the working directory, this will allow you to access the fine-tuned model you will be making from another environment later.
61+
62+
After running this command, you'll be inside the container with a root shell prompt.
63+
64+
## Install dependencies
65+
66+
The base PyTorch container doesn't include all the specialized libraries needed for efficient model fine-tuning. You need to install several additional Python packages that provide transformer models, parameter-efficient fine-tuning methods, dataset utilities, and training frameworks.
67+
68+
Inside the running container, install the required dependencies:
69+
70+
```bash
71+
pip install transformers peft datasets trl bitsandbytes
72+
```
73+
74+
These packages serve specific purposes:
75+
76+
- `transformers` provides access to pre-trained language models and tokenizers from Hugging Face
77+
- `peft` (Parameter-Efficient Fine-Tuning) enables techniques like LoRA and QLoRA that reduce memory requirements
78+
- `datasets` offers a standardized interface for loading and processing training datasets
79+
- `trl` (Transformer Reinforcement Learning) includes training utilities and recipes for language models
80+
- `bitsandbytes` enables 4-bit and 8-bit quantization for memory-efficient training
81+
82+
The installation typically takes a few minutes as pip downloads and installs each package along with their dependencies.
83+
84+
## Authenticate with Hugging Face
85+
86+
Many of the models you'll fine-tune are hosted on Hugging Face's model hub. Some models, particularly larger ones like Llama, require authentication to download. Even for public models, authentication provides better rate limits and tracking.
87+
88+
First, obtain a Hugging Face access token from [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens). Then authenticate:
89+
90+
```bash
91+
huggingface-cli login
92+
```
93+
94+
When prompted, paste your token and press Enter. When asked about git credentials, enter `n` since you don't need git integration for this workflow. This authentication persists across sessions because you mounted your Hugging Face cache directory, so you won't need to repeat this step.
95+
96+
## Download NVIDIA DGX Spark playbook
97+
98+
NVIDIA provides a collection of ready-to-use fine-tuning scripts specifically optimized for DGX systems. These scripts implement best practices for various model sizes and fine-tuning techniques, saving you from writing training code from scratch.
99+
100+
Clone the playbooks repository:
101+
102+
```bash
103+
git clone https://github.com/NVIDIA/dgx-spark-playbooks
104+
cd dgx-spark-playbooks/nvidia/pytorch-fine-tune/assets
105+
```
106+
107+
The repository contains scripts for different model architectures and training strategies. The `assets` directory includes the fine-tuning scripts you'll use in the next steps. Each script is preconfigured with sensible defaults but also accepts command-line arguments for customization.
108+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: How Fine Tuning Works
3+
weight: 3
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Why fine-tuning matters
10+
11+
Pre-trained large language models (LLMs) are trained on vast amounts of general text data, giving them broad knowledge and language understanding. However, these models often need specialization to perform well on specific tasks, domains, or to follow particular instruction formats. Fine-tuning adapts a pre-trained model to your specific use case without the computational expense of training from scratch.
12+
13+
Fine-tuning is essential when you need a model to:
14+
15+
- Understand domain-specific terminology and concepts (medical, legal, scientific)
16+
- Follow specific instruction formats or conversation styles
17+
- Perform specialized tasks with higher accuracy than a general-purpose model
18+
- Align with organizational guidelines or safety requirements
19+
- Reduce hallucinations in specific knowledge domains
20+
21+
The process typically requires significantly less data and compute resources than pre-training. While pre-training might use trillions of tokens on thousands of GPUs, fine-tuning can achieve excellent results with thousands or even hundreds of carefully curated examples on a single GPU or small GPU cluster, making it an ideal use case for the NVIDIA DGX Spark.
22+
23+
For a deeper look at LLM fine-tuning with Hugging Face transformers, see the [Hugging Face Fine-tuning Guide](https://huggingface.co/docs/transformers/training).
24+
25+
## How supervised fine-tuning works
26+
27+
Supervised fine-tuning (SFT) continues the training process on a pre-trained model using labeled examples that demonstrate the desired behavior. Unlike pre-training, which predicts the next token from unlabeled text, SFT uses input-output pairs that explicitly teach the model how to respond to specific queries or prompts.
28+
29+
The process works by:
30+
31+
**Data preparation** - You create or collect a dataset of input-output pairs. For instruction tuning, this means pairs of user prompts and desired responses. For example: "Explain photosynthesis" paired with a detailed explanation.
32+
33+
**Loss calculation** - The model generates predictions for the training examples, and the training algorithm calculates how different the predictions are from the target outputs. This difference is quantified using a loss function, typically cross-entropy loss for language models.
34+
35+
**Gradient computation** - A gradient represents the direction and magnitude of change needed for each model parameter to reduce the loss. The training process calculates gradients that indicate how to adjust each model parameter to reduce the loss. These gradients flow backward through the neural network layers via backpropagation.
36+
37+
**Parameter updates** - The optimizer uses the gradients to update the model's weights, making small adjustments that should improve performance on the training examples. This process repeats across many examples and multiple epochs.
38+
39+
**Validation** - Periodically, you evaluate the model on held-out validation data to ensure it's learning to generalize rather than simply memorizing the training set.
40+
41+
The key advantage of SFT is that it preserves the pre-trained model's general knowledge while adapting its behavior to match your specific examples. The model learns the patterns in your data without forgetting what it learned during pre-training.
42+
43+
For technical details on the algorithms behind supervised fine-tuning, refer to the [PyTorch training documentation](https://pytorch.org/tutorials/beginner/introyt/trainingyt.html).
44+
45+
## What instruction tuning does for a model
46+
47+
Instruction tuning is a specific type of supervised fine-tuning that teaches models to follow natural language instructions. Base pre-trained models are excellent at completing text but don't inherently understand how to respond to commands or questions in a conversational format. Instruction tuning bridges this gap.
48+
49+
The transformation happens through training on datasets where each example contains:
50+
51+
**Instruction** - A clear directive or question
52+
**Input** (optional) - Additional context or data to process
53+
**Output** - The desired response demonstrating correct behavior
54+
55+
For example:
56+
- Instruction: "Summarize the following article"
57+
- Input: [article text]
58+
- Output: [concise summary]
59+
60+
After instruction tuning, the model learns to:
61+
62+
- Recognize and interpret different instruction formats
63+
- Generate responses that directly address the given task
64+
- Maintain an expected tone and formatting for different request types
65+
66+
This process dramatically improves the model's usability. While a base model might continue a prompt like "Translate this sentence to French: Hello" by generating more English text, an instruction-tuned model understands this is a task request and produces the French translation.
67+
68+
Popular instruction-tuning datasets include Alpaca, Dolly, and FLAN. These datasets contain diverse instructions across many domains and task types, helping models generalize to new instructions they haven't seen during training. In the next step you will use the Alpaca dataset to fine-tune a base pre-trained model.
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
title: Fine Tuning with PyTorch and Hugging Face
3+
weight: 4
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Review fine-tuning scripts
10+
11+
The NVIDIA playbook provides four main fine-tuning scripts, each designed for different scenarios:
12+
13+
**Llama3_3B_full_finetuning.py** - Full supervised fine-tuning for Llama 3.2 3B
14+
This script trains all model parameters, providing maximum flexibility but requiring more GPU memory. Use this for smaller models when you have sufficient GPU resources and want the best possible fine-tuning results.
15+
16+
**Llama3_8B_LoRA_finetuning.py** - LoRA fine-tuning for Llama 3.1 8B
17+
This script uses Low-Rank Adaptation (LoRA), which trains only a small number of additional parameters while keeping the base model frozen. This approach dramatically reduces memory requirements and training time while maintaining good performance.
18+
19+
**Llama3_70B_LoRA_finetuning.py** - LoRA fine-tuning for Llama 3.1 70B with FSDP
20+
For larger 70B models, this script implements LoRA with Fully Sharded Data Parallel (FSDP) support, distributing the model across multiple GPUs to handle the increased memory requirements.
21+
22+
**Llama3_70B_qLoRA_finetuning.py** - QLoRA fine-tuning for Llama 3.1 70B
23+
This script uses Quantized LoRA (QLoRA), which combines LoRA with 4-bit quantization. This is the most memory-efficient option, allowing you to fine-tune very large models even on systems with limited GPU memory.
24+
25+
26+
The file names only refer to the default model they will use if you don't specify one on the command line, you can use them to train other models of your choosing. This tutorial will use the `Llama3_3B_full_finetuning.py` script. Below are the key sections of that script.
27+
28+
## Imports and dataset preparation
29+
30+
This section sets up the foundation for finetuning. The imports bring in PyTorch, dataset loading utilities, and Hugging Face libraries for supervised fine-tuning.
31+
32+
```python
33+
34+
import torch
35+
import argparse
36+
from datasets import load_dataset
37+
from trl import SFTConfig, SFTTrainer
38+
from transformers import AutoModelForCausalLM, AutoTokenizer
39+
```
40+
41+
The `ALPACA_PROMPT_TEMPLATE` defines the instruction-following format for training data with three fields: instruction, input, and response. This is the format that the fine-tuned model will be taught to expect as input and produce as output.
42+
43+
The `get_alpaca_dataset()` function loads the Alpaca dataset and formats each example using the template, appending the EOS (End of String) token. It selects a configurable number of samples (default 500) and shuffles them for training.
44+
45+
```python
46+
# Define prompt templates
47+
ALPACA_PROMPT_TEMPLATE = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
48+
### Instruction: {}
49+
50+
### Input: {}
51+
52+
### Response: {}"""
53+
54+
def get_alpaca_dataset(eos_token, dataset_size=500):
55+
# Preprocess the dataset
56+
def preprocess(x):
57+
texts = [
58+
ALPACA_PROMPT_TEMPLATE.format(instruction, input, output) + eos_token
59+
for instruction, input, output in zip(x["instruction"], x["input"], x["output"])
60+
]
61+
return {"text": texts}
62+
63+
dataset = load_dataset("tatsu-lab/alpaca", split="train").select(range(dataset_size)).shuffle(seed=42)
64+
return dataset.map(preprocess, remove_columns=dataset.column_names, batched=True)
65+
```
66+
67+
## Model and tokenizer loading
68+
69+
This section initializes the language model. The `from_pretrained()` method loads a pre-trained language model from Hugging Face. The tokenizer loads the corresponding tokenizer and sets the padding token to match the EOS token, which is necessary for batched training.
70+
71+
```python
72+
# Load the model and tokenizer
73+
print(f"Loading model: {args.model_name}")
74+
model = AutoModelForCausalLM.from_pretrained(
75+
args.model_name,
76+
dtype=args.dtype,
77+
device_map="auto",
78+
trust_remote_code=True
79+
)
80+
tokenizer = AutoTokenizer.from_pretrained(args.model_name, trust_remote_code=True)
81+
tokenizer.pad_token = tokenizer.eos_token
82+
```
83+
84+
## Dataset loading
85+
86+
This section prepares the training data by calling the previously defined `get_alpaca_dataset()` function with the model's tokenizer EOS token and the specified dataset size. The formatted dataset is ready for the trainer to consume.
87+
88+
```python
89+
# Load and preprocess the dataset
90+
print(f"Loading dataset with {args.dataset_size} samples...")
91+
dataset = get_alpaca_dataset(tokenizer.eos_token, args.dataset_size)
92+
```
93+
94+
## Training configuration
95+
96+
This section defines parameters for supervised fine-tuning. Key parameters include `num_train_epochs` (set to 0.01 for a warmup epoch, later changed to full training), `gradient_accumulation_steps` (how many batches to accumulate before updating weights), `learning_rate` (step size for optimizer updates), and `max_length` (maximum sequence length for training samples). The logging parameters control where and how often training metrics are saved.
97+
98+
```python
99+
# Configure the SFT config
100+
config = {
101+
"per_device_train_batch_size": args.batch_size,
102+
"num_train_epochs": 0.01, # Warmup epoch
103+
"gradient_accumulation_steps": args.gradient_accumulation_steps,
104+
"learning_rate": args.learning_rate,
105+
"optim": "adamw_torch",
106+
"save_strategy": 'no',
107+
"remove_unused_columns": False,
108+
"seed": 42,
109+
"dataset_text_field": "text",
110+
"packing": False,
111+
"max_length": args.seq_length,
112+
"torch_compile": False,
113+
"report_to": "none",
114+
"logging_dir": args.log_dir,
115+
"logging_steps": args.logging_steps,
116+
"gradient_checkpointing": args.gradient_checkpointing, # Save memory
117+
}
118+
```
119+
120+
## Model compilation and training
121+
122+
This section handles optional PyTorch compilation and executes the training. If enabled, `torch.compile()` optimizes the model for faster execution on the hardware. A warmup training pass runs a short training session (0.01 epochs) to trigger compilation and avoid compilation overhead during the actual training run. The full training creates an `SFTTrainer` with the full epoch count, then executes the training with `trainer.train()`. The `trainer_stats` variable returns training metrics like loss, throughput, and training time.
123+
124+
```python
125+
# Compile model if requested
126+
if args.use_torch_compile:
127+
print("Compiling model with torch.compile()...")
128+
model = torch.compile(model)
129+
130+
# Warmup for torch compile
131+
print("Running warmup for torch.compile()...")
132+
SFTTrainer(
133+
model=model,
134+
processing_class=tokenizer,
135+
train_dataset=dataset,
136+
args=SFTConfig(**config),
137+
).train()
138+
139+
# Train the model
140+
print(f"\nStarting full fine-tuning for {args.num_epochs} epoch(s)...")
141+
config["num_train_epochs"] = args.num_epochs
142+
config["report_to"] = "tensorboard"
143+
144+
trainer = SFTTrainer(
145+
model=model,
146+
processing_class=tokenizer,
147+
train_dataset=dataset,
148+
args=SFTConfig(**config),
149+
)
150+
151+
trainer_stats = trainer.train()
152+
```
153+
154+
## Model saving
155+
156+
Finally, section saves the fine-tuned model and tokenizer to disk if an output directory is specified. The `trainer.save_model()` method saves the model weights and configuration, while `tokenizer.save_pretrained()` saves the tokenizer configuration and vocabulary. This allows you to load and use the fine-tuned model later for inference or further training.
157+
158+
```python
159+
# Save model if requested
160+
if args.output_dir:
161+
print(f"Saving model to {args.output_dir}...")
162+
trainer.save_model(args.output_dir)
163+
tokenizer.save_pretrained(args.output_dir)
164+
print("Model saved successfully!")
165+
```
166+
167+
## Run the fine-tuning
168+
169+
```bash
170+
python Llama3_3B_full_finetuning.py \
171+
--model_name "meta-llama/Meta-Llama-3-8B" \
172+
--output_dir workspace/Models/Llama-3-8B-FineTuned
173+
```

0 commit comments

Comments
 (0)