ultralytics 8.0.50
AMP check and YOLOv5u YAMLs (#1263)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Troy <wudashuo@vip.qq.com> Co-authored-by: Yonghye Kwon <developer.0hye@gmail.com> Co-authored-by: Ayush Chaurasia <ayush.chaurarsia@gmail.com> Co-authored-by: Laughing <61612323+Laughing-q@users.noreply.github.com> Co-authored-by: Huijae Lee <46982469+ZeroAct@users.noreply.github.com>
This commit is contained in:
@ -27,6 +27,10 @@ def check_class_names(names):
|
||||
if isinstance(names, dict):
|
||||
if not all(isinstance(k, int) for k in names.keys()): # convert string keys to int, i.e. '0' to 0
|
||||
names = {int(k): v for k, v in names.items()}
|
||||
n = len(names)
|
||||
if max(names.keys()) >= n:
|
||||
raise KeyError(f'{n}-class dataset requires class indices 0-{n - 1}, but you have invalid class indices '
|
||||
f'{min(names.keys())}-{max(names.keys())} defined in your dataset YAML.')
|
||||
if isinstance(names[0], str) and names[0].startswith('n0'): # imagenet class codes, i.e. 'n01440764'
|
||||
map = yaml_load(ROOT / 'datasets/ImageNet.yaml')['map'] # human-readable names
|
||||
names = {k: map[v] for k, v in names.items()}
|
||||
@ -35,12 +39,14 @@ def check_class_names(names):
|
||||
|
||||
class AutoBackend(nn.Module):
|
||||
|
||||
def _apply_default_class_names(self, data):
|
||||
with contextlib.suppress(Exception):
|
||||
return yaml_load(check_yaml(data))['names']
|
||||
return {i: f'class{i}' for i in range(999)} # return default if above errors
|
||||
|
||||
def __init__(self, weights='yolov8n.pt', device=torch.device('cpu'), dnn=False, data=None, fp16=False, fuse=True):
|
||||
def __init__(self,
|
||||
weights='yolov8n.pt',
|
||||
device=torch.device('cpu'),
|
||||
dnn=False,
|
||||
data=None,
|
||||
fp16=False,
|
||||
fuse=True,
|
||||
verbose=True):
|
||||
"""
|
||||
MultiBackend class for python inference on various platforms using Ultralytics YOLO.
|
||||
|
||||
@ -51,6 +57,7 @@ class AutoBackend(nn.Module):
|
||||
data (str), (Path): Additional data.yaml file for class names, optional
|
||||
fp16 (bool): If True, use half precision. Default: False
|
||||
fuse (bool): Whether to fuse the model or not. Default: True
|
||||
verbose (bool): Whether to run in verbose mode or not. Default: True
|
||||
|
||||
Supported formats and their naming conventions:
|
||||
| Format | Suffix |
|
||||
@ -83,7 +90,7 @@ class AutoBackend(nn.Module):
|
||||
# NOTE: special case: in-memory pytorch model
|
||||
if nn_module:
|
||||
model = weights.to(device)
|
||||
model = model.fuse() if fuse else model
|
||||
model = model.fuse(verbose=verbose) if fuse else model
|
||||
names = model.module.names if hasattr(model, 'module') else model.names # get class names
|
||||
stride = max(int(model.stride.max()), 32) # model stride
|
||||
model.half() if fp16 else model.float()
|
||||
@ -410,6 +417,12 @@ class AutoBackend(nn.Module):
|
||||
for _ in range(2 if self.jit else 1): #
|
||||
self.forward(im) # warmup
|
||||
|
||||
@staticmethod
|
||||
def _apply_default_class_names(data):
|
||||
with contextlib.suppress(Exception):
|
||||
return yaml_load(check_yaml(data))['names']
|
||||
return {i: f'class{i}' for i in range(999)} # return default if above errors
|
||||
|
||||
@staticmethod
|
||||
def _model_type(p='path/to/model.pt'):
|
||||
"""
|
||||
|
@ -8,9 +8,7 @@ import thop
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from ultralytics.nn.modules import (C1, C2, C3, C3TR, SPP, SPPF, Bottleneck, BottleneckCSP, C2f, C3Ghost, C3x, Classify,
|
||||
Concat, Conv, ConvTranspose, Detect, DWConv, DWConvTranspose2d, Ensemble, Focus,
|
||||
GhostBottleneck, GhostConv, Segment)
|
||||
from ultralytics.nn.modules import * # noqa: F403
|
||||
from ultralytics.yolo.utils import DEFAULT_CFG_DICT, DEFAULT_CFG_KEYS, LOGGER, RANK, colorstr, emojis, yaml_load
|
||||
from ultralytics.yolo.utils.checks import check_requirements, check_yaml
|
||||
from ultralytics.yolo.utils.torch_utils import (fuse_conv_and_bn, fuse_deconv_and_bn, initialize_weights,
|
||||
@ -87,7 +85,7 @@ class BaseModel(nn.Module):
|
||||
if c:
|
||||
LOGGER.info(f"{sum(dt):10.2f} {'-':>10s} {'-':>10s} Total")
|
||||
|
||||
def fuse(self):
|
||||
def fuse(self, verbose=True):
|
||||
"""
|
||||
Fuse the `Conv2d()` and `BatchNorm2d()` layers of the model into a single layer, in order to improve the
|
||||
computation efficiency.
|
||||
@ -105,7 +103,7 @@ class BaseModel(nn.Module):
|
||||
m.conv_transpose = fuse_deconv_and_bn(m.conv_transpose, m.bn)
|
||||
delattr(m, 'bn') # remove batchnorm
|
||||
m.forward = m.forward_fuse # update forward
|
||||
self.info()
|
||||
self.info(verbose=verbose)
|
||||
|
||||
return self
|
||||
|
||||
@ -130,7 +128,7 @@ class BaseModel(nn.Module):
|
||||
verbose (bool): if True, prints out the model information. Defaults to False
|
||||
imgsz (int): the size of the image that the model will be trained on. Defaults to 640
|
||||
"""
|
||||
model_info(self, verbose, imgsz)
|
||||
model_info(self, verbose=verbose, imgsz=imgsz)
|
||||
|
||||
def _apply(self, fn):
|
||||
"""
|
||||
@ -437,7 +435,7 @@ def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)
|
||||
ch = [ch]
|
||||
layers, save, c2 = [], [], ch[-1] # layers, savelist, ch out
|
||||
for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']): # from, number, module, args
|
||||
m = eval(m) if isinstance(m, str) else m # eval strings
|
||||
m = getattr(torch.nn, m[3:]) if 'nn.' in m else globals()[m] # get module
|
||||
for j, a in enumerate(args):
|
||||
# TODO: re-implement with eval() removal if possible
|
||||
# args[j] = (locals()[a] if a in locals() else ast.literal_eval(a)) if isinstance(a, str) else a
|
||||
|
Reference in New Issue
Block a user