Skip to content

Commit ccb2a34

Browse files
PareesaMSmrwyattii
andauthored
Adding Imagenet Example (deepspeedai#680)
Co-authored-by: Michael Wyatt <mrwyattii@gmail.com>
1 parent fe7a76d commit ccb2a34

11 files changed

Lines changed: 786 additions & 0 deletions

File tree

training/imagenet/README.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# ImageNet training with DeepSpeed
2+
3+
This example activated DeepSpeed on the implementation of training a set of popular model architectures on ImageNet dataset. The models include ResNet, AlexNet, and VGG, and the
4+
baseline implementation could be found at pytorch examples [Github repository](https://github.com/pytorch/examples/tree/main/imagenet). Parts of this README is also borrowed from the original repo. DeepSpeed activation allows for ease in
5+
running the code in distributed manner, allowing for easily applying fp16 quantization benefitting Zero stage1 memory reduction.
6+
7+
## DeepSpeed Optimizations
8+
9+
Applying fp16 quantization and Zero stage 1 memory optimization we were able to reduce the required memory. The table bellow summarizes the results of running resnet 50 on a DGX-1
10+
node (with 16 V100 GPUs):
11+
12+
| Optimization level | Allocated Memory (GB) | Mem. Consumption Improvement (%) |
13+
|-------------------|-------------------|---------|
14+
|Baseline | 1.66 | -|
15+
|DS + fp16 | 1.04 | 37.3|
16+
|Ds + fp16 + Zero 1 | 0.81 | 51.2|
17+
18+
Furthermore, the memory optimization had no adverse impact on accuracy, a point illustrated by the graph below.
19+
![resnet-plot](assets/resnetplot.png)
20+
21+
## Requirements
22+
23+
- Install PyTorch ([pytorch.org](http://pytorch.org))
24+
- `pip install -r requirements.txt`
25+
- Download the ImageNet dataset from http://www.image-net.org/
26+
- Then, move and extract the training and validation images to labeled subfolders, using [the following shell script](extract_ILSVRC.sh)
27+
28+
## Training
29+
30+
To train a model, run one of the bash files after setting the model name as well as the path to the ImageNet dataset:
31+
run_ds.sh : baseline code with DeepSpeed activated
32+
run_ds_fp16.sh : fp16 activated
33+
run_ds_fp16_z1.sh: fp16 and Zero1 are activated
34+
35+
36+
The default learning rate schedule starts at 0.1 and decays by a factor of 10 every 30 epochs. This is appropriate for ResNet and models with batch normalization, but too high for AlexNet and VGG. Use 0.01 as the initial learning rate for AlexNet or VGG:
37+
38+
39+
## Use Dummy Data
40+
41+
ImageNet dataset is large and time-consuming to download. To get started quickly, run `main.py` using dummy data by "--dummy". It's also useful for training speed benchmark. Note that the loss or accuracy is useless in this case.
42+
43+
44+
## Usage
45+
46+
```bash
47+
usage: deepspeed main.py [-h] [-a ARCH] [-j N] [--epochs N] [--start-epoch N] [-b N] [--lr LR] [--momentum M] [--wd W] [-p N] [--resume PATH] [-e] [--pretrained] [--world-size WORLD_SIZE]
48+
[--num_gpus NUM GPU] [--num_nodes NUM NODES] [--seed SEED] [--gpu GPU] [--multiprocessing-distributed] [--deepspeed] [--deepspeed_config] [CONFIG FILE] [--dummy] [DIR]
49+
50+
51+
positional arguments:
52+
DIR path to dataset (default: imagenet)
53+
CINFIG FILE path to deepspeed config file
54+
55+
optional arguments:
56+
--deepspeed activated deepspeed library
57+
--deepspeed_config path to the deepspeed config file
58+
--help, -h show this help message and exit
59+
--arch ARCH, -a ARCH model architecture: alexnet | convnext_base | convnext_large | convnext_small | convnext_tiny | densenet121 | densenet161 | densenet169 | densenet201 | efficientnet_b0 |
60+
efficientnet_b1 | efficientnet_b2 | efficientnet_b3 | efficientnet_b4 | efficientnet_b5 | efficientnet_b6 | efficientnet_b7 | googlenet | inception_v3 | mnasnet0_5 | mnasnet0_75 |
61+
mnasnet1_0 | mnasnet1_3 | mobilenet_v2 | mobilenet_v3_large | mobilenet_v3_small | regnet_x_16gf | regnet_x_1_6gf | regnet_x_32gf | regnet_x_3_2gf | regnet_x_400mf | regnet_x_800mf |
62+
regnet_x_8gf | regnet_y_128gf | regnet_y_16gf | regnet_y_1_6gf | regnet_y_32gf | regnet_y_3_2gf | regnet_y_400mf | regnet_y_800mf | regnet_y_8gf | resnet101 | resnet152 | resnet18 |
63+
resnet34 | resnet50 | resnext101_32x8d | resnext50_32x4d | shufflenet_v2_x0_5 | shufflenet_v2_x1_0 | shufflenet_v2_x1_5 | shufflenet_v2_x2_0 | squeezenet1_0 | squeezenet1_1 | vgg11 |
64+
vgg11_bn | vgg13 | vgg13_bn | vgg16 | vgg16_bn | vgg19 | vgg19_bn | vit_b_16 | vit_b_32 | vit_l_16 | vit_l_32 | wide_resnet101_2 | wide_resnet50_2 (default: resnet18)
65+
--workers N, -j N number of data loading workers (default: 4)
66+
--epochs N number of total epochs to run
67+
--start-epoch N manual epoch number (useful on restarts)
68+
--batch-size N, -b N mini-batch size (default: 256), this is the total batch size of all GPUs on the current node when using Data Parallel or Distributed Data Parallel
69+
--lr LR, --learning-rate LR
70+
initial learning rate
71+
--momentum M momentum
72+
--wd W, --weight-decay W
73+
weight decay (default: 1e-4)
74+
--print-freq N, -p N print frequency (default: 10)
75+
--resume PATH path to latest checkpoint (default: none)
76+
--evaluate, -e evaluate model on validation set
77+
--pretrained use pre-trained model
78+
--world-size WORLD_SIZE
79+
number of nodes for distributed training
80+
--local_rank LOCAL_RANK
81+
node rank for distributed training
82+
--seed SEED seed for initializing training.
83+
--gpu GPU GPU id to use.
84+
--num_gpus NUM GPU Num GPUs to use.
85+
--num_nodes NUM NODES Num nodes to use
86+
--multiprocessing-distributed
87+
use multi-processing distributed training to launch N processes per node, which has N GPUs. This is the fastest way to use PyTorch for either single node or multi node data parallel
88+
training
89+
--dummy use fake data to benchmark
90+
91+
92+
Example of running resnet50 on single GPU:
93+
deepspeed --num_nodes=1 --num_gpus=1 main.py -a resnet50 --deepspeed --deepspeed_config config/ds_config.json --dummy
94+
95+
```
136 KB
Loading
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"train_batch_size": 256,
3+
"gradient_accumulation_steps": 1,
4+
"steps_per_print": 50,
5+
6+
"optimizer": {
7+
"type": "Adam",
8+
"params": {
9+
"lr": 0.001,
10+
"betas": [
11+
0.8,
12+
0.999
13+
],
14+
"eps": 1e-8,
15+
"weight_decay": 3e-7
16+
}
17+
},
18+
19+
"zero_optimization": {
20+
"stage": 0
21+
},
22+
"zero_allow_untested_optimizer": true,
23+
"fp16": {
24+
"enabled": false
25+
}
26+
"gradient_clipping": 0,
27+
"prescale_gradients": false,
28+
"cuda_visible_devices": 0,
29+
"wall_clock_breakdown" : false
30+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"train_batch_size": 256,
3+
"gradient_accumulation_steps": 1,
4+
"steps_per_print": 50,
5+
6+
"optimizer": {
7+
"type": "Adam",
8+
"params": {
9+
"lr": 0.001,
10+
"betas": [
11+
0.8,
12+
0.999
13+
],
14+
"eps": 1e-8,
15+
"weight_decay": 3e-7
16+
}
17+
},
18+
19+
"zero_optimization": {
20+
"stage": 0
21+
},
22+
"zero_allow_untested_optimizer": true,
23+
"fp16": {
24+
"enabled": true,
25+
"auto_cast": true
26+
}
27+
"gradient_clipping": 0,
28+
"prescale_gradients": false,
29+
"cuda_visible_devices": 0,
30+
"wall_clock_breakdown" : false
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"train_batch_size": 256,
3+
"gradient_accumulation_steps": 1,
4+
"steps_per_print": 50,
5+
6+
"optimizer": {
7+
"type": "Adam",
8+
"params": {
9+
"lr": 0.001,
10+
"betas": [
11+
0.8,
12+
0.999
13+
],
14+
"eps": 1e-8,
15+
"weight_decay": 3e-7
16+
}
17+
},
18+
19+
"zero_optimization": {
20+
"stage": 1
21+
},
22+
"zero_allow_untested_optimizer": true,
23+
"fp16": {
24+
"enabled": true,
25+
"auto_cast": true
26+
}
27+
"gradient_clipping": 0,
28+
"prescale_gradients": false,
29+
"cuda_visible_devices": 0,
30+
"wall_clock_breakdown" : false
31+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/bin/bash
2+
#
3+
# script to extract ImageNet dataset
4+
# ILSVRC2012_img_train.tar (about 138 GB)
5+
# ILSVRC2012_img_val.tar (about 6.3 GB)
6+
# make sure ILSVRC2012_img_train.tar & ILSVRC2012_img_val.tar in your current directory
7+
#
8+
# Adapted from:
9+
# https://github.com/facebook/fb.resnet.torch/blob/master/INSTALL.md
10+
# https://gist.github.com/BIGBALLON/8a71d225eff18d88e469e6ea9b39cef4
11+
#
12+
# imagenet/train/
13+
# ├── n01440764
14+
# │ ├── n01440764_10026.JPEG
15+
# │ ├── n01440764_10027.JPEG
16+
# │ ├── ......
17+
# ├── ......
18+
# imagenet/val/
19+
# ├── n01440764
20+
# │ ├── ILSVRC2012_val_00000293.JPEG
21+
# │ ├── ILSVRC2012_val_00002138.JPEG
22+
# │ ├── ......
23+
# ├── ......
24+
#
25+
#
26+
# Make imagnet directory
27+
#
28+
mkdir imagenet
29+
#
30+
# Extract the training data:
31+
#
32+
# Create train directory; move .tar file; change directory
33+
mkdir imagenet/train && mv ILSVRC2012_img_train.tar imagenet/train/ && cd imagenet/train
34+
# Extract training set; remove compressed file
35+
tar -xvf ILSVRC2012_img_train.tar && rm -f ILSVRC2012_img_train.tar
36+
#
37+
# At this stage imagenet/train will contain 1000 compressed .tar files, one for each category
38+
#
39+
# For each .tar file:
40+
# 1. create directory with same name as .tar file
41+
# 2. extract and copy contents of .tar file into directory
42+
# 3. remove .tar file
43+
find . -name "*.tar" | while read NAME ; do mkdir -p "${NAME%.tar}"; tar -xvf "${NAME}" -C "${NAME%.tar}"; rm -f "${NAME}"; done
44+
#
45+
# This results in a training directory like so:
46+
#
47+
# imagenet/train/
48+
# ├── n01440764
49+
# │ ├── n01440764_10026.JPEG
50+
# │ ├── n01440764_10027.JPEG
51+
# │ ├── ......
52+
# ├── ......
53+
#
54+
# Change back to original directory
55+
cd ../..
56+
#
57+
# Extract the validation data and move images to subfolders:
58+
#
59+
# Create validation directory; move .tar file; change directory; extract validation .tar; remove compressed file
60+
mkdir imagenet/val && mv ILSVRC2012_img_val.tar imagenet/val/ && cd imagenet/val && tar -xvf ILSVRC2012_img_val.tar && rm -f ILSVRC2012_img_val.tar
61+
# get script from soumith and run; this script creates all class directories and moves images into corresponding directories
62+
wget -qO- https://raw.githubusercontent.com/soumith/imagenetloader.torch/master/valprep.sh | bash
63+
#
64+
# This results in a validation directory like so:
65+
#
66+
# imagenet/val/
67+
# ├── n01440764
68+
# │ ├── ILSVRC2012_val_00000293.JPEG
69+
# │ ├── ILSVRC2012_val_00002138.JPEG
70+
# │ ├── ......
71+
# ├── ......
72+
#
73+
#
74+
# Check total files after extract
75+
#
76+
# $ find train/ -name "*.JPEG" | wc -l
77+
# 1281167
78+
# $ find val/ -name "*.JPEG" | wc -l
79+
# 50000
80+
#

0 commit comments

Comments
 (0)