Mission Tomorrow Career Exploration Event hosted by Chamber RVA
Presented to 11,000+ eighth graders in Richmond
Volunteered for IEEE Region3 Richmond
This directory contains scripts and configuration for training YOLOv11 models to recognize facial emotions. This is Step 2 of the emotion detection workflow.
The model-training.py script teaches a YOLOv11 model to recognize emotions by using transfer learning — starting with a pre-trained model and fine-tuning it with emotion detection data.
Think of training a model like teaching a student:
Step 1: Start with a Smart Student
└─ YOLOv11 Nano (yolo11n.pt)
- Already knows how to detect objects
- Pre-trained on 1M+ images
- Ready to specialize in emotions
Step 2: Show Lots of Examples
└─ Roboflow emotion dataset
- Thousands of labeled emotion images
- Different faces, ages, ethnicities
- Each labeled: happy, sad, angry, etc.
Step 3: Let Them Practice & Learn
└─ Train for 200 epochs (repetitions)
- Model adjusts its "brain" weights
- Gets better at recognizing patterns
- Learns what makes faces happy vs sad
Step 4: Test & Save the Best
└─ runs/detect/train/weights/best.pt
- Most accurate version saved
- Ready to use in real-world apps!
- Only 6.5 MB (fits on Raspberry Pi)
Training from scratch would take weeks on a regular computer. Transfer learning:
- Reuses knowledge from 1M+ images
- Trains in minutes/hours (not days)
- Needs fewer examples (thousands vs millions)
- Works great for specialized tasks
This process is what ML Engineers do:
- Prepare datasets
- Train models
- Evaluate performance
- Deploy to production
- Monitor and improve
-
Get Your Roboflow Dataset
First, prepare the emotion detection dataset using the separate roboflow-dataset-manager project:
cd ../roboflow-dataset-manager python dataset-download-roboflow.py # Downloads emotion detection data in YOLOv11 format
This creates a
datasets/folder with:datasets/ ├── data.yaml # Dataset configuration ├── train/images/ # Training images ├── train/labels/ # Training annotations ├── valid/images/ # Validation images ├── valid/labels/ # Validation annotations └── test/images/ # Test images📖 For detailed dataset setup: See ../roboflow-dataset-manager/README.md
-
Dependencies
pip install -r ultralytics-requirements.txt
-
Base Model
yolo11n.ptshould already be in this directory- If missing, it will auto-download on first run
python model-training.pyExpected output:
Loading YOLOv11 Nano base model for transfer learning...
Starting training on emotion detection dataset...
----------------------------------------------------------------------
...training progress...
----------------------------------------------------------------------
✓ Training completed successfully!
Output:
- Best model: runs/detect/emotionsbest.pt/weights/best.pt
- Training results: runs/detect/emotionsbest.pt/results.csv
Training time estimates:
- CPU (typical): 2-4 hours
- GPU (NVIDIA): 30-60 minutes
- Raspberry Pi: Not recommended (use pre-trained model instead)
- Path to dataset configuration file downloaded via roboflow-dataset-manager
- Points to your emotion detection dataset from Roboflow
- This YAML file contains:
path:dataset root directorytrain:path to training imagesval:path to validation imagesnc:10 (number of emotion classes)names:list of emotion class names (e.g., happy, sad, angry, etc.)
Important: Make sure to run the roboflow-dataset-manager script first to generate this file!
- Number of complete passes through the training dataset
- Each epoch:
- Model sees all training images once
- Weights updated based on performance
- Validation performed to check progress
Guidelines:
100-150epochs: Quick training (1-2 hours), decent accuracy200epochs: Balanced (2-4 hours), good accuracy300+epochs: Long training (4+ hours), may overfit
- Input image size (320×320 pixels)
- Trade-off between speed and accuracy
- Options:
320: Fast, lower accuracy (good for RPi deployment)512: Medium (good balance)640: Slower, higher accuracy (best for accuracy)
- Number of images processed per training step
- Depends on available memory
- If "out of memory" error: reduce to 8, 5, or 2
- Larger batches train faster but need more memory
- Where computation happens
- Options:
"cpu": CPU-only (slow but works everywhere)"0": GPU 0 (fast, if NVIDIA CUDA available)"0,1": Multiple GPUs (fastest)
Recommendation:
- For quick testing: Use CPU
- For production: Use GPU (10x faster)
- Name of training run
- Output folder:
runs/detect/emotionsbest.pt/ - Change name for different training runs:
name="emotionsbest_v2.pt" # For second training run
- Parallel workers for loading data
- Depends on CPU cores
- If your CPU has 4 cores: use
workers=4 - If slower: reduce to
workers=2
- Learning rate (how much weights change per step)
- Lower (0.0001): Slow, stable training
- Higher (0.01): Fast, may diverge/fail
- Default (0.001): Recommended balance
- Data augmentation (modify images during training)
- Includes: rotation, scaling, color changes, etc.
- Benefits:
- More diverse training examples
- Better model generalization
- Reduces overfitting
- Recommended: Always
True
After training completes:
runs/detect/emotionsbest.pt/
├── weights/
│ ├── best.pt ← Use this for deployment
│ └── last.pt
├── results.csv ← Training metrics
├── results.png ← Training charts
├── confusion_matrix.png ← Per-class performance
└── val_batch*.jpg ← Example predictions
- Best weights from all 200 epochs
- Highest validation accuracy
- Ready to deploy to Raspberry Pi
- File size: ~6.5 MB
Training progress shown in console with metrics:
Epoch 1/200: loss=2.34, val_loss=2.12, accuracy=0.45
Epoch 2/200: loss=2.10, val_loss=1.98, accuracy=0.58
...
# After training completes
open runs/detect/emotionsbest.pt/results.png
# or
display runs/detect/emotionsbest.pt/results.png # Linuxcat runs/detect/emotionsbest.pt/results.csvmodel.train(
data="../roboflow-dataset-manager/datasets/data.yaml",
epochs=50, # Fewer epochs
imgsz=320,
batch=10,
device="cpu"
)model.train(
data="../roboflow-dataset-manager/datasets/data.yaml",
epochs=300, # More epochs
imgsz=512, # Larger images
batch=16,
device="0" # Use GPU
)model.train(
data="../roboflow-dataset-manager/datasets/data.yaml",
epochs=200,
imgsz=512,
batch=32, # Larger batch (uses multiple GPUs)
device="0,1" # Use GPU 0 and 1
)model.train(
data="../roboflow-dataset-manager/datasets/data.yaml",
epochs=150,
imgsz=320, # Small images
batch=8,
device="cpu"
)Solution: Reduce batch size or image size
batch=5 # Instead of 10
imgsz=320 # Instead of 512Solution: Ensure dataset is downloaded from Roboflow
# Check dataset exists in roboflow-dataset-manager
ls ../roboflow-dataset-manager/datasets/data.yaml
ls ../roboflow-dataset-manager/datasets/train/images/
ls ../roboflow-dataset-manager/datasets/train/labels/
# If not found, run:
cd ../roboflow-dataset-manager
python dataset-download-roboflow.py
cd ../yolo-model-trainingSolution: Use GPU or reduce settings
device="0" # Use GPU if available
imgsz=320 # Smaller images
batch=10 # OK batch size
epochs=100 # Fewer epochs for testingSolutions:
- Increase training time:
epochs=300 - Use larger images:
imgsz=512 - Verify dataset quality (check annotations)
- Try different learning rate:
lr0=0.0005
Solution: Clean up old training runs
rm -rf runs/detect/emotionsbest.pt*/
# Keep only the best versionfrom ultralytics import YOLO
# Load trained model
model = YOLO('runs/detect/emotionsbest.pt/weights/best.pt')
# Predict on image
results = model('image.jpg')
# Display results
results[0].show()# Copy trained model to deployment
cp runs/detect/emotionsbest.pt/weights/best.pt \
../../face-emotion-detection-yolo/yolo-trained-models/emotionnanomodel.ptfrom ultralytics import YOLO
model = YOLO('runs/detect/emotionsbest.pt/weights/best.pt')
# Export to ONNX format (more portable)
model.export(format='onnx')
# Output: best.onnx (can use on different platforms)- Precision: 0.85-0.92 (% of detections that are correct)
- Recall: 0.80-0.88 (% of objects detected)
- mAP50: 0.87-0.94 (overall accuracy at IOU 0.5)
- Inference Speed: 50-100ms per image (CPU)
epoch,train/loss,val/loss,metrics/precision,metrics/recall,metrics/mAP50
0,2.34,2.12,0.45,0.52,0.38
1,2.10,1.98,0.58,0.65,0.51
...
199,0.12,0.18,0.89,0.86,0.87
- Lower loss = better training
- Higher precision/recall = better detections
The dataset downloaded from Roboflow is automatically organized in YOLOv11 format:
Training Data: Used to teach the model
- Located in:
../roboflow-dataset-manager/datasets/train/ - ~70-80% of total images
- Typically 1000+ labeled emotion images
Validation Data: Used to check progress during training
- Located in:
../roboflow-dataset-manager/datasets/valid/ - ~10-15% of total images
- Monitor to prevent overfitting
Test Data: Used to evaluate final model
- Located in:
../roboflow-dataset-manager/datasets/test/ - ~10-15% of total images
- Never seen during training
Switching Datasets: To use a different Roboflow dataset
- Edit
dataset-download-roboflow.pyin roboflow-dataset-manager - Change workspace, project, or version
- Re-run the download script
- Training will automatically use the new dataset
-
Evaluate Results
- Review
results.pngchart - Check
confusion_matrix.png - Analyze metrics in
results.csv
- Review
-
Test on New Images
- Create simple test script
- Verify emotion predictions
- Check confidence scores
-
Deploy Model
- Copy to Raspberry Pi
- Update deployment scripts
- Run real-time inference
-
Iterate if Needed
- Collect more diverse data
- Retrain with new data
- Compare model versions
| Model | Size | Speed | Accuracy |
|---|---|---|---|
| Nano (11n) | 6.5 MB | Fast | Good |
| Small (11s) | 13 MB | Medium | Better |
| Medium (11m) | 33 MB | Slower | Best |
| Large (11l) | 55 MB | Slowest | Excellent |
Recommendation for RPi: Use Nano (11n) - best balance of size and speed
- YOLOv11 Docs: https://docs.ultralytics.com/models/yolov11/
- Ultralytics Training Guide: https://docs.ultralytics.com/modes/train/
- Roboflow Integration: See ../roboflow-dataset-manager/README.md
- Transfer Learning: https://docs.ultralytics.com/modes/train/#transfer-learning
- Backup trained models:
cp runs/detect/emotionsbest.pt/weights/best.pt backup/ - Track experiments: Different
nameparameter for each run - Version datasets: Keep separate version directories
- Monitor resources: Check CPU/GPU usage during training
- Save results: Archive training logs before next training
This project is licensed under the MIT License. See LICENSE file for full details.
MIT License Summary: You are free to use, modify, and distribute this software for any purpose, provided you include the original license and copyright notice.
Created for: IEEE Mission Tomorrow Career Exploration Event
Event: Hosted by Chamber RVA for 11,000+ eighth graders in Richmond
Presented by: IEEE Region 3 Richmond
External Dependencies:
- Ultralytics YOLOv11 — Object detection and transfer learning framework
- PyTorch — Deep learning framework
- Roboflow Python SDK — Dataset downloading and management
- OpenCV — Computer vision library
Special Thanks:
- IEEE Region 3 Richmond for volunteering
- Chamber RVA for organizing Mission Tomorrow
- All educators supporting STEM education
Last Updated: November 2025
Model: YOLOv11 Nano
Framework: Ultralytics
Use Case: Facial Emotion Detection