minimind/docs/training.md

680 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Model Training Guide
Learn how to train MiniMind language models from scratch using pure PyTorch.
## 📊 Training Overview
MiniMind implements a complete training pipeline:
```
Tokenizer Training
↓
Pretraining (Learn knowledge)
↓
SFT (Learn conversation)
↓
┌───────────────────┬─────────────────────┬──────────────┐
↓ ↓ ↓ ↓
LoRA DPO/RLHF RLAIF (PPO/GRPO/SPO) Distillation
(Domain adapt) (Preference) (Reinforcement Learn) (Reasoning)
```
## 💰 Training Costs (Single NVIDIA 3090)
| Model | Dataset | Duration | Cost (RMB) | Quality |
|-------|---------|----------|-----------|---------|
| MiniMind2-Small | pretrain_hq + sft_mini_512 | 2.1h | ≈3 | 😊😊 |
| MiniMind2-Small | Full dataset | 38h | ≈50 | 😊😊😊😊😊😊 |
| MiniMind2 | pretrain_hq + sft_mini_512 | 3.3h | ≈5 | 😊😊 |
| MiniMind2 | Full dataset | 122h | ≈160 | 😊😊😊😊😊😊😊 |
!!! success "Ultra-Fast Training"
**Just 2.1 hours + $3 = Functional ChatBot!**
Use `pretrain_hq.jsonl` + `sft_mini_512.jsonl` for fastest reproduction
## 📋 Data Preparation
### 1. Download Datasets
Download from [ModelScope](https://www.modelscope.cn/datasets/gongjy/minimind_dataset) or [HuggingFace](https://huggingface.co/datasets/jingyaogong/minimind_dataset):
```bash
mkdir -p dataset
cd dataset
# Download required files
```
### 2. Dataset Directory Structure
```
./dataset/
├── pretrain_hq.jsonl ✨ (1.6GB, required for pretraining)
├── sft_mini_512.jsonl ✨ (1.2GB, fastest SFT)
├── sft_512.jsonl (7.5GB, standard SFT)
├── sft_1024.jsonl (5.6GB, longer SFT)
├── sft_2048.jsonl (9GB, very long SFT)
├── dpo.jsonl (909MB, DPO training)
├── r1_mix_1024.jsonl (340MB, reasoning distillation)
├── rlaif-mini.jsonl (1MB, RLAIF algorithms)
├── lora_identity.jsonl (22.8KB, identity LoRA)
└── lora_medical.jsonl (34MB, medical domain LoRA)
```
### 3. Data Formats
**Pretraining Data** (`pretrain_hq.jsonl`):
```json
{"text": "How to overcome procrastination? Overcoming procrastination is not easy, but these suggestions may help..."}
```
**SFT Data** (`sft_*.jsonl`):
```json
{
"conversations": [
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hello! How can I help?"},
{"role": "user", "content": "Tell me a joke."},
{"role": "assistant", "content": "Why did the scarecrow win an award? Because he was outstanding in his field!"}
]
}
```
**DPO Data** (`dpo.jsonl`):
```json
{
"chosen": [
{"role": "user", "content": "What is 2+2?"},
{"role": "assistant", "content": "2+2 equals 4."}
],
"rejected": [
{"role": "user", "content": "What is 2+2?"},
{"role": "assistant", "content": "2+2 equals 5."}
]
}
```
**LoRA Domain Data** (`lora_*.jsonl`):
```json
{
"conversations": [
{"role": "user", "content": "What's the treatment for cervical spondylosis?"},
{"role": "assistant", "content": "Cervical spondylosis treatment typically includes..."}
]
}
```
## 🎯 Complete Training Pipeline
All training scripts are in the `./trainer` directory.
```bash
cd trainer
```
### Stage 1: Pretraining
**Purpose**: Learn foundational knowledge (word continuation)
```bash
# Single GPU
python train_pretrain.py
# Multi-GPU (DDP)
torchrun --nproc_per_node 2 train_pretrain.py
# Multi-GPU (DeepSpeed)
deepspeed --master_port 29500 --num_gpus=2 train_pretrain.py
```
**Key Parameters**:
- `max_seq_len`: 512 (adjust based on GPU memory)
- `learning_rate`: 1e-4
- `epochs`: Adjust based on dataset size
**Output**: `./out/pretrain_*.pth`
**Training Duration**:
- MiniMind2-Small (26M): ~1.1h
- MiniMind2 (104M): ~3.9h
!!! tip "Pretraining Tips"
- Start with `pretrain_hq.jsonl` for best results
- Quality > Quantity for pretraining data
- Monitor loss curve to detect overfitting
### Stage 2: Supervised Fine-Tuning (SFT)
**Purpose**: Teach conversation patterns and chat templates
```bash
# Single GPU
python train_full_sft.py
# Multi-GPU
torchrun --nproc_per_node 2 train_full_sft.py
```
**Configuration**:
- Load pretrained model from Stage 1
- Use SFT dataset (`sft_mini_512.jsonl` or `sft_512.jsonl`)
- Adjust `max_seq_len` to match training data
**Output**: `./out/full_sft_*.pth`
**Training Duration**:
- With sft_mini_512: 1-3 hours
- With full sft_512: 20-25 hours
!!! warning "SFT Data Selection"
- `sft_mini_512.jsonl`: Fastest, ~1.2GB, 512 tokens max
- `sft_512.jsonl`: Standard, ~7.5GB, 512 tokens max
- `sft_1024.jsonl`: Longer, ~5.6GB, 1024 tokens max
- `sft_2048.jsonl`: Extended, ~9GB, 2048 tokens max
### Stage 3: LoRA Fine-Tuning (Optional)
**Purpose**: Parameter-efficient domain adaptation
**Use Cases**:
- Medical Q&A knowledge
- Personal identity/self-awareness
- Proprietary domain knowledge
```bash
# Edit train_lora.py to set correct dataset and base model
python train_lora.py
# Multi-GPU
torchrun --nproc_per_node 2 train_lora.py
```
**Output**: `./out/lora/lora_*.pth`
**Example 1: Medical Domain**
Prepare `dataset/lora_medical.jsonl`:
```json
{
"conversations": [
{"role": "user", "content": "What's the correct pillow height for cervical spondylosis?"},
{"role": "assistant", "content": "For cervical spondylosis, pillow height should be..."}
]
}
```
Train:
```bash
# Modify train_lora.py: lora_name = 'medical'
python train_lora.py
```
**Example 2: Identity/Self-Awareness**
Prepare `dataset/lora_identity.jsonl`:
```json
{
"conversations": [
{"role": "user", "content": "Who are you?"},
{"role": "assistant", "content": "I am MiniMind..."}
]
}
```
### Stage 4: Direct Preference Optimization (DPO)
**Purpose**: Align model responses with human preferences
DPO eliminates the need for separate reward models by directly optimizing preference pairs.
```bash
python train_dpo.py
# Multi-GPU
torchrun --nproc_per_node 2 train_dpo.py
```
**Output**: `./out/rlhf_*.pth`
**Key Features**:
- Off-policy training (reuse data across epochs)
- No separate reward model needed
- Better sample efficiency than PPO
- Stable training convergence
**Training Duration**: ~1-3 hours
### Stage 5: Reinforcement Learning from AI Feedback (RLAIF)
RLAIF is an advanced training approach using AI-generated rewards instead of human annotations. MiniMind implements three modern algorithms:
#### 5.1 PPO (Proximal Policy Optimization)
Classical on-policy RL algorithm with proven stability.
```bash
python train_ppo.py
# Multi-GPU
torchrun --nproc_per_node 2 train_ppo.py
```
**Algorithm**:
$$\mathcal{L}_{PPO} = -\mathbb{E}\left[\min(r_t \cdot A_t, \text{clip}(r_t, 1-\varepsilon, 1+\varepsilon) \cdot A_t)\right] + \beta \cdot \mathbb{E}[\text{KL}]$$
**Characteristics**:
- Stable but slower reward improvement
- Requires both Actor and Critic networks
- High memory usage (1.5-2× single network)
- Good for exploration
**Output**: `./out/ppo_actor_*.pth`
**Training Duration**: ~1-3 hours
#### 5.2 GRPO (Group Relative Policy Optimization)
Modern algorithm used in DeepSeek-R1, with faster convergence.
```bash
python train_grpo.py
# Multi-GPU
torchrun --nproc_per_node 2 train_grpo.py
```
**Algorithm**:
$$\mathcal{L}_{GRPO} = -\mathbb{E}\left[r_t \cdot A_t - \beta \cdot \text{KL}_t\right]$$
Where advantage is computed as:
$$A_t = \frac{R - \mu_{group}}{\sigma_{group}}$$
**Characteristics**:
- Single-network design (memory efficient)
- Faster reward improvement
- Group normalization removes bias
- Better convergence stability
**Output**: `./out/grpo_*.pth`
**Training Duration**: ~1-3 hours
#### 5.3 SPO (Single-stream Policy Optimization)
Newest algorithm (2025) addressing GRPO's degenerate group problem.
```bash
python train_spo.py
# Multi-GPU
torchrun --nproc_per_node 2 train_spo.py
```
**Algorithm**:
$$\mathcal{L}_{SPO} = -\mathbb{E}\left[\log \pi_\theta(a_t|s) \cdot A_t - \beta \cdot \text{KL}_t\right]$$
With adaptive baseline: $B_t^{adaptive}$
**Characteristics**:
- No group dependency (1 input → 1 training sample)
- Adaptive value tracking
- Better handling of difficult examples
- Experimental on small models
**Output**: `./out/spo_*.pth`
**Training Duration**: ~1-3 hours
#### RLAIF Dataset Preparation
All RLAIF algorithms use `rlaif-mini.jsonl` (1MB, 10k examples):
```bash
# Download dataset
# Format: Same as SFT, but assistant content is "无" (none)
{
"conversations": [
{"role": "user", "content": "Explain photosynthesis briefly."},
{"role": "assistant", "content": "无"}
]
}
```
The model generates completions during training, which are scored by a **Reward Model** (e.g., InternLM2-1.8B-Reward).
**Reward Model Setup**:
```bash
# Download reward model to parent directory
cd ../
git clone https://huggingface.co/internlm/internlm2-1_8b-reward
# Directory structure should be:
# project/
# ├── minimind/
# └── internlm2-1_8b-reward/
```
#### RLAIF vs DPO Comparison
| Aspect | DPO | RLAIF (PPO/GRPO/SPO) |
|--------|-----|---------------------|
| Training Type | Off-policy | On-policy |
| Data Freshness | Static pairs | Dynamic (generated) |
| Reward Source | Implicit | Explicit model |
| Convergence | Fast | Slower |
| Memory Usage | Lower | Higher |
| Best For | Preference refinement | Capability improvement |
### Stage 6: Reasoning Model Distillation
**Purpose**: Distill DeepSeek-R1-style reasoning into MiniMind
```bash
python train_distill_reason.py
# Multi-GPU
torchrun --nproc_per_node 2 train_distill_reason.py
```
**Data Format** (`r1_mix_1024.jsonl`):
```json
{
"conversations": [
{
"role": "user",
"content": "Solve: 5 + 3 = ?"
},
{
"role": "assistant",
"content": "<think>\nI need to add 5 and 3.\n5 + 3 = 8\n</think>\n<answer>\n5 + 3 = 8\n</answer>"
}
]
}
```
**Output**: `./out/reason_*.pth`
**Training Features**:
- Enforces `<think>` and `<answer>` tags
- Penalty loss for format violations
- Mixed data (reasoning + multi-turn + English)
## 🔧 Multi-GPU Training
### DDP (Distributed Data Parallel)
Best for single-machine multi-GPU:
```bash
torchrun --nproc_per_node N train_xxx.py
# N = number of GPUs
```
### DeepSpeed
For advanced optimization:
```bash
deepspeed --master_port 29500 --num_gpus=N train_xxx.py
```
### Wandb Monitoring
Track training progress:
```bash
# Login first
wandb login
# Enable wandb logging
torchrun --nproc_per_node N train_xxx.py --use_wandb
# Or SwanLab (China-friendly alternative)
python train_xxx.py --use_wandb # Automatically uses SwanLab if available
```
## 🧪 Model Testing
### Evaluate Pretrain Model
```bash
python eval_model.py --model_mode 0
```
### Evaluate Chat Model
```bash
python eval_model.py --model_mode 1
```
### Evaluate with LoRA
```bash
python eval_model.py --lora_name 'lora_medical' --model_mode 1
```
### Evaluate Reasoning Model
```bash
python eval_model.py --model_mode 3
```
### Evaluate RLAIF Models
```bash
# PPO model
python eval_model.py --model_mode 4
# GRPO model
python eval_model.py --model_mode 4
```
### RoPE Length Extrapolation
Test with extended context:
```bash
python eval_model.py --model_mode 1 --inference_rope_scaling True
```
## 📐 Model Architecture
### MiniMind Structure
**Decoder-Only Transformer** (similar to Llama3):
```
Input Tokens
↓
Token Embedding (6400 vocab)
↓
Rotary Embeddings (RoPE) [with YaRN for length extrapolation]
↓
[Transformer Blocks] ×N
├─ Attention (Multi-Head)
├─ RMSNorm
├─ SwiGLU FFN [or MoE for MoE variant]
└─ Residual Connections
↓
RMSNorm
↓
LM Head (→ 6400 vocab logits)
↓
Output Probabilities
```
### Model Configurations
| Config | MiniMind2-Small | MiniMind2 | MiniMind2-MoE |
|--------|-----------------|----------|---------------|
| Parameters | 26M | 104M | 145M |
| Hidden Dim | 512 | 768 | 640 |
| Layers | 8 | 16 | 8 |
| KV Heads | 2 | 2 | 2 |
| Q Heads | 8 | 8 | 8 |
| Vocab Size | 6,400 | 6,400 | 6,400 |
| Context Length | 2,048 | 2,048 | 2,048 |
### Modify Architecture
Edit `./model/LMConfig.py`:
```python
class LMConfig:
hidden_size: int = 768
num_layers: int = 16
num_heads: int = 8
num_kv_heads: int = 2
# ... other configs
```
## 🔍 Training Tips & Best Practices
### Data Quality > Quantity
- High-quality pretraining data accelerates convergence
- `pretrain_hq.jsonl` is carefully curated for quality
- Consider data deduplication and cleaning
### Learning Rate Scheduling
```python
# Recommended schedules
- Linear warmup then decay
- Initial: 1e-4 to 5e-4
- Warmup steps: 10% of total
- Final: 10% of initial LR
```
### Batch Size & Sequence Length
```python
# Balance between GPU memory and convergence
- Pretraining: max_seq_len=512, batch_size=32
- SFT: max_seq_len=512, batch_size=16
- LoRA: max_seq_len=512, batch_size=16
```
### Memory Optimization
```bash
# Reduce batch size if OOM
python train_xxx.py --batch_size 8
# Or use gradient accumulation
python train_xxx.py --gradient_accumulation_steps 4
```
### Checkpoint Management
- Saves every 100 steps by default
- Each new save overwrites the old one
- Automatic backup before training
## 🚨 Common Issues & Solutions
### Issue: CUDA Out of Memory
```bash
# Solution 1: Reduce batch size
python train_xxx.py --batch_size 4
# Solution 2: Use gradient accumulation
python train_xxx.py --batch_size 16 --gradient_accumulation_steps 2
# Solution 3: Use smaller model
# Edit trainer script to use MiniMind2-Small instead
```
### Issue: Training Not Converging
```python
# Possible causes:
1. Learning rate too high/low
2. Data quality issues
3. Model capacity mismatch
# Solutions:
- Reduce learning rate: --learning_rate 1e-5
- Check data format and quality
- Try smaller model first
```
### Issue: Multi-GPU Sync Errors
```bash
# Ensure:
1. All GPUs visible: nvidia-smi
2. Same CUDA version across all GPUs
3. Network connectivity for distributed training
# Debug:
torchrun --nproc_per_node 2 train_xxx.py --debug
```
### Issue: Different Results Than Expected
```python
# Check:
1. Random seed set (reproducibility)
2. Correct model checkpoint loaded
3. Correct dataset being used
4. Same hyperparameters as reference
```
## 📈 Training Progression
Typical training curves:
```
Pretraining Loss: ↘↘↘ (steep decline, then plateau)
SFT Loss: ↘ (steady decline)
PPO Reward: ↗ (rising, may plateau)
GRPO Reward: ↗↗ (faster rise, more stable)
```
## 🎓 Advanced Topics
### Custom Datasets
Create your own dataset:
```python
# Format: JSONL with conversations list
# Each line is one training example
# Ensure consistent quality and format
```
### Model Quantization (Post-training)
```bash
# 4-bit quantization for inference
# Use tools like:
# - llama.cpp (gguf format)
# - bitsandbytes (dynamic quantization)
# - AutoGPTQ (static quantization)
```
### Model Merging
```python
# Merge base model + LoRA weights
# Use tools like: peft, llama.cpp
```
## 📚 References
- [Scaling Laws](https://arxiv.org/pdf/2001.08361.pdf)
- [RoPE Position Embeddings](https://arxiv.org/abs/2104.09864)
- [YaRN Length Extrapolation](https://arxiv.org/abs/2309.00071)
- [PPO Algorithm](https://arxiv.org/abs/1707.06347)
- [GRPO (DeepSeek)](https://arxiv.org/pdf/2402.03300)
- [SPO Algorithm](https://arxiv.org/abs/2509.13232)
- [DPO](https://arxiv.org/abs/2305.18290)
---
**Next**: Deploy your trained model or explore [advanced inference options](quickstart.md#third-party-inference-frameworks)