Commit e92e37c5 authored by João Porto's avatar João Porto
Browse files

mudança nas configurações de execução

parent a8f4c291
# __compara_detectores_tf2
__autores__: Hemerson Pistori (pistori@ucdb.br)
__versao__: 1.0.0
__autores__: Hemerson Pistori (pistori@ucdb.br), Fabio Prestes (fpcrezende@gmail.com), Joao Vitor Porto (jvaporto@gmail.com)
__versao__: 2.0.0
Scripts e patches para facilitar a utilização do mmdetection
Scripts e patches para facilitar a instalação e utilização do MMDetection
### Instalação e dependências:
Testado no Ubuntu 20.04 com python 3.7.7
Leia o arquivo install.sh para ver o que é preciso instalar
Leia o arquivo install.sh para ver o que é preciso instalar, ou crie o ambiente e instale todas as dependencias usando o seguinte comando:
```shell
sh install.sh
```
Caso o script em si nao rode corretamente, rode cada linha de comando do script install.sh linha por linha.
Placa gráfica: GTX 1070
Driver nvidia: 450.66
......@@ -48,11 +52,13 @@ $ cd ../run
$ ./testa.sh
# Detecta os objetos em uma imagem
# Possivelmente depreciado em v2.0
$ cd ../run
$ ./detecta.sh caminho_para_arquivo_da_imagem
# Detecta os objetos em todas as imagens da pasta ./mmdetection/data/VOCdevkit/VOC2007/JPEGImages/
# Feche a janela da imagem para ver a próxima
# Possivelmente depreciado em v2.0
cd ../run
./detectaTodas.sh
......
......@@ -4,20 +4,13 @@
# Criando um ambiente conda específico para rodar o mmdetection
# estou usando esta versão do python pois não testei em outras
# (mas pode ser que funcione em outras)
conda create --name od_porto python=3.7 -y
conda create --name openmmlab python=3.7 -y
# Ativando o ambiente recém criado (confira para ver se ativou
# corretamente olhando para a linha de comando, deve começar
# a aparecer um (od) no lugar de (base) no prompt
conda activate od_porto
conda activate openmmlab
# Algumas coisas instalam com o conda mas outras precisam do pip
conda install pytorch torchvision torchaudio cudatoolkit=11.0 -c pytorch
# Se der erro na linha abaixo pode ter relação com a instalação do CUDA
# e da placa gráfica na máquina
pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu110/torch1.7.0/index.html
cd mmdetection
pip install -r requirements/build.txt
pip install -r requirements/optional.txt
pip install -r requirements/runtime.txt
pip install -r requirements/tests.txt
# openMim eh uma biblioteca do OpenMMLab para instalar todas a dependencias para seus projetos
pip install openmim
mim install mmdet
......@@ -29,6 +29,12 @@ def process_checkpoint(in_file, out_file):
# remove optimizer for smaller file size
if 'optimizer' in checkpoint:
del checkpoint['optimizer']
# remove ema state_dict
for key in list(checkpoint['state_dict']):
if key.startswith('ema_'):
checkpoint['state_dict'].pop(key)
# if it is necessary to remove some sensitive data in checkpoint['meta'],
# add the code here.
if torch.__version__ >= '1.6':
......
# dataset settings
dataset_type = 'CocoDataset'
data_root = 'data/coco1/'
img_norm_cfg = dict(mean=[154.04, 159.83, 181.41], std=[13.59, 17.70, 25.08], to_rgb=True)
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)#mean do coco
#mean=[154.04, 159.83, 181.41], std=[13.59, 17.70, 25.08], to_rgb=True) #mean de pupa
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
......@@ -31,18 +34,19 @@ data = dict(
workers_per_gpu=2,
train=dict(
type=dataset_type,
classes=('Male','Female'),
classes=("Female", "Male"),
ann_file=data_root + 'train/_annotations.coco.json',
img_prefix=data_root + 'train/',
pipeline=train_pipeline),
val=dict(
type=dataset_type,
classes=('Male','Female'),
classes=("Female", "Male"),
ann_file=data_root + 'valid/_annotations.coco.json',
img_prefix=data_root + 'valid/',
pipeline=test_pipeline),
test=dict(
type=dataset_type,
classes=("Female", "Male"),
ann_file=data_root + 'test/_annotations.coco.json',
img_prefix=data_root + 'test/',
pipeline=test_pipeline))
......
......@@ -8,4 +8,4 @@ lr_config = dict(
warmup_iters=500,
warmup_ratio=0.001,
step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=12)
runner = dict(type='EpochBasedRunner', max_epochs=500)
# Neste arquivo são definidos os vários hiperparâmetros do modelo.
# Atenção com o número de classes que pode mudar de um conjunto de
# dados para outro. Geralmente usa-se uma classe a mais por conta
# do fundo (background)
_base_ = [
'../_base_/models/faster_rcnn_r50_fpn.py', '../_base_/datasets/coco_detection.py',
'../_base_/default_runtime.py'
]
img_norm_cfg = dict(mean=[154.04, 159.83, 181.41], std=[13.59, 17.70, 25.08], to_rgb=True)
# TROQUE AQUI PELA QUANTIDADE DE CLASSES DO SEU PROBLEMA (UMA A MAIS PARA O FUNDO SE NECESSÁRIO)
model = dict(roi_head=dict(bbox_head=dict(num_classes=2)))
# optimizer
optimizer = dict(type='SGD', lr=0.001, momentum=0.9, weight_decay=0.0001)
#optimizer = dict(type='Adam', lr=0.001, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
# learning policy
# actual epoch = 3 * 3 = 9
lr_config = dict(policy='step', step=[3])
# runtime settings
total_epochs = 1000 # actual epoch = 4 * 3 = 12
# checkpoint saving configuration
checkpoint_config = dict(interval=250)
# Neste arquivo são definidos os vários hiperparâmetros do modelo.
# Atenção com o número de classes que pode mudar de um conjunto de
# dados para outro. Geralmente usa-se uma classe a mais por conta
# do fundo (background)
_base_ = [
'../_base_/models/faster_rcnn_r50_fpn.py', '../_base_/datasets/coco_detection.py',
'../_base_/default_runtime.py'
]
img_norm_cfg = dict(mean=[154.04, 159.83, 181.41], std=[13.59, 17.70, 25.08], to_rgb=True)
# TROQUE AQUI PELA QUANTIDADE DE CLASSES DO SEU PROBLEMA (UMA A MAIS PARA O FUNDO SE NECESSÁRIO)
model = dict(roi_head=dict(bbox_head=dict(num_classes=2)))
# optimizer
optimizer = dict(type='SGD', lr=0.001, momentum=0.9, weight_decay=0.0001)
#optimizer = dict(type='Adam', lr=0.001, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
# learning policy
# actual epoch = 3 * 3 = 9
lr_config = dict(policy='step', step=[3])
# runtime settings
total_epochs = 1000 # actual epoch = 4 * 3 = 12
# checkpoint saving configuration
checkpoint_config = dict(interval=250)
# Eu precisei mexer neste arquivo pois estou usando apenas o formato VOC2007
# e não o VOC2012. Estava dando um erro antes, por isso eu copio este
# arquivo para a estrutura do mmdetection antes de rodar
_base_ = [
'../_base_/models/faster_rcnn_r50_fpn.py', '../_base_/datasets/voc0712.py',
'../_base_/default_runtime.py'
]
model = dict(roi_head=dict(bbox_head=dict(num_classes=20)))
CLASSES = ('aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car',
'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike',
'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor')
# dataset settings
dataset_type = 'VOCDataset'
dataset_type = 'CocoDataset'
data_root = 'data/VOCdevkit/'
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
......@@ -40,19 +46,30 @@ data = dict(
times=3,
dataset=dict(
type=dataset_type,
ann_file=[
data_root + 'VOC2007/ImageSets/Main/trainval.txt'
],
img_prefix=[data_root + 'VOC2007/'],
pipeline=train_pipeline)),
ann_file='data/voc0712_trainval.json',
img_prefix='data/VOCdevkit',
pipeline=train_pipeline,
classes=CLASSES)),
val=dict(
type=dataset_type,
ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt',
img_prefix=data_root + 'VOC2007/',
pipeline=test_pipeline),
ann_file='data/voc07_test.json',
img_prefix='data/VOCdevkit',
pipeline=test_pipeline,
classes=CLASSES),
test=dict(
type=dataset_type,
ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt',
img_prefix=data_root + 'VOC2007/',
pipeline=test_pipeline))
evaluation = dict(interval=1, metric='mAP')
ann_file='data/voc07_test.json',
img_prefix='data/VOCdevkit',
pipeline=test_pipeline,
classes=CLASSES))
evaluation = dict(interval=1, metric='bbox')
# optimizer
optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
# learning policy
# actual epoch = 3 * 3 = 9
lr_config = dict(policy='step', step=[3])
# runtime settings
runner = dict(
type='EpochBasedRunner', max_epochs=4) # actual epoch = 4 * 3 = 12
_base_ = './faster_rcnn_r50_fpn_1x_coco.py'
model = dict(
backbone=dict(
depth=101,
init_cfg=dict(type='Pretrained',
checkpoint='torchvision://resnet101')))
_base_ = [
'../_base_/models/faster_rcnn_r50_fpn.py',
'../_base_/datasets/coco_detection.py',
'../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]
checkpoint_config = dict(interval=250)
......@@ -60,3 +60,7 @@ data = dict(
# optimizer
optimizer = dict(type='SGD', lr=2e-3, momentum=0.9, weight_decay=5e-4)
optimizer_config = dict(_delete_=True)
custom_hooks = [
dict(type='NumClassCheckHook'),
dict(type='CheckInvalidLossHook', interval=50, priority='VERY_LOW')
]
......@@ -73,3 +73,7 @@ data = dict(
# optimizer
optimizer = dict(type='SGD', lr=2e-3, momentum=0.9, weight_decay=5e-4)
optimizer_config = dict(_delete_=True)
custom_hooks = [
dict(type='NumClassCheckHook'),
dict(type='CheckInvalidLossHook', interval=50, priority='VERY_LOW')
]
......@@ -139,3 +139,7 @@ runner = dict(type='EpochBasedRunner', max_epochs=120)
# Avoid evaluation and saving weights too frequently
evaluation = dict(interval=5, metric='bbox')
checkpoint_config = dict(interval=5)
custom_hooks = [
dict(type='NumClassCheckHook'),
dict(type='CheckInvalidLossHook', interval=50, priority='VERY_LOW')
]
......@@ -62,7 +62,7 @@ for i in range(self.num_stages):
if rois[j].shape[0] > 0:
bbox_label = cls_score[j][:, :-1].argmax(dim=1)
refine_roi = self.bbox_head[i].regress_by_class(
rois[j], bbox_label[j], bbox_pred[j], img_metas[j])
rois[j], bbox_label, bbox_pred[j], img_metas[j])
refine_roi_list.append(refine_roi)
```
......
......@@ -59,6 +59,7 @@ python tools/deployment/pytorch2onnx.py \
- `--verify`: Determines whether to verify the correctness of an exported model. If not specified, it will be set to `False`.
- `--simplify`: Determines whether to simplify the exported ONNX model. If not specified, it will be set to `False`.
- `--cfg-options`: Override some settings in the used config file, the key-value pair in `xxx=yyy` format will be merged into config file.
- `--skip-postprocess`: Determines whether export model without post process. If not specified, it will be set to `False`. Notice: This is an experimental option. Only work for some single stage models. Users need to implement the post-process by themselves. We do not guarantee the correctness of the exported model.
Example:
......
......@@ -188,7 +188,7 @@ python tools/deployment/mmdet2torchserve.py ${CONFIG_FILE} ${CHECKPOINT_FILE} \
--model-name ${MODEL_NAME}
```
***Note**: ${MODEL_STORE} needs to be an absolute path to a folder.
**Note**: ${MODEL_STORE} needs to be an absolute path to a folder.
### 2. Build `mmdet-serve` docker image
......@@ -382,3 +382,48 @@ python tools/analysis_tools/eval_metric.py ${CONFIG} ${PKL_RESULTS} [-h] [--form
```shell
python tools/misc/print_config.py ${CONFIG} [-h] [--options ${OPTIONS [OPTIONS...]}]
```
## Hyper-parameter Optimization
### YOLO Anchor Optimization
`tools/analysis_tools/optimize_anchors.py` provides two method to optimize YOLO anchors.
One is k-means anchor cluster which refers from [darknet](https://github.com/AlexeyAB/darknet/blob/master/src/detector.c#L1421).
```shell
python tools/analysis_tools/optimize_anchors.py ${CONFIG} --algorithm k-means --input-shape ${INPUT_SHAPE [WIDTH HEIGHT]} --output-dir ${OUTPUT_DIR}
```
Another is using differential evolution to optimize anchors.
```shell
python tools/analysis_tools/optimize_anchors.py ${CONFIG} --algorithm differential_evolution --input-shape ${INPUT_SHAPE [WIDTH HEIGHT]} --output-dir ${OUTPUT_DIR}
```
E.g.,
```shell
python tools/analysis_tools/optimize_anchors.py configs/yolo/yolov3_d53_320_273e_coco.py --algorithm differential_evolution --input-shape 608 608 --device cuda --output-dir work_dirs
```
You will get:
```
loading annotations into memory...
Done (t=9.70s)
creating index...
index created!
2021-07-19 19:37:20,951 - mmdet - INFO - Collecting bboxes from annotation...
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 117266/117266, 15874.5 task/s, elapsed: 7s, ETA: 0s
2021-07-19 19:37:28,753 - mmdet - INFO - Collected 849902 bboxes.
differential_evolution step 1: f(x)= 0.506055
differential_evolution step 2: f(x)= 0.506055
......
differential_evolution step 489: f(x)= 0.386625
2021-07-19 19:46:40,775 - mmdet - INFO Anchor evolution finish. Average IOU: 0.6133754253387451
2021-07-19 19:46:40,776 - mmdet - INFO Anchor differential evolution result:[[10, 12], [15, 30], [32, 22], [29, 59], [61, 46], [57, 116], [112, 89], [154, 198], [349, 336]]
2021-07-19 19:46:40,798 - mmdet - INFO Result saved in work_dirs/anchor_optimize_result.json
```
# Neste arquivo são definidos os nomes das classes na hora de
# gerar as tabelas com os resultados das métricas. Além de
# trocar aqui, é preciso trocar as classes também em voc.py
import mmcv
def wider_face_classes():
return ['face']
# TROQUE AQUI PELAS CLASSES DO SEU PROBLEMA
def voc_classes():
return [
'Male', 'Female'
'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat',
'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person',
'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'
]
......@@ -68,7 +66,7 @@ def imagenet_vid_classes():
def coco_classes():
return [
'Male', 'Female'
'Female', 'Male'
]
......@@ -84,7 +82,7 @@ dataset_aliases = {
'imagenet_det': ['det', 'imagenet_det', 'ilsvrc_det'],
'imagenet_vid': ['vid', 'imagenet_vid', 'ilsvrc_vid'],
'coco': ['coco', 'mscoco', 'ms_coco'],
'wider_face': ['WIDERFaceDataset', 'wider_face', 'WDIERFace'],
'wider_face': ['WIDERFaceDataset', 'wider_face', 'WIDERFace'],
'cityscapes': ['cityscapes']
}
......
from .checkloss_hook import CheckInvalidLossHook
from .ema import ExpMomentumEMAHook, LinearMomentumEMAHook
from .sync_norm_hook import SyncNormHook
from .sync_random_size_hook import SyncRandomSizeHook
......@@ -6,5 +7,6 @@ from .yolox_mode_switch_hook import YOLOXModeSwitchHook
__all__ = [
'SyncRandomSizeHook', 'YOLOXModeSwitchHook', 'SyncNormHook',
'ExpMomentumEMAHook', 'LinearMomentumEMAHook', 'YOLOXLrUpdaterHook'
'ExpMomentumEMAHook', 'LinearMomentumEMAHook', 'YOLOXLrUpdaterHook',
'CheckInvalidLossHook'
]
import torch
from mmcv.runner.hooks import HOOKS, Hook
@HOOKS.register_module()
class CheckInvalidLossHook(Hook):
"""Check invalid loss hook.
This hook will regularly check whether the loss is valid
during training.
Args:
interval (int): Checking interval (every k iterations).
Default: 50.
"""
def __init__(self, interval=50):
self.interval = interval
def after_train_iter(self, runner):
if self.every_n_iters(runner, self.interval):
assert torch.isfinite(runner.outputs['loss']), \
runner.logger.info('loss become infinite or NaN!')
......@@ -2,35 +2,24 @@ import itertools
import logging
import os.path as osp
import tempfile
import warnings
from collections import OrderedDict
import mmcv
import numpy as np
from mmcv.utils import print_log
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
from terminaltables import AsciiTable
from mmdet.core import eval_recalls
from .api_wrappers import COCO, COCOeval
from .builder import DATASETS
from .custom import CustomDataset
try:
import pycocotools
if not hasattr(pycocotools, '__sphinx_mock__'): # for doc generation
assert pycocotools.__version__ >= '12.0.2'
except AssertionError:
raise AssertionError('Incompatible version of pycocotools is installed. '
'Run pip uninstall pycocotools first. Then run pip '
'install mmpycocotools to install open-mmlab forked '
'pycocotools.')
@DATASETS.register_module()
class CocoDataset(CustomDataset):
# TROQUE AQUI AS CLASSES
classes = ('Male','Female')
CLASSES = ('Male','Female')
def load_annotations(self, ann_file):
"""Load annotation from COCO style annotation file.
......@@ -43,14 +32,22 @@ class CocoDataset(CustomDataset):
"""
self.coco = COCO(ann_file)
# The order of returned `cat_ids` will not
# change with the order of the CLASSES
self.cat_ids = self.coco.get_cat_ids(cat_names=self.CLASSES)
self.cat2label = {cat_id: i for i, cat_id in enumerate(self.cat_ids)}
self.img_ids = self.coco.get_img_ids()
data_infos = []
total_ann_ids = []
for i in self.img_ids:
info = self.coco.load_imgs([i])[0]
info['filename'] = info['file_name']
data_infos.append(info)
ann_ids = self.coco.get_ann_ids(img_ids=[i])
total_ann_ids.extend(ann_ids)
assert len(set(total_ann_ids)) == len(
total_ann_ids), f"Annotation ids in '{ann_file}' are not unique!"
return data_infos
def get_ann_info(self, idx):
......@@ -60,7 +57,7 @@ class CocoDataset(CustomDataset):
idx (int): Index of data.
Returns:
dict: Annotation info of spec ified index.
dict: Annotation info of specified index.
"""
img_id = self.data_infos[idx]['id']
......@@ -421,10 +418,27 @@ class CocoDataset(CustomDataset):
print_log(log_msg, logger=logger)
continue
iou_type = 'bbox' if metric == 'proposal' else metric
if metric not in result_files:
raise KeyError(f'{metric} is not in results')
try:
cocoDt = cocoGt.loadRes(result_files[metric])
predictions = mmcv.load(result_files[metric])
if iou_type == 'segm':
# Refer to https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/coco.py#L331 # noqa
# When evaluating mask AP, if the results contain bbox,
# cocoapi will use the box area instead of the mask area
# for calculating the instance area. Though the overall AP
# is not affected, this leads to different
# small/medium/large mask AP results.
for x in predictions:
x.pop('bbox')
warnings.simplefilter('once')
warnings.warn(
'The key "bbox" is deleted for more accurate mask AP '
'of small/medium/large instances since v2.12.0. This '
'does not change the overall mAP calculation.',
UserWarning)
cocoDt = cocoGt.loadRes(predictions)
except IndexError:
print_log(
'The testing results of the whole dataset is empty.',
......@@ -432,7 +446,6 @@ class CocoDataset(CustomDataset):
level=logging.ERROR)
break
iou_type = 'bbox' if metric == 'proposal' else metric
cocoEval = COCOeval(cocoGt, cocoDt, iou_type)
cocoEval.params.catIds = self.cat_ids
cocoEval.params.imgIds = self.img_ids
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment