Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New YOLOv5 Classification Models #8956

Merged
merged 448 commits into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
448 commits
Select commit Hold shift + click to select a range
4602c01
Update
glenn-jocher Jul 20, 2022
798cab5
Logger step fix: Increment step with epochs (#8654)
AyushExel Jul 20, 2022
5d69e04
Update
glenn-jocher Jul 20, 2022
fceeb9a
Update
glenn-jocher Jul 20, 2022
bdb33b9
Update
glenn-jocher Jul 21, 2022
5fdeba7
Update
glenn-jocher Jul 21, 2022
bc72ec0
Update
glenn-jocher Jul 21, 2022
1b00861
Update
glenn-jocher Jul 21, 2022
053ada1
Update
glenn-jocher Jul 21, 2022
167406d
Update
glenn-jocher Jul 21, 2022
dbe92bb
Update
glenn-jocher Jul 21, 2022
761c1d3
Update
glenn-jocher Jul 21, 2022
07297c4
Update
glenn-jocher Jul 21, 2022
d80c2f5
Update
glenn-jocher Jul 21, 2022
8610aa8
Update
glenn-jocher Jul 21, 2022
0524acb
Update
glenn-jocher Jul 21, 2022
c31cfb4
Update
glenn-jocher Jul 21, 2022
0610a5d
Update
glenn-jocher Jul 21, 2022
1433d3b
Update
glenn-jocher Jul 21, 2022
b66d142
Update
glenn-jocher Jul 21, 2022
3a7a404
Update
glenn-jocher Jul 21, 2022
d11fc06
Update
glenn-jocher Jul 21, 2022
334f8bc
Update
glenn-jocher Jul 21, 2022
ebebb62
Update
glenn-jocher Jul 21, 2022
8faadee
Update
glenn-jocher Jul 21, 2022
0a5a0ab
Update
glenn-jocher Jul 22, 2022
7cc91cc
Update
glenn-jocher Jul 22, 2022
a545207
Update
glenn-jocher Jul 22, 2022
50aaf98
Update
glenn-jocher Jul 22, 2022
1c2f432
Allow logging models from GenericLogger (#8676)
AyushExel Jul 22, 2022
5760567
Update
glenn-jocher Jul 22, 2022
c2095e1
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Jul 22, 2022
a551986
Update
glenn-jocher Jul 22, 2022
6c9ff8c
Update
glenn-jocher Jul 22, 2022
956879b
Update
glenn-jocher Jul 22, 2022
bfb5c1f
Update
glenn-jocher Jul 22, 2022
5ed36ee
Update warning emojis
glenn-jocher Jul 22, 2022
04d3e64
Update dataset download
glenn-jocher Jul 22, 2022
dcf5670
Update dataset download
glenn-jocher Jul 22, 2022
a86fdd0
Update
glenn-jocher Jul 22, 2022
2a59208
Update
glenn-jocher Jul 22, 2022
b80dd7e
Update
glenn-jocher Jul 22, 2022
1097af8
Update
glenn-jocher Jul 22, 2022
4edd9b2
Update
glenn-jocher Jul 22, 2022
9256d45
Update
glenn-jocher Jul 22, 2022
1d72089
Update
glenn-jocher Jul 22, 2022
73bb5ff
Update
glenn-jocher Jul 22, 2022
0670b38
Update
glenn-jocher Jul 22, 2022
aa9184d
Update
glenn-jocher Jul 22, 2022
3626508
Update
glenn-jocher Jul 22, 2022
aa32e13
Update
glenn-jocher Jul 22, 2022
0e010ae
Update
glenn-jocher Jul 22, 2022
1ecaf0b
Update
glenn-jocher Jul 22, 2022
685503b
Update
glenn-jocher Jul 22, 2022
101b21f
Update
glenn-jocher Jul 22, 2022
97d1fa6
Update
glenn-jocher Jul 22, 2022
19ffb4e
Update
glenn-jocher Jul 22, 2022
95eca5d
Update
glenn-jocher Jul 22, 2022
fa44db7
Update
glenn-jocher Jul 23, 2022
b751ab2
Update
glenn-jocher Jul 23, 2022
ff85584
Update
glenn-jocher Jul 23, 2022
e1fb3e6
Pass imgsz to classify_transforms()
glenn-jocher Jul 23, 2022
7a73663
Update
glenn-jocher Jul 23, 2022
e535213
Update
glenn-jocher Jul 23, 2022
f839244
Update
glenn-jocher Jul 23, 2022
2c90896
Update
glenn-jocher Jul 23, 2022
a6d5521
Update
glenn-jocher Jul 23, 2022
9dc5e6a
Update
glenn-jocher Jul 24, 2022
1782d0c
Update
glenn-jocher Jul 24, 2022
84d6bd7
Update
glenn-jocher Jul 25, 2022
a06efbd
Update
glenn-jocher Jul 25, 2022
6432df0
Update
glenn-jocher Jul 25, 2022
d86bb55
Update
glenn-jocher Jul 25, 2022
0d6490c
Update
glenn-jocher Jul 25, 2022
12421e1
Update
glenn-jocher Jul 25, 2022
5f3773b
Update
glenn-jocher Jul 25, 2022
9db31ea
Update
glenn-jocher Jul 25, 2022
0551a31
Update
glenn-jocher Jul 25, 2022
f12bc8a
Update
glenn-jocher Jul 26, 2022
9d9e16f
Update
glenn-jocher Jul 26, 2022
55f0fa8
Update
glenn-jocher Jul 26, 2022
fabac7c
Update
glenn-jocher Jul 26, 2022
e64ba0e
Update
glenn-jocher Jul 27, 2022
1038734
Update
glenn-jocher Jul 27, 2022
86dd4d9
Cos scheduler
glenn-jocher Jul 30, 2022
2594685
Cos scheduler
glenn-jocher Jul 30, 2022
0251d35
Remove unused args
glenn-jocher Jul 30, 2022
1f7b95c
Update
glenn-jocher Jul 30, 2022
e88ba9d
Add seed
glenn-jocher Jul 30, 2022
f610079
Add seed
glenn-jocher Jul 30, 2022
635ab3f
Update
glenn-jocher Jul 30, 2022
eea5731
Update
glenn-jocher Jul 30, 2022
ef749a1
Add run(), main()
glenn-jocher Jul 30, 2022
d2cde35
Merge master
glenn-jocher Jul 30, 2022
8a0da6d
Merge master
glenn-jocher Jul 30, 2022
a92840a
Merge master
glenn-jocher Jul 30, 2022
976d5c7
Merge master
glenn-jocher Jul 31, 2022
f43572e
Update
glenn-jocher Aug 1, 2022
cabbb30
Update
glenn-jocher Aug 1, 2022
59b2353
Update
glenn-jocher Aug 1, 2022
c5b92f5
Update
glenn-jocher Aug 1, 2022
ebb9c99
Update
glenn-jocher Aug 1, 2022
7c1225f
Update
glenn-jocher Aug 1, 2022
e24b47d
Update
glenn-jocher Aug 1, 2022
8ac8830
Merge master
glenn-jocher Aug 1, 2022
ebb141a
fix
glenn-jocher Aug 1, 2022
e567764
Create YOLOv5 BaseModel class (#8829)
glenn-jocher Aug 2, 2022
13c46bd
Add experiment
glenn-jocher Aug 3, 2022
1e548f0
Merge master
glenn-jocher Aug 3, 2022
3284fe7
Merge master
glenn-jocher Aug 3, 2022
1e9994a
Merge master
glenn-jocher Aug 4, 2022
903169a
Attach names
glenn-jocher Aug 4, 2022
84cc9bf
Merge master
glenn-jocher Aug 4, 2022
2291181
weight decay = 1e-4
glenn-jocher Aug 4, 2022
524e989
weight decay = 5e-5
glenn-jocher Aug 4, 2022
4d3fede
update smart_optimizer console printout
glenn-jocher Aug 4, 2022
2fe1b97
fashion-mnist fix
glenn-jocher Aug 4, 2022
6a01f58
Merge master
glenn-jocher Aug 9, 2022
7114bb9
Merge master
glenn-jocher Aug 9, 2022
ef00f41
Merge master
glenn-jocher Aug 9, 2022
01bc47f
Merge master
glenn-jocher Aug 13, 2022
9c5a035
Update Table
glenn-jocher Aug 13, 2022
bd135ba
Update Table
glenn-jocher Aug 13, 2022
012476b
Remove destroy process group
glenn-jocher Aug 13, 2022
037fb37
Merge master
glenn-jocher Aug 13, 2022
a1e81df
add kwargs to forward()
glenn-jocher Aug 13, 2022
9c17a70
fuse fix for resnet50
glenn-jocher Aug 13, 2022
7132881
nc, names fix for resnet50
glenn-jocher Aug 13, 2022
a512ab0
nc, names fix for resnet50
glenn-jocher Aug 13, 2022
c2cab3a
ONNX CPU inference fix
glenn-jocher Aug 13, 2022
6302731
revert
glenn-jocher Aug 13, 2022
7a60338
cuda
glenn-jocher Aug 13, 2022
ea8d237
if augment or visualize
glenn-jocher Aug 13, 2022
49720f7
if augment or visualize
glenn-jocher Aug 13, 2022
3f5c692
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2022
f27df13
New smart_inference_mode()
glenn-jocher Aug 13, 2022
0a07a83
New smart_inference_mode()
glenn-jocher Aug 13, 2022
5fe56fc
Update README
glenn-jocher Aug 13, 2022
7c93f2c
Refactor into /classify dir
glenn-jocher Aug 14, 2022
ea8729b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2022
0173fdf
comma fix
glenn-jocher Aug 14, 2022
30e46ed
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2022
1d961a4
reset defaults
glenn-jocher Aug 14, 2022
9f666e3
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 14, 2022
52b73c7
reset defaults
glenn-jocher Aug 14, 2022
d97848e
fix gpu predict
glenn-jocher Aug 14, 2022
17564e1
warmup
glenn-jocher Aug 14, 2022
f1f71c9
ema half fix
glenn-jocher Aug 14, 2022
26d3a1e
spacing
glenn-jocher Aug 14, 2022
0e9ba3c
remove data
glenn-jocher Aug 14, 2022
4a982ae
remove cache
glenn-jocher Aug 14, 2022
dada286
remove denormalize
glenn-jocher Aug 14, 2022
03e7a97
save run settings
glenn-jocher Aug 14, 2022
ef20d65
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2022
bc969a7
verbose false on initial plots
glenn-jocher Aug 14, 2022
4d03b79
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 14, 2022
fbff212
new save_yaml() function
glenn-jocher Aug 14, 2022
59e1300
Update ci-testing.yml
glenn-jocher Aug 14, 2022
61f635f
Path(data) CI fix
glenn-jocher Aug 14, 2022
e8ed7cd
Separate classification CI
glenn-jocher Aug 14, 2022
379a936
fix val
glenn-jocher Aug 14, 2022
f81686d
fix val
glenn-jocher Aug 14, 2022
3dd6ef3
fix val
glenn-jocher Aug 14, 2022
e378210
smartCrossEntropyLoss
glenn-jocher Aug 14, 2022
56c5b8e
skip validation on hub load
glenn-jocher Aug 14, 2022
0e5720b
autodownload with working dir root
glenn-jocher Aug 14, 2022
22b9d4b
str(data)
glenn-jocher Aug 14, 2022
986390d
Dataset usage example
glenn-jocher Aug 14, 2022
b456f51
im_show normalize
glenn-jocher Aug 14, 2022
b7f3016
im_show normalize
glenn-jocher Aug 14, 2022
e663ff4
add imagenet simple names to multibackend
glenn-jocher Aug 14, 2022
cb13e7f
Add validation speeds
glenn-jocher Aug 14, 2022
92fd072
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2022
d864cda
24-space names
glenn-jocher Aug 14, 2022
eafe847
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 14, 2022
4020446
Update bash scripts
glenn-jocher Aug 14, 2022
044022b
Update permissions
glenn-jocher Aug 14, 2022
3d2d112
Add bash script arguments
glenn-jocher Aug 14, 2022
b41070b
Merge branch 'master' into classifier
glenn-jocher Aug 14, 2022
13ec336
remove verbose
glenn-jocher Aug 14, 2022
95090dc
TRT data fix
glenn-jocher Aug 15, 2022
e749931
names generator fix
glenn-jocher Aug 15, 2022
3e6b07a
optimize if names
glenn-jocher Aug 15, 2022
5963a25
update usage
glenn-jocher Aug 15, 2022
d35d9f0
Add local loading
glenn-jocher Aug 15, 2022
cb8ddc0
Verbose=False
glenn-jocher Aug 15, 2022
5a5bd4e
update names printing
glenn-jocher Aug 15, 2022
b3bd5a1
Add Usage examples
glenn-jocher Aug 15, 2022
4086b0f
Add Usage examples
glenn-jocher Aug 15, 2022
6d2ce08
Add Usage examples
glenn-jocher Aug 15, 2022
d212511
Add Usage examples
glenn-jocher Aug 15, 2022
3951615
Merge master
glenn-jocher Aug 15, 2022
1abaf42
named_children
glenn-jocher Aug 15, 2022
db2f7b3
reshape_classifier_outputs
glenn-jocher Aug 15, 2022
5b2070b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 15, 2022
1338c6d
update
glenn-jocher Aug 15, 2022
ab97b5a
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 15, 2022
b088d52
update
glenn-jocher Aug 15, 2022
6730731
fix CI
glenn-jocher Aug 15, 2022
fc3b0bb
fix incorrect class substitution
glenn-jocher Aug 15, 2022
0ff0ec2
fix incorrect class substitution
glenn-jocher Aug 15, 2022
72e5607
remove denormalize
glenn-jocher Aug 15, 2022
bf1dae5
ravel fix
glenn-jocher Aug 15, 2022
5f64ebd
cleanup
glenn-jocher Aug 15, 2022
bdee2e4
update opt file printing
glenn-jocher Aug 15, 2022
fd388d6
update opt file printing
glenn-jocher Aug 15, 2022
1a307b8
update defaults
glenn-jocher Aug 15, 2022
4ab5ee6
Merge branch 'master' into classifier
glenn-jocher Aug 15, 2022
6a347f3
add opt to checkpoint
glenn-jocher Aug 15, 2022
48da61b
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 15, 2022
26dfbe3
Add warning
glenn-jocher Aug 16, 2022
8ee42ff
Merge branch 'master' into classifier
glenn-jocher Aug 16, 2022
b6d3018
Add comment
glenn-jocher Aug 16, 2022
0c97910
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 16, 2022
cc60aef
Merge branch 'master' into classifier
glenn-jocher Aug 16, 2022
04e84d6
plot half bug fix
glenn-jocher Aug 16, 2022
9d9a2f1
Use NotImplementedError
glenn-jocher Aug 16, 2022
44584ce
fix export shape report
glenn-jocher Aug 16, 2022
b26129b
Fix TRT load
glenn-jocher Aug 16, 2022
7449066
cleanup CI
glenn-jocher Aug 16, 2022
c0f0b7b
profile comment
glenn-jocher Aug 16, 2022
01806e3
CI fix
glenn-jocher Aug 16, 2022
1d867fd
Add cls models
glenn-jocher Aug 16, 2022
4b75256
Merge branch 'master' into classifier
glenn-jocher Aug 16, 2022
ebb99af
avoid inplace error
glenn-jocher Aug 16, 2022
3652de4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 16, 2022
105c73a
Merge branch 'master' into classifier
glenn-jocher Aug 16, 2022
d1c84ae
Fix usage examples
glenn-jocher Aug 16, 2022
c99c051
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 16, 2022
706ff96
Update README
glenn-jocher Aug 16, 2022
6f4a1bb
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 16, 2022
b5f8748
Update README
glenn-jocher Aug 16, 2022
ca01d76
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 16, 2022
0a8f489
Update README
glenn-jocher Aug 16, 2022
33ae017
Update README
glenn-jocher Aug 16, 2022
7c494aa
Update README
glenn-jocher Aug 16, 2022
dcdc38b
Update README
glenn-jocher Aug 16, 2022
85289d4
Update README
glenn-jocher Aug 16, 2022
ef63af1
Update README
glenn-jocher Aug 17, 2022
105184c
Update README
glenn-jocher Aug 17, 2022
47bbaee
Update README
glenn-jocher Aug 17, 2022
4719685
Update README
glenn-jocher Aug 17, 2022
55d85a6
Update README
glenn-jocher Aug 17, 2022
e8ce124
Update README
glenn-jocher Aug 17, 2022
78e1bf9
Update README
glenn-jocher Aug 17, 2022
d0a3e70
Update README
glenn-jocher Aug 17, 2022
4b398df
Update README
glenn-jocher Aug 17, 2022
e90cc95
Merge branch 'master' into classifier
glenn-jocher Aug 17, 2022
9a43979
Update README
glenn-jocher Aug 17, 2022
4b231d4
Merge remote-tracking branch 'origin/classifier' into classifier
glenn-jocher Aug 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,19 @@ We are super excited about our first-ever Ultralytics YOLOv5 🚀 EXPORT Competi

</details>

### Classification Checkpoints

| Model | size<br><sup>(pixels) | accuracy<br><sup>top1 | accuracy<br><sup>top5 | Train time<br><sup>90 epochs<br>(hours) | Speed<br><sup>CPU<br>(ms) | Speed<br><sup>V100<br>(ms) | params<br><sup>(M) | FLOPs<br><sup>@640 (B) |
|----------------------------------------------------------------------------------------------------|-----------------------|-----------------------|-----------------------|-----------------------------------------|---------------------------|----------------------------|--------------------|------------------------|
| [ResNet50](https://github.com/ultralytics/yolov5/releases/download/v6.2/resnet50.pt) | 224 | 76.8 | 93.4 | 11:10 | 61.8 | 9.2 | 25.6 | 8.3 |
| [EfficientNet_b0](https://github.com/ultralytics/yolov5/releases/download/v6.2/efficientnet_b0.pt) | 224 | 75.1 | 92.4 | 13:03 | 31.8 | 11.2 | 5.3 | 0.8 |
| [YOLOv5n-cls](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5n-cls.pt) | 224 | 64.6 | 85.4 | 7:59 | 8.0 | 3.9 | 2.5 | 0.4 |
| [YOLOv5s-cls](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5s-cls.pt) | 224 | 71.5 | 90.2 | 8:09 | 14.5 | 4.6 | 5.5 | 1.3 |
| [YOLOv5m-cls](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5m-cls.pt) | 224 | 75.9 | 92.9 | 10:06 | 30.1 | 6.3 | 13.0 | 3.8 |
| [YOLOv5l-cls](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5l-cls.pt) | 224 | 78.0 | 94.0 | 11:56 | 55.4 | 8.3 | 26.6 | 8.4 |
| [YOLOv5x-cls](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5x-cls.pt) | 224 | 78.9 | 94.4 | 15:04 | 96.5 | 10.1 | 48.1 | 15.9 |


Copy link
Contributor

@AyushExel AyushExel Aug 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glenn-jocher I think you're already planning to make this section collapsible right?
How about this structure instead:

  • [head1] Classification:
    [code] Example command for classification training and inference
    • [Collapsible head2] Classification Checkpoints

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the current README content needs updating. I'll work on that a little later. I've refactored classification into /classify now, will add classification CI today.

Screenshot 2022-08-14 at 13 29 38

## <div align="center">Contribute</div>

We love your input! We want to make contributing to YOLOv5 as easy and transparent as possible. Please see our [Contributing Guide](CONTRIBUTING.md) to get started, and fill out the [YOLOv5 Survey](https://ultralytics.com/survey?utm_source=github&utm_medium=social&utm_campaign=Survey) to send us feedback on your experiences. Thank you to all our contributors!
Expand Down
420 changes: 420 additions & 0 deletions classifier.py

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions data/scripts/get_imagenet.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# Download ILSVRC2012 ImageNet dataset https://image-net.org
# Example usage: bash data/scripts/get_imagenet.sh
# parent
# ├── yolov5
# └── datasets
# └── imagenet ← downloads here

# Download
d='../datasets/imagenet' # unzip directory
mkdir -p $d && cd $d
wget https://image-net.org/data/ILSVRC/2012/ILSVRC2012_img_val.tar # 6.3G, 50000 images
wget https://image-net.org/data/ILSVRC/2012/ILSVRC2012_img_train.tar # 138G, 1281167 images

# Extract train
mkdir train && mv ILSVRC2012_img_train.tar train/ && cd train
tar -xvf ILSVRC2012_img_train.tar && rm -f ILSVRC2012_img_train.tar
find . -name "*.tar" | while read NAME; do
mkdir -p "${NAME%.tar}"
tar -xvf "${NAME}" -C "${NAME%.tar}"
rm -f "${NAME}"
done
cd ..

# Extract val and move images into subdirectories
mkdir val && mv ILSVRC2012_img_val.tar val/ && cd val && tar -xvf ILSVRC2012_img_val.tar
wget -qO- https://github.com/raw/soumith/imagenetloader.torch/master/valprep.sh | bash

# Delete corrupted image (optional: PNG under JPEG name that may cause dataloaders to fail)
# rm train/n04266014/n04266014_10835.JPEG

# TFRecords (optional)
# wget https://github.com/raw/tensorflow/models/master/research/slim/datasets/imagenet_lsvrc_2015_synsets.txt
2 changes: 0 additions & 2 deletions export.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,11 +495,9 @@ def run(
assert device.type != 'cpu' or coreml, '--half only compatible with GPU export, i.e. use --device 0'
assert not dynamic, '--half not compatible with --dynamic, i.e. use either --half or --dynamic but not both'
model = attempt_load(weights, device=device, inplace=True, fuse=True) # load FP32 model
nc, names = model.nc, model.names # number of classes, class names

# Checks
imgsz *= 2 if len(imgsz) == 1 else 1 # expand
assert nc == len(names), f'Model class count {nc} != len(names) {len(names)}'
if optimize:
assert device.type == 'cpu', '--optimize not compatible with cuda devices, i.e. use --device cpu'

Expand Down
21 changes: 13 additions & 8 deletions models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ def __init__(self, weights='yolov5s.pt', device=torch.device('cpu'), dnn=False,
w = str(weights[0] if isinstance(weights, list) else weights)
pt, jit, onnx, xml, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs = self.model_type(w) # get backend
w = attempt_download(w) # download if not local
fp16 &= (pt or jit or onnx or engine) and device.type != 'cpu' # FP16
cuda = torch.cuda.is_available() and device.type != 'cpu'
fp16 &= (pt or jit or onnx or engine) and cuda # FP16
stride, names = 32, [f'class{i}' for i in range(1000)] # assign defaults
if data: # assign class names (optional)
with open(data, errors='ignore') as f:
Expand All @@ -350,7 +351,6 @@ def __init__(self, weights='yolov5s.pt', device=torch.device('cpu'), dnn=False,
net = cv2.dnn.readNetFromONNX(w)
elif onnx: # ONNX Runtime
LOGGER.info(f'Loading {w} for ONNX Runtime inference...')
cuda = torch.cuda.is_available()
check_requirements(('onnx', 'onnxruntime-gpu' if cuda else 'onnxruntime'))
import onnxruntime
providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if cuda else ['CPUExecutionProvider']
Expand Down Expand Up @@ -457,7 +457,9 @@ def forward(self, im, augment=False, visualize=False, val=False):
im = im.half() # to FP16

if self.pt: # PyTorch
y = self.model(im, augment=augment, visualize=visualize)[0]
y = self.model(im, augment=augment, visualize=visualize) if augment or visualize else self.model(im)
if isinstance(y, tuple):
y = y[0]
elif self.jit: # TorchScript
y = self.model(im)[0]
elif self.dnn: # ONNX OpenCV DNN
Expand Down Expand Up @@ -753,10 +755,13 @@ class Classify(nn.Module):
# Classification head, i.e. x(b,c1,20,20) to x(b,c2)
def __init__(self, c1, c2, k=1, s=1, p=None, g=1): # ch_in, ch_out, kernel, stride, padding, groups
super().__init__()
self.aap = nn.AdaptiveAvgPool2d(1) # to x(b,c1,1,1)
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g) # to x(b,c2,1,1)
self.flat = nn.Flatten()
c_ = 1280 # efficientnet_b0 size
self.conv = Conv(c1, c_, k, s, autopad(k, p), g)
self.pool = nn.AdaptiveAvgPool2d(1) # to x(b,c_,1,1)
self.drop = nn.Dropout(p=0.0, inplace=True)
self.linear = nn.Linear(c_, c2) # to x(b,c2)

def forward(self, x):
z = torch.cat([self.aap(y) for y in (x if isinstance(x, list) else [x])], 1) # cat if list
return self.flat(self.conv(z)) # flatten to x(b,c2)
if isinstance(x, list):
x = torch.cat(x, 1)
return self.linear(self.drop(self.pool(self.conv(x)).flatten(1)))
11 changes: 8 additions & 3 deletions models/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ def attempt_load(weights, device=None, inplace=True, fuse=True):
for w in weights if isinstance(weights, list) else [weights]:
ckpt = torch.load(attempt_download(w), map_location='cpu') # load
ckpt = (ckpt.get('ema') or ckpt['model']).to(device).float() # FP32 model
model.append(ckpt.fuse().eval() if fuse else ckpt.eval()) # fused or un-fused model in eval mode
if not hasattr(ckpt, 'stride'):
ckpt.stride = torch.tensor([32.]) # compatibility update for ResNet etc.
model.append(ckpt.fuse().eval() if fuse and hasattr(ckpt, 'fuse') else ckpt.eval()) # model in eval mode

# Compatibility updates
for m in model.modules():
Expand All @@ -92,11 +94,14 @@ def attempt_load(weights, device=None, inplace=True, fuse=True):
elif t is nn.Upsample and not hasattr(m, 'recompute_scale_factor'):
m.recompute_scale_factor = None # torch 1.11.0 compatibility

# Return model
if len(model) == 1:
return model[-1] # return model
return model[-1]

# Return detection ensemble
print(f'Ensemble created with {weights}\n')
for k in 'names', 'nc', 'yaml':
setattr(model, k, getattr(model[0], k))
model.stride = model[torch.argmax(torch.tensor([m.stride.max() for m in model])).int()].stride # max stride
assert all(model[0].nc == m.nc for m in model), f'Models have different class counts: {[m.nc for m in model]}'
return model # return ensemble
return model
145 changes: 84 additions & 61 deletions models/yolo.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,64 @@ def _make_grid(self, nx=20, ny=20, i=0, torch_1_10=check_version(torch.__version
return grid, anchor_grid


class Model(nn.Module):
# YOLOv5 model
class BaseModel(nn.Module):
# YOLOv5 base model
def forward(self, x, profile=False, visualize=False):
return self._forward_once(x, profile, visualize) # single-scale inference, train

def _forward_once(self, x, profile=False, visualize=False):
y, dt = [], [] # outputs
for m in self.model:
if m.f != -1: # if not from previous layer
x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f] # from earlier layers
if profile:
self._profile_one_layer(m, x, dt)
x = m(x) # run
y.append(x if m.i in self.save else None) # save output
if visualize:
feature_visualization(x, m.type, m.i, save_dir=visualize)
return x

def _profile_one_layer(self, m, x, dt):
c = m == self.model[-1] # is final layer, copy input as inplace fix
o = thop.profile(m, inputs=(x.copy() if c else x,), verbose=False)[0] / 1E9 * 2 if thop else 0 # FLOPs
t = time_sync()
for _ in range(10):
m(x.copy() if c else x)
dt.append((time_sync() - t) * 100)
if m == self.model[0]:
LOGGER.info(f"{'time (ms)':>10s} {'GFLOPs':>10s} {'params':>10s} module")
LOGGER.info(f'{dt[-1]:10.2f} {o:10.2f} {m.np:10.0f} {m.type}')
if c:
LOGGER.info(f"{sum(dt):10.2f} {'-':>10s} {'-':>10s} Total")

def fuse(self): # fuse model Conv2d() + BatchNorm2d() layers
LOGGER.info('Fusing layers... ')
for m in self.model.modules():
if isinstance(m, (Conv, DWConv)) and hasattr(m, 'bn'):
m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
delattr(m, 'bn') # remove batchnorm
m.forward = m.forward_fuse # update forward
self.info()
return self

def info(self, verbose=False, img_size=640): # print model information
model_info(self, verbose, img_size)

def _apply(self, fn):
# Apply to(), cpu(), cuda(), half() to model tensors that are not parameters or registered buffers
self = super()._apply(fn)
m = self.model[-1] # Detect()
if isinstance(m, Detect):
m.stride = fn(m.stride)
m.grid = list(map(fn, m.grid))
if isinstance(m.anchor_grid, list):
m.anchor_grid = list(map(fn, m.anchor_grid))
return self


class DetectionModel(BaseModel):
# YOLOv5 detection model
def __init__(self, cfg='yolov5s.yaml', ch=3, nc=None, anchors=None): # model, input channels, number of classes
super().__init__()
if isinstance(cfg, dict):
Expand Down Expand Up @@ -149,19 +205,6 @@ def _forward_augment(self, x):
y = self._clip_augmented(y) # clip augmented tails
return torch.cat(y, 1), None # augmented inference, train

def _forward_once(self, x, profile=False, visualize=False):
y, dt = [], [] # outputs
for m in self.model:
if m.f != -1: # if not from previous layer
x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f] # from earlier layers
if profile:
self._profile_one_layer(m, x, dt)
x = m(x) # run
y.append(x if m.i in self.save else None) # save output
if visualize:
feature_visualization(x, m.type, m.i, save_dir=visualize)
return x

def _descale_pred(self, p, flips, scale, img_size):
# de-scale predictions following augmented inference (inverse operation)
if self.inplace:
Expand Down Expand Up @@ -190,19 +233,6 @@ def _clip_augmented(self, y):
y[-1] = y[-1][:, i:] # small
return y

def _profile_one_layer(self, m, x, dt):
c = isinstance(m, Detect) # is final layer, copy input as inplace fix
o = thop.profile(m, inputs=(x.copy() if c else x,), verbose=False)[0] / 1E9 * 2 if thop else 0 # FLOPs
t = time_sync()
for _ in range(10):
m(x.copy() if c else x)
dt.append((time_sync() - t) * 100)
if m == self.model[0]:
LOGGER.info(f"{'time (ms)':>10s} {'GFLOPs':>10s} {'params':>10s} module")
LOGGER.info(f'{dt[-1]:10.2f} {o:10.2f} {m.np:10.0f} {m.type}')
if c:
LOGGER.info(f"{sum(dt):10.2f} {'-':>10s} {'-':>10s} Total")

def _initialize_biases(self, cf=None): # initialize biases into Detect(), cf is class frequency
# https://arxiv.org/abs/1708.02002 section 3.3
# cf = torch.bincount(torch.tensor(np.concatenate(dataset.labels, 0)[:, 0]).long(), minlength=nc) + 1.
Expand All @@ -213,41 +243,34 @@ def _initialize_biases(self, cf=None): # initialize biases into Detect(), cf is
b[:, 5:] += math.log(0.6 / (m.nc - 0.999999)) if cf is None else torch.log(cf / cf.sum()) # cls
mi.bias = torch.nn.Parameter(b.view(-1), requires_grad=True)

def _print_biases(self):
m = self.model[-1] # Detect() module
for mi in m.m: # from
b = mi.bias.detach().view(m.na, -1).T # conv.bias(255) to (3,85)
LOGGER.info(
('%6g Conv2d.bias:' + '%10.3g' * 6) % (mi.weight.shape[1], *b[:5].mean(1).tolist(), b[5:].mean()))

# def _print_weights(self):
# for m in self.model.modules():
# if type(m) is Bottleneck:
# LOGGER.info('%10.3g' % (m.w.detach().sigmoid() * 2)) # shortcut weights
Model = DetectionModel # retain YOLOv5 'Model' class for backwards compatibility

def fuse(self): # fuse model Conv2d() + BatchNorm2d() layers
LOGGER.info('Fusing layers... ')
for m in self.model.modules():
if isinstance(m, (Conv, DWConv)) and hasattr(m, 'bn'):
m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
delattr(m, 'bn') # remove batchnorm
m.forward = m.forward_fuse # update forward
self.info()
return self

def info(self, verbose=False, img_size=640): # print model information
model_info(self, verbose, img_size)

def _apply(self, fn):
# Apply to(), cpu(), cuda(), half() to model tensors that are not parameters or registered buffers
self = super()._apply(fn)
m = self.model[-1] # Detect()
if isinstance(m, Detect):
m.stride = fn(m.stride)
m.grid = list(map(fn, m.grid))
if isinstance(m.anchor_grid, list):
m.anchor_grid = list(map(fn, m.anchor_grid))
return self
class ClassificationModel(BaseModel):
# YOLOv5 classification model
def __init__(self, cfg=None, model=None, nc=1000, cutoff=10): # yaml, model, number of classes, cutoff index
super().__init__()
self._from_detection_model(model, nc, cutoff) if model is not None else self._from_yaml(cfg)

def _from_detection_model(self, model, nc=1000, cutoff=10):
# Create a YOLOv5 classification model from a YOLOv5 detection model
if isinstance(model, DetectMultiBackend):
model = model.model # unwrap DetectMultiBackend
model.model = model.model[:cutoff] # backbone
m = model.model[-1] # last layer
ch = m.conv.in_channels if hasattr(m, 'conv') else m.cv1.conv.in_channels # ch into module
c = Classify(ch, nc) # Classify()
c.i, c.f, c.type = m.i, m.f, 'models.common.Classify' # index, from, type
model.model[-1] = c # replace
self.model = model.model
self.stride = model.stride
self.save = []
self.nc = nc

def _from_yaml(self, cfg):
# Create a YOLOv5 classification model from a *.yaml file
self.model = None


def parse_model(d, ch): # model_dict, input_channels(3)
Expand Down Expand Up @@ -321,7 +344,7 @@ def parse_model(d, ch): # model_dict, input_channels(3)

# Options
if opt.line_profile: # profile layer by layer
_ = model(im, profile=True)
model(im, profile=True)

elif opt.profile: # profile forward-backward
results = profile(input=im, ops=[model], n=3)
Expand Down
2 changes: 1 addition & 1 deletion train.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def main(opt, callbacks=Callbacks()):
if RANK in {-1, 0}:
print_args(vars(opt))
check_git_status()
check_requirements(exclude=['thop'])
check_requirements()

# Resume
if opt.resume and not (check_wandb_resume(opt) or opt.evolve): # resume from specified or most recent last.pt
Expand Down
Loading