刚刚我成功训练了yolox_nano模型,并且成功预测,但是现在要训练yolox_nano的时候又出现了问题,我的环境配置如下文章所示:
https://blog.csdn.net/ELSA001/article/details/120918082?spm=1001.2014.3001.5501
我的训练命令如下:
python tools/train.py -f exps/example/yolox_voc/yolox_voc_nano.py -d 1 -b 4 -c weights/yolox_nano.pth
报错信息如下:
AttributeError: 'Exp' object has no attribute 'perspective'
报错图片如下:
完整报错信息如下:
2021-10-23 19:07:10 | ERROR | yolox.core.launch:98 - An error has been caught in function 'launch', process 'MainProcess' (53772), thread 'MainThread' (52004):
Traceback (most recent call last):
File "tools\train.py", line 125, in <module>
launch(
└ <function launch at 0x000001BC0A7A8550>
> File "e:\yolox\yolox\core\launch.py", line 98, in launch
main_func(*args)
│ └ (╒══════════════════╤════════════════════════════════════════════════════════════════════════════════════════════════════════...
└ <function main at 0x000001BC0C7DF0D0>
File "tools\train.py", line 110, in main
trainer.train()
│ └ <function Trainer.train at 0x000001BC0BB4FC10>
└ <yolox.core.trainer.Trainer object at 0x000001BC04BF0F10>
File "e:\yolox\yolox\core\trainer.py", line 70, in train
self.before_train()
│ └ <function Trainer.before_train at 0x000001BC0C7BC9D0>
└ <yolox.core.trainer.Trainer object at 0x000001BC04BF0F10>
File "e:\yolox\yolox\core\trainer.py", line 145, in before_train
self.train_loader = self.exp.get_data_loader(
│ │ │ └ <function Exp.get_data_loader at 0x000001BC0C7FE430>
│ │ └ ╒══════════════════╤═════════════════════════════════════════════════════════════════════════════════════════════════════════...
│ └ <yolox.core.trainer.Trainer object at 0x000001BC04BF0F10>
└ <yolox.core.trainer.Trainer object at 0x000001BC04BF0F10>
File "E:\YOLOX\exps/example/yolox_voc\yolox_voc_nano.py", line 90, in get_data_loader
perspective=self.perspective,
└ ╒══════════════════╤═════════════════════════════════════════════════════════════════════════════════════════════════════════...
AttributeError: 'Exp' object has no attribute 'perspective'
yolox_nano.pth是我在官网上面下载的,应该没事问题。
yolox_voc_nano.py文件如下:
# encoding: utf-8
import os
import torch
import torch.distributed as dist
import torch.nn as nn
from yolox.data import get_yolox_datadir
from yolox.exp import Exp as MyExp
class Exp(MyExp):
def __init__(self):
super(Exp, self).__init__()
self.num_classes = 1
self.warmup_epochs = 1
self.depth = 0.33
self.width = 0.25
self.input_size = (416, 416)
self.random_size = (10, 20)
self.mosaic_scale = (0.5, 1.5)
self.test_size = (416, 416)
self.mosaic_prob = 0.5
self.enable_mixup = False
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
def get_model(self, sublinear=False):
def init_yolo(M):
for m in M.modules():
if isinstance(m, nn.BatchNorm2d):
m.eps = 1e-3
m.momentum = 0.03
if "model" not in self.__dict__:
from yolox.models import YOLOX, YOLOPAFPN, YOLOXHead
in_channels = [256, 512, 1024]
# NANO model use depthwise = True, which is main difference.
backbone = YOLOPAFPN(self.depth, self.width, in_channels=in_channels, depthwise=True)
head = YOLOXHead(self.num_classes, self.width, in_channels=in_channels, depthwise=True)
self.model = YOLOX(backbone, head)
self.model.apply(init_yolo)
self.model.head.initialize_biases(1e-2)
return self.model
def get_data_loader(self, batch_size, is_distributed, no_aug=False, cache_img=False):
from yolox.data import (
VOCDetection,
TrainTransform,
YoloBatchSampler,
DataLoader,
InfiniteSampler,
MosaicDetection,
worker_init_reset_seed,
)
from yolox.utils import (
wait_for_the_master,
get_local_rank,
)
local_rank = get_local_rank()
with wait_for_the_master(local_rank):
dataset = VOCDetection(
data_dir=os.path.join(get_yolox_datadir(), "VOCdevkit"),
#image_sets=[('2007', 'trainval'), ('2012', 'trainval')],
image_sets=[('2007', 'trainval')],
img_size=self.input_size,
preproc=TrainTransform(
max_labels=50,
flip_prob=self.flip_prob,
hsv_prob=self.hsv_prob),
cache=cache_img,
)
dataset = MosaicDetection(
dataset,
mosaic=not no_aug,
img_size=self.input_size,
preproc=TrainTransform(
max_labels=120,
flip_prob=self.flip_prob,
hsv_prob=self.hsv_prob),
degrees=self.degrees,
translate=self.translate,
mosaic_scale=self.mosaic_scale,
mixup_scale=self.mixup_scale,
shear=self.shear,
perspective=self.perspective,
enable_mixup=self.enable_mixup,
mosaic_prob=self.mosaic_prob,
mixup_prob=self.mixup_prob,
)
self.dataset = dataset
if is_distributed:
batch_size = batch_size // dist.get_world_size()
sampler = InfiniteSampler(
len(self.dataset), seed=self.seed if self.seed else 0
)
batch_sampler = YoloBatchSampler(
sampler=sampler,
batch_size=batch_size,
drop_last=False,
mosaic=not no_aug,
)
dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
dataloader_kwargs["batch_sampler"] = batch_sampler
# Make sure each process has different random seed, especially for 'fork' method
dataloader_kwargs["worker_init_fn"] = worker_init_reset_seed
train_loader = DataLoader(self.dataset, **dataloader_kwargs)
return train_loader
def get_eval_loader(self, batch_size, is_distributed, testdev=False, legacy=False):
from yolox.data import VOCDetection, ValTransform
valdataset = VOCDetection(
data_dir=os.path.join(get_yolox_datadir(), "VOCdevkit"),
image_sets=[('2007', 'test')],
img_size=self.test_size,
preproc=ValTransform(legacy=legacy),
)
if is_distributed:
batch_size = batch_size // dist.get_world_size()
sampler = torch.utils.data.distributed.DistributedSampler(
valdataset, shuffle=False
)
else:
sampler = torch.utils.data.SequentialSampler(valdataset)
dataloader_kwargs = {
"num_workers": self.data_num_workers,
"pin_memory": True,
"sampler": sampler,
}
dataloader_kwargs["batch_size"] = batch_size
val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
return val_loader
def get_evaluator(self, batch_size, is_distributed, testdev=False, legacy=False):
from yolox.evaluators import VOCEvaluator
val_loader = self.get_eval_loader(batch_size, is_distributed, testdev, legacy)
evaluator = VOCEvaluator(
dataloader=val_loader,
img_size=self.test_size,
confthre=self.test_conf,
nmsthre=self.nmsthre,
num_classes=self.num_classes,
)
return evaluator