vita-group / abd-net Goto Github PK
View Code? Open in Web Editor NEW[ICCV 2019] "ABD-Net: Attentive but Diverse Person Re-Identification" https://arxiv.org/abs/1908.01114
License: MIT License
[ICCV 2019] "ABD-Net: Attentive but Diverse Person Re-Identification" https://arxiv.org/abs/1908.01114
License: MIT License
The file format of the downloaded pretrained model is tar, but I got an error when I opened it with the compression software.
I opened the file in text form and found the torch
word. So is the downloaded file in pth format, or did I make a mistake in downloading it?
downloaded file: market_final_best.pth.tar
md5: e306d943f6ddf837e5f5a619ccce8ee8
can we get the output images in a folder as we get by using torchreid framework?
hi, Your work is awesome! I have been doing some work recently, but the result of the baseline is very low. I see that your baseline (XE) has achieved a score of 91.5 / 77.4 on the market1501, Could you give me some guideance about the detail of your implement for baseline(XE). Following is my question.
Forgive me for not looking at your code in detail because I want to save time for deadlines
@hsfzxjy
I use the command in the our training guide
python train.py -s market1501 -t market1501
--flip-eval --eval-freq 10
--label-smooth
--criterion htri
--lambda-htri 0.1
--data-augment crop,random-erase
--margin 1.2
--train-batch-size 48
--height 384
--width 128
--optim adam
--lr 0.0003
--stepsize 20 40
--gpu-devices 0,1
--max-epoch 80
--save-dir log
--arch resnet50
--use-of
--abd-dan cam pam
--abd-np 2
--shallow-cam
--use-ow
But after training, the performance is poor:
Model size: 69.175 M
Loaded pretrained weights from 'log/checkpoint_ep80.pth.tar'
Evaluate only
Evaluating market1501 ...
Extracted features for query set, obtained 3368-by-3072 matrix
Extracted features for gallery set, obtained 15913-by-3072 matrix
==> BatchTime(s)/BatchSize(img): 0.190/100
Computing CMC and mAP
Results ----------
mAP: 72.77%
CMC curve
Rank-1 : 88.15%
Rank-5 : 95.01%
Rank-10 : 96.56%
Rank-20 : 97.71%
In branches , there are four sets [global, abd, dan, np]. Global and abd are default, but what is dan or np? I don't notice it in your paper, could you explain it for me, thank you !
Do you know what it is?thank you
I want to perform inference with pretrained models on a custom dataset, to obtain features. Which part of the code is for single test image inference and feature extraction? (To then perform similarity test with another image's feature?)
Thanks for your great work!
@hsfzxjy Can you provide the parameters to reproduce the results in different datasets, such as market1501, CUHK03, etc. ? Thanks!
I try to load the model "Market1501 best ABD-Net model" provided by you. However, I find the names and the number of parameters both are different from defined model. I hope you can help me. Thank you!
Hi,
Thanks for the awesome code. I am wondering what should I do if I want to train on my customized dataset. Do you have some suggestions? I guess I can follow the code within the dataset folder and write a similar one?
Thanks
Using Cython evaluation code as the backend
Traceback (most recent call last):
File "eval_acc.py", line 29, in
from torchreid.losses.wrapped_cross_entropy_loss import WrappedCrossEntropyLoss
ModuleNotFoundError: No module named 'torchreid.losses.wrapped_cross_entropy_loss'
Hi, I have a question when I run train. Something like multithreading or way of using lambda().And I do it in windows not Unbantu.
Error like this:
Evaluate only
Evaluating market1501 ...
warnings.warn("Cython evaluation is UNAVAILABLE, which is highly recommended")
Traceback (most recent call last):
File "D:/syh/ABD-Net-master/train.py", line 391, in
main()
File "D:/syh/ABD-Net-master/train.py", line 124, in main
distmat = test(model, queryloader, galleryloader, use_gpu, return_distmat=True)
File "D:/syh/ABD-Net-master/train.py", line 290, in test
enumerator = enumerate(zip(queryloader[0], queryloader[1]))
File "D:\CONDA\envs\py10\lib\site-packages\torch\utils\data\dataloader.py", line 278, in iter
return _MultiProcessingDataLoaderIter(self)
File "D:\CONDA\envs\py10\lib\site-packages\torch\utils\data\dataloader.py", line 682, in init
w.start()
File "D:\CONDA\envs\py10\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "D:\CONDA\envs\py10\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "D:\CONDA\envs\py10\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
File "D:\CONDA\envs\py10\lib\multiprocessing\popen_spawn_win32.py", line 65, in init
reduction.dump(process_obj, to_child)
File "D:\CONDA\envs\py10\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'build_transforms..'
And EOFError: Ran out of input!!!
CAN u help me!!thanks very much.Looking forward to your reply!
Hi,could you tell how did you visualize the attention map in two branches model with Grad-CAM?As far as I know,Grad-CAM script in repo“pytorch-cnn-visualizations” can just visualize the
model with only one branch.
resnet_best.py
from .tricks.feature_distilation import FeatureDistilationTrick
from .tricks.attention import AttentionModule
from .tricks.dropout import SimpleDropoutOptimizer
but I cat not find it?
Do you know what it is?thank you
For testing model performance, I download the pretrained model which you provide and modify the --load-weights.
However, the mAP and CMC are not so high.
Could you help me to find what's the problem.
My args.py followed by README_Training_and_Testing_Guides.md is here.
`parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
# ************************************************************
# Datasets (general)
# ************************************************************
parser.add_argument('--root', type=str, default='/dlwsdata2/scorpiolu/Re_ID',
help="root path to data directory")
parser.add_argument('-s', '--source-names', type=str, nargs='+', default=['market1501'],
help="source datasets (delimited by space)")
parser.add_argument('-t', '--target-names', type=str, nargs='+', default=['market1501'],
help="target datasets (delimited by space)")
parser.add_argument('-j', '--workers', default=4, type=int,
help="number of data loading workers (tips: 4 or 8 times number of gpus)")
parser.add_argument('--height', type=int, default=384,
help="height of an image")
parser.add_argument('--width', type=int, default=128,
help="width of an image")
parser.add_argument('--split-id', type=int, default=0,
help="split index (note: 0-based)")
parser.add_argument('--train-sampler', type=str, default='',
help="sampler for trainloader")
parser.add_argument('--data-augment', type=str, nargs='+', choices=['none', 'crop', 'random-erase', 'color-jitter', 'crop,random-erase', 'crop,color-jitter', 'crop,color-jitter,random-erase'], default='crop,random-erase')
# ************************************************************
# Video datasets
# ************************************************************
parser.add_argument('--seq-len', type=int, default=15,
help="number of images to sample in a tracklet")
parser.add_argument('--sample-method', type=str, default='evenly',
help="how to sample images from a tracklet")
parser.add_argument('--pool-tracklet-features', type=str, default='avg', choices=['avg', 'max'],
help="how to pool features over a tracklet (for video reid)")
# ************************************************************
# CUHK03-specific setting
# ************************************************************
parser.add_argument('--cuhk03-labeled', action='store_true',
help="use labeled images, if false, use detected images")
parser.add_argument('--cuhk03-classic-split', action='store_true',
help="use classic split by Li et al. CVPR'14")
parser.add_argument('--use-metric-cuhk03', action='store_true',
help="use cuhk03's metric for evaluation")
# ************************************************************
# Optimization options
# ************************************************************
parser.add_argument('--optim', type=str, default='adam',
help="optimization algorithm (see optimizers.py)")
parser.add_argument('--lr', default=0.0003, type=float,
help="initial learning rate")
parser.add_argument('--weight-decay', default=5e-04, type=float,
help="weight decay")
# sgd
parser.add_argument('--momentum', default=0.9, type=float,
help="momentum factor for sgd and rmsprop")
parser.add_argument('--sgd-dampening', default=0, type=float,
help="sgd's dampening for momentum")
parser.add_argument('--sgd-nesterov', action='store_true',
help="whether to enable sgd's Nesterov momentum")
# rmsprop
parser.add_argument('--rmsprop-alpha', default=0.99, type=float,
help="rmsprop's smoothing constant")
# adam/amsgrad
parser.add_argument('--adam-beta1', default=0.9, type=float,
help="exponential decay rate for adam's first moment")
parser.add_argument('--adam-beta2', default=0.999, type=float,
help="exponential decay rate for adam's second moment")
# ************************************************************
# Training hyperparameters
# ************************************************************
parser.add_argument('--max-epoch', default=60, type=int,
help="maximum epochs to run")
parser.add_argument('--start-epoch', default=0, type=int,
help="manual epoch number (useful when restart)")
parser.add_argument('--stepsize', default=[20, 40], nargs='+', type=int,
help="stepsize to decay learning rate")
parser.add_argument('--gamma', default=0.1, type=float,
help="learning rate decay")
parser.add_argument('--train-batch-size', default=64, type=int,
help="training batch size")
parser.add_argument('--test-batch-size', default=100, type=int,
help="test batch size")
parser.add_argument('--fixbase', action='store_true',
help="always fix base network")
parser.add_argument('--fixbase-epoch', type=int, default=10,
help="how many epochs to fix base network (only train randomly initialized classifier)")
parser.add_argument('--open-layers', type=str, nargs='+', default=['classifier'],
help="open specified layers for training while keeping others frozen")
parser.add_argument('--criterion', type=str, default='htri')
# parser.add_argument('--switch-loss', type=int, default=0)
# parser.add_argument('--fix-custom-loss', action='store_true', default=False)
# parser.add_argument('--regularizer', type=str, default='none')
# # parser.add_argument('--dropout', type=str, default='none', choices=['none', 'incr', 'fix'])
# parser.add_argument('--penalty-position', type=str, default='before', choices=['before', 'after', 'pam', 'cam', 'pam,cam', 'before,pam', 'before,cam', 'before,pam,cam', 'layer5', 'all_layers', 'before,layer5', 'after,layer5', 'after,cam', 'before,after,cam,pam', 'after,pam', 'before,before2,after,cam,pam', 'before,after,cam,pam,layer5', 'before,after'])
# ************************************************************
# Cross entropy loss-specific setting
# ************************************************************
parser.add_argument('--label-smooth', action='store_true', default=True,
help="use label smoothing regularizer in cross entropy loss")
# ************************************************************
# Hard triplet loss-specific setting
# ************************************************************
parser.add_argument('--margin', type=float, default=1.2,
help="margin for triplet loss")
parser.add_argument('--num-instances', type=int, default=4,
help="number of instances per identity")
parser.add_argument('--htri-only', action='store_true',
help="only use hard triplet loss")
parser.add_argument('--lambda-xent', type=float, default=1,
help="weight to balance cross entropy loss")
parser.add_argument('--lambda-htri', type=float, default=0.1,
help="weight to balance hard triplet loss")
# ************************************************************
# Architecture
# ************************************************************
parser.add_argument('-a', '--arch', type=str, default='resnet50')
# ************************************************************
# Test settings
# ************************************************************
parser.add_argument('--load-weights', type=str, default='checkpoint/market_checkpoint_best.pth.tar',
help="load pretrained weights but ignore layers that don't match in size")
parser.add_argument('--evaluate', action='store_true',default=True,
help="evaluate only")
parser.add_argument('--eval-freq', type=int, default=1,
help="evaluation frequency (set to -1 to test only in the end)")
parser.add_argument('--start-eval', type=int, default=0,
help="start to evaluate after a specific epoch")
parser.add_argument('--flip-eval', action='store_true', default=True)
# ************************************************************
# Miscs
# ************************************************************
parser.add_argument('--print-freq', type=int, default=10,
help="print frequency")
parser.add_argument('--seed', type=int, default=1,
help="manual seed")
parser.add_argument('--resume', type=str, default='', metavar='PATH',
help="resume from a checkpoint")
parser.add_argument('--save-dir', type=str, default='log',
help="path to save log and model weights")
parser.add_argument('--use-cpu', action='store_true',
help="use cpu")
parser.add_argument('--gpu-devices', default='0', type=str,
help='gpu device ids for CUDA_VISIBLE_DEVICES')
parser.add_argument('--use-avai-gpus', action='store_true',
help="use available gpus instead of specified devices (useful when using managed clusters)")
parser.add_argument('--visualize-ranks', action='store_true',
help="visualize ranked results, only available in evaluation mode")
# ************************************************************
# Branches Related
# ************************************************************
parser.add_argument('--compatibility', action='store_true')
parser.add_argument('--branches', nargs='+', type=str, default=['global', 'abd'])
parser.add_argument('--dropout', type=float, default=0.5)
parser.add_argument('--global-dim', type=int, default=1024)
parser.add_argument('--global-max-pooling', action='store_true')
parser.add_argument('--abd-dim', type=int, default=1024)
parser.add_argument('--abd-np', type=int, default=2)
#parser.add_argument('--abd-dan', nargs='+', type=str, default=['cam','pam'])
parser.add_argument('--abd-dan', nargs='+', type=str, default=['cam','pam'])
parser.add_argument('--abd-dan-no-head', action='store_true')
parser.add_argument('--shallow-cam', action='store_true', default=True)
parser.add_argument('--np-dim', type=int, default=1024)
parser.add_argument('--np-np', type=int, default=2)
parser.add_argument('--np-with-global', action='store_true')
parser.add_argument('--np-max-pooling', action='store_true')
parser.add_argument('--dan-dim', type=int, default=1024)
parser.add_argument('--dan-dan', nargs='+', type=str, default=[])
parser.add_argument('--dan-dan-no-head', action='store_true')
parser.add_argument('--use-of', action='store_true', default=True)
parser.add_argument('--of-beta', type=float, default=1e-6)
parser.add_argument('--of-start-epoch', type=int, default=23)
parser.add_argument('--of-position', nargs='+', type=str, default=['before', 'after', 'cam', 'pam', 'intermediate'])
parser.add_argument('--use-ow', action='store_true', default=True)
parser.add_argument('--ow-beta', type=float, default=1e-3)
`
CUDA out of memory when it reach 23th epoch
I noticed that in a closed issue, so I cd to torchreid/eval_cylib and make. But this ''No module named 'torchreid.losses.wrapped_cross_entropy_loss' is still there. And the make procedure seems to be successful.
i tried use --visualize-ranks to visualize the ranks result when i evaluate the model,but it seems dose not work ,so have you test this module to visualize rank result ?please let me know if you have any idea,thanks a lot
Why can't I set the gpu to 0,1?Or just use 0 directly?Please help me.
Hello, i really enjoy you wonderfer work. Can you show how to draw colorful image with attenion weights? Just like those image in paper. Thx
-.-
thanks for your great job !
in table 1 of the paper, i found that " baseline (XE) + O.F. " Get a huge boost in both top-1 and mAP.
could you tell me how to run that single method ?
Method Market-1501 DukeMTMC
top1 mAP top1 mAP
baseline (XE) 91.50 77.40 82.80 66.40
baseline (XE) + PAM 92.10 78.10 83.80 67.00
baseline (XE) + CAM 91.80 78.00 84.30 67.60
baseline (XE) + PAM + CAM 92.70 78.50 84.40 67.90
baseline (XE) + O.F. 92.90 82.10 84.90 71.30
baseline (XE) + O.W. 92.50 78.50 83.70 67.40
baseline (XE) + O.F. + O.W. 93.20 82.30 85.30 72.20
baseline + SVD layer 90.80 76.90 79.40 62.50
ABD-Net (XE) 94.90 85.90 87.30 76.00
ABD-Net 95.60 88.28 89.00 78.59
I know that the inverse power method can find the minimum eigenvalue and equation (5) can find the maximum eigenvalue of X ,
but why the maximum eigenvalue of the FF^T - lambda_1 I
is the minimum eignevalue of FF^T ?
Besides in the code, it seems that you first use equation (5) get maximum eignevalue , and use FF^T - lambda_1 I to get the disancte between minimum and maximum eignevalue
Thank you for sharing results of your work.
This is a really impressive paper and your response is appreciated
I tried to replicate the results of the project on Market1501, DukeMTMC and MSMT17 using Pytorch 1.3.1.
First, I found some mismatches of duke and msmt17 pretrained weights with model definitions. The following code shoud be inserted
for k, v in pretrain_dict.items():
# fix pretrained weights for duke and msmt17
if (args.load_weights.startswith('duke') or args.load_weights.startswith('msmt17')) and (k.startswith('branches.1.1.cam_module') or k.startswith('branches.1.1.pam_module')):
k = k.replace('branches.1', 'branches.0')
######################
if not (k in model_dict and model_dict[k].size() == v.size()):
if k in model_dict:
print('param miss match', k, v.size(), model_dict[k].size())
else:
print('extra key', k)
else:
print('matched key', k)
before the line
pretrain_dict = {k: v for k, v in pretrain_dict.items() if k in model_dict and model_dict[k].size() == v.size()}
in file train.py
to fix the problem.
Then, I evaluated pretrained weights using the following commands:
python3 train.py -s market1501 -t market1501 --evaluate --load-weights market_checkpoint_best.pth.tar --height 384 --use-of --abd-dan cam pam --abd-np 3 --shallow-cam --use-ow
python3 train.py -s dukemtmcreid -t dukemtmcreid --evaluate --load-weights duke_checkpoint_best.pth.tar --height 384 --use-of --abd-dan cam pam --abd-np 3 --shallow-cam --use-ow
python3 train.py -s msmt17 -t msmt17 --evaluate --load-weights msmt17_final_best.pth.zip.tar --height 384 --use-of --abd-dan cam pam --abd-np 3 --shallow-cam --use-ow
For flip evaluation, I added an aditional parameter --filp-eval
Here is the result:
Datasets | mAP | R1 | mAP(flip_eval) | R1(flip_eval) | mAP(paper) | R1(paper) |
---|---|---|---|---|---|---|
market1501 | 86.1 | 94.6 | 86.8 | 94.7 | 88.3 | 95.6 |
dukemtmc | 76.3 | 87.4 | 77.1 | 87.8 | 78.6 | 89.0 |
msmt17 | 48.4 | 73.8 | Insufficient Memory? | Insufficient Memory? | 60.8 | 82.3 |
For makert1501 and dukemtmc, the replicated performance is a bit slower than reported. For msmt17, however, the performance gap is significant.
Could the authors help me find the cause of performance drop? It is crucial since the paper reported performance gain compared with other competitive methods (such as IANet, DGNet) by a great margin (at least 8% in mAP and 5% in R1) on MSMT17. Personally, I think it's strange that this great advantage is not present on DukeMTMC-reid and Market1501 but present on MSMT17 only.
I noticed the original dataset page of msmt17 is not available now. What I got is with three folders only:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import glob
import re
import sys
import urllib
import tarfile
import zipfile
import os.path as osp
from scipy.io import loadmat
import numpy as np
import h5py
#from scipy.misc import imsave
from .bases import BaseImageDataset
class MSMT17(BaseImageDataset):
"""
MSMT17
Reference:
Wei et al. Person Transfer GAN to Bridge Domain Gap for Person Re-Identification. CVPR 2018.
URL: http://www.pkuvmc.com/publications/msmt17.html
Dataset statistics:
# identities: 4101
# images: 32621 (train) + 11659 (query) + 82161 (gallery)
# cameras: 15
"""
#dataset_dir = 'msmt17'
dataset_dir = 'MSMT17'
def __init__(self, root='data', verbose=True, **kwargs):
super(MSMT17, self).__init__()
self.dataset_dir = osp.join(root, self.dataset_dir)
self.train_dir = osp.join(self.dataset_dir, 'bounding_box_train')
self.test_dir = osp.join(self.dataset_dir, 'bounding_box_test')
self.query_dir = osp.join(self.dataset_dir, 'query')
#self.list_train_path = osp.join(self.dataset_dir, 'MSMT17_V1/list_train.txt')
#self.list_val_path = osp.join(self.dataset_dir, 'MSMT17_V1/list_val.txt')
#self.list_query_path = osp.join(self.dataset_dir, 'MSMT17_V1/list_query.txt')
#self.list_gallery_path = osp.join(self.dataset_dir, 'MSMT17_V1/list_gallery.txt')
self._check_before_run()
train = self._process_dir(self.train_dir)
#val = self._process_dir(self.train_dir, self.list_val_path)
query = self._process_dir(self.query_dir)
gallery = self._process_dir(self.test_dir)
#train += val
#num_train_imgs += num_val_imgs
if verbose:
print("=> MSMT17 loaded")
self.print_dataset_statistics(train, query, gallery)
self.train = train
self.query = query
self.gallery = gallery
self.num_train_pids, self.num_train_imgs, self.num_train_cams = self.get_imagedata_info(self.train)
self.num_query_pids, self.num_query_imgs, self.num_query_cams = self.get_imagedata_info(self.query)
self.num_gallery_pids, self.num_gallery_imgs, self.num_gallery_cams = self.get_imagedata_info(self.gallery)
def _check_before_run(self):
"""Check if all files are available before going deeper"""
if not osp.exists(self.dataset_dir):
raise RuntimeError("'{}' is not available".format(self.dataset_dir))
if not osp.exists(self.train_dir):
raise RuntimeError("'{}' is not available".format(self.train_dir))
if not osp.exists(self.test_dir):
raise RuntimeError("'{}' is not available".format(self.test_dir))
def _process_dir(self, dir_path):
#with open(list_path, 'r') as txt:
# lines = txt.readlines()
lines = [f for f in os.listdir(dir_path) if f.endswith('.jpg') ]
dataset = []
pid_container = set()
for img_idx, img_name in enumerate(lines):
pid, camid, _ = img_name.split('_')
pid = int(pid) # no need to relabel
camid = int(camid[1:]) - 1 # index starts from 0
img_path = osp.join(dir_path, img_name)
dataset.append((img_path, pid, camid))
pid_container.add(pid)
num_pids = len(pid_container)
# check if pid starts from 0 and increments with 1
for idx, pid in enumerate(pid_container):
assert idx == pid, "See code comment for explanation"
return dataset
at torchreid/components/branches.py class MultibranchNetwork at _get_branches
branch_names = (frozenset(args['branches'])
this sometimes can change the order of the branches, such as from abd, global to global, abd, causes the model sometimes cannot resume from checkpoint throwing exception like
'Error loading checkpoint
unexpected keys : ...'
HI,thanks for your awesome work,but can you Provide the training commands? thanks you very mush
First of all thank you very much for your outstanding contribution!
In the paper, you have deployed O.M and O.F many times. I have been searching for a long time and have not found the deployment py file for deploying O.M and O.F. Can you give me some guidance?
best wishs
Please see this https://kaiyangzhou.github.io/deep-person-reid/MODEL_ZOO.html
您好大佬,我想请教一下您。您的README_Training_and_Testing_Guides.md 给出的参数是论文中在market-1501数据集上获得最优结果时使用的参数嘛?我只得到了95.3%的rank1而论文中是95.6%,在怀疑是不是参数的问题。感谢您的帮助,您的代码十分优雅,小弟非常喜欢,叹为观止!
This result cannot be achieved.
rank1=95.6
map=88.28
can you provide me the args.py file?
Hello, can i have your code about the attention visualization?
Hi,
When i run source code to evaluate model. I changed backbond to inceptionv4. But i got an error
" Dimension out of range (expected to be in range of [-1, 0], but got 1) ". Can you explain why?
thank you
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.