diff --git a/.gitignore b/.gitignore index 0c8b387..d8c5f55 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,4 @@ __pycache__ .vscode csrc/eval_cylib/build/ logs/ -.ipynb_checkpoints -tests/ \ No newline at end of file +.ipynb_checkpoints \ No newline at end of file diff --git a/README.md b/README.md index 595e201..28021d7 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,21 @@ # ReID_baseline -**The results in CUHK03 is wrong becuase I use the same evaluation protocol with market1501 and duke. I will fix this later. You can use the right evaluation protocol to get accurate result.** -Baseline model (with bottleneck) for person ReID (using softmax and triplet loss). +A strong baseline (state-of-the-art) for person re-identification. We support - [x] easy dataset preparation - [x] end-to-end training and evaluation +- [ ] multi-GPU distributed training +- [ ] fast training speed with fp16 +- [ ] support both image and video reid +- [x] multi-dataset training +- [x] cross-dataset evaluation - [x] high modular management +- [x] state-of-the-art performance with simple model +- [ ] high efficient backbone +- [ ] advanced training techniques +- [ ] various loss functions +- [ ] visualization tools ## Get Started The designed architecture follows this guide [PyTorch-Project-Template](https://github.com/L1aoXingyu/PyTorch-Project-Template), you can check each folder's purpose by yourself. diff --git a/datasets b/datasets index 306a491..30f9f15 120000 --- a/datasets +++ b/datasets @@ -1 +1 @@ -/export/home/datasets/ \ No newline at end of file +../datasets/ \ No newline at end of file diff --git a/engine/trainer.py b/engine/trainer.py index 93b12a5..0cc8ded 100644 --- a/engine/trainer.py +++ b/engine/trainer.py @@ -20,7 +20,7 @@ class TrackValue(Callback): total_iter: int def on_epoch_end(self, epoch, smooth_loss, **kwargs): - self.logger.info('Epoch {}[Iter {}], loss: {:.4f}'.format(epoch, self.total_iter, smooth_loss.item())) + self.logger.info(f'Epoch {epoch}[Iter {self.total_iter}], loss: {smooth_loss.item():.4f}') @dataclass @@ -76,10 +76,10 @@ class TestModel(LearnerCallback): distmat.addmm_(1, -2, qf, gf.t()) distmat = to_np(distmat) cmc, mAP = evaluate(distmat, self.q_pids, self.g_pids, self.q_camids, self.g_camids) - self._logger.info("Test Results - Epoch: {}".format(epoch + 1)) - self._logger.info("mAP: {:.1%}".format(mAP)) + self._logger.info(f"Test Results - Epoch: {epoch+1}") + self._logger.info(f"mAP: {mAP:.1%}") for r in [1, 5, 10]: - self._logger.info("CMC curve, Rank-{:<3}:{:.1%}".format(r, cmc[r - 1])) + self._logger.info(f"CMC curve, Rank-{r:<3}:{cmc[r-1]:.1%}") self.learn.save("model_{}".format(epoch)) diff --git a/scripts/debug.sh b/scripts/debug.sh deleted file mode 100644 index 938743f..0000000 --- a/scripts/debug.sh +++ /dev/null @@ -1,8 +0,0 @@ -gpu=2 - -CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \ -DATASETS.NAMES '("market1501",)' \ -DATASETS.TEST_NAMES 'market1501' \ -INPUT.DO_LIGHTING 'True' \ -INPUT.MIXUP 'True' \ -OUTPUT_DIR 'logs/test' diff --git a/scripts/train_bj.sh b/scripts/train_bj.sh deleted file mode 100644 index d2fbd35..0000000 --- a/scripts/train_bj.sh +++ /dev/null @@ -1,21 +0,0 @@ -gpu=1 - -CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \ -DATASETS.NAMES '("market1501","duke","cuhk03","beijing")' \ -DATASETS.TEST_NAMES 'bj' \ -INPUT.DO_LIGHTING 'False' \ -OUTPUT_DIR 'logs/2019.8.14/bj/baseline' - -# CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \ -# DATASETS.NAMES '("market1501","duke","cuhk03","beijing")' \ -# DATASETS.TEST_NAMES 'bj' \ -# INPUT.DO_LIGHTING 'True' \ -# OUTPUT_DIR 'logs/2019.8.9/bj/lighting' - -# CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \ -# DATASETS.NAMES '("market1501","duke","cuhk03","beijing")' \ -# DATASETS.TEST_NAMES 'bj' \ -# MODEL.BACKBONE 'resnet50_ibn' \ -# MODEL.PRETRAIN_PATH '/export/home/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar' \ -# INPUT.DO_LIGHTING 'True' \ -# OUTPUT_DIR 'logs/2019.8.14/bj/lighting_ibn7_1' \ No newline at end of file diff --git a/scripts/train_market.sh b/scripts/train_market.sh index 2364599..d2a205e 100644 --- a/scripts/train_market.sh +++ b/scripts/train_market.sh @@ -3,10 +3,10 @@ gpu=0 CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \ DATASETS.NAMES '("market1501",)' \ DATASETS.TEST_NAMES 'market1501' \ -MODEL.BACKBONE 'resnet50_ibn' \ -MODEL.PRETRAIN_PATH '/export/home/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar' \ -INPUT.DO_LIGHTING 'True' \ -OUTPUT_DIR 'logs/2019.8.14/market/lighting_ibn_7_1' +MODEL.BACKBONE 'resnet50' \ +MODEL.PRETRAIN_PATH '/home/user01/.cache/torch/checkpoints/resnet50-19c8e357.pth' \ +INPUT.DO_LIGHTING 'False' \ +OUTPUT_DIR 'logs/2019.8.14/market/baseline' # CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \ # DATASETS.NAMES '("market1501",)' \ diff --git a/solver/__init__.py b/solver/__init__.py deleted file mode 100644 index 0925e56..0000000 --- a/solver/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# encoding: utf-8 -""" -@author: sherlock -@contact: sherlockliao01@gmail.com -""" - -from .adabound import * \ No newline at end of file diff --git a/solver/build.py b/solver/build.py deleted file mode 100644 index a6b0339..0000000 --- a/solver/build.py +++ /dev/null @@ -1,15 +0,0 @@ -# encoding: utf-8 -""" -@author: sherlock -@contact: sherlockliao01@gmail.com -""" - -from fastai.vision import * - - -def make_optimizer(cfg): - if cfg.SOLVER.OPTIMIZER_NAME == 'SGD': - opt = partial(getattr(torch.optim, cfg.SOLVER.OPTIMIZER_NAME), momentum=cfg.SOLVER.MOMENTUM) - else: - opt = partial(getattr(torch.optim, cfg.SOLVER.OPTIMIZER_NAME)) - return opt diff --git a/tools/train.py b/tools/train.py index 498de8b..e722b31 100644 --- a/tools/train.py +++ b/tools/train.py @@ -17,7 +17,6 @@ from engine.trainer import do_train from fastai.vision import * from layers import make_loss from modeling import build_model -from solver import * from utils.logger import setup_logger @@ -29,7 +28,7 @@ def train(cfg): # prepare model model = build_model(cfg, data_bunch.c) - opt_func = partial(torch.optim.Adam) + opt_fns = partial(getattr(torch.optim, cfg.SOLVER.OPTIMIZER_NAME)) def warmup_multistep(start: float, end: float, pct: float): warmup_factor = 1 @@ -41,9 +40,7 @@ def train(cfg): warmup_factor = cfg.SOLVER.WARMUP_FACTOR * (1 - alpha) + alpha return start * warmup_factor * gamma ** bisect_right(milestones, pct) - # lr = cfg.SOLVER.BASE_LR * (cfg.SOLVER.IMS_PER_BATCH // 64) - lr = cfg.SOLVER.BASE_LR - lr_sched = Scheduler(lr, cfg.SOLVER.MAX_EPOCHS, warmup_multistep) + lr_sched = Scheduler(cfg.SOLVER.BASE_LR, cfg.SOLVER.MAX_EPOCHS, warmup_multistep) loss_func = make_loss(cfg) @@ -52,7 +49,7 @@ def train(cfg): model, data_bunch, test_labels, - opt_func, + opt_fns, lr_sched, loss_func, num_query, @@ -89,6 +86,5 @@ def main(): train(cfg) - if __name__ == '__main__': main()