mirror of https://github.com/JDAI-CV/fast-reid.git
parent
08d105560c
commit
369325906f
|
@ -5,4 +5,4 @@ __pycache__
|
|||
datasets
|
||||
csrc/eval_cylib/build/
|
||||
logs/
|
||||
*.ipynb
|
||||
*.ipynb
|
||||
|
|
|
@ -43,7 +43,7 @@ _C.INPUT.PADDING = 10
|
|||
# -----------------------------------------------------------------------------
|
||||
_C.DATASETS = CN()
|
||||
# List of the dataset names for training, as present in paths_catalog.py
|
||||
_C.DATASETS.NAMES = ('market1501')
|
||||
_C.DATASETS.NAMES = ()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# DataLoader
|
||||
|
|
|
@ -9,7 +9,7 @@ INPUT:
|
|||
PADDING: 10
|
||||
|
||||
DATASETS:
|
||||
NAMES: ('market1501')
|
||||
NAMES: ("market1501",)
|
||||
|
||||
DATALOADER:
|
||||
SAMPLER: 'softmax_triplet'
|
||||
|
@ -21,7 +21,7 @@ SOLVER:
|
|||
BASE_LR: 0.00035
|
||||
WEIGHT_DECAY: 0.0005
|
||||
WEIGHT_DECAY_BIAS: 0.0005
|
||||
IMS_PER_BATCH: 64
|
||||
IMS_PER_BATCH: 256
|
||||
|
||||
STEPS: [40, 90]
|
||||
GAMMA: 0.1
|
||||
|
@ -35,6 +35,6 @@ TEST:
|
|||
IMS_PER_BATCH: 512
|
||||
WEIGHT: "path"
|
||||
|
||||
OUTPUT_DIR: "logs/beijing/market+duke+bj/"
|
||||
OUTPUT_DIR: "logs/market/batch256/"
|
||||
|
||||
|
||||
|
|
|
@ -22,39 +22,53 @@ def get_data_bunch(cfg):
|
|||
None
|
||||
)
|
||||
|
||||
def _process_dir(dir_path):
|
||||
def _process_dir(dir_path, recursive=False):
|
||||
img_paths = []
|
||||
if 'beijingStation' in dir_path:
|
||||
if recursive:
|
||||
id_dirs = os.listdir(dir_path)
|
||||
for d in id_dirs:
|
||||
img_paths.extend(glob.glob(os.path.join(dir_path, d, '*.jpg')))
|
||||
else:
|
||||
img_paths = glob.glob(os.path.join(dir_path, '*.jpg'))
|
||||
pattern = re.compile(r'([-\d]+)_c(\d)')
|
||||
|
||||
pid_container = set()
|
||||
pattern = re.compile(r'([-\d]+)_c(\d*)')
|
||||
v_paths = []
|
||||
for img_path in img_paths:
|
||||
pid, camid = map(int, pattern.search(img_path).groups())
|
||||
pid = int(pid)
|
||||
if pid == -1: continue # junk images are just ignored
|
||||
pid_container.add(pid)
|
||||
v_paths.append([img_path, pid, camid])
|
||||
v_paths.append([img_path,pid,camid])
|
||||
return v_paths
|
||||
|
||||
|
||||
market_train_path = 'datasets/Market-1501-v15.09.15/bounding_box_train'
|
||||
duke_train_path = 'datasets/DukeMTMC-reID/bounding_box_train'
|
||||
cuhk03_train_path = 'datasets/cuhk03/'
|
||||
bjStation_train_path = 'datasets/beijingStation/20190720/train'
|
||||
|
||||
query_path = 'datasets/Market-1501-v15.09.15/query'
|
||||
gallery_path = 'datasets/Market-1501-v15.09.15/bounding_box_test'
|
||||
market_query_path = 'datasets/Market-1501-v15.09.15/query'
|
||||
marker_gallery_path = 'datasets/Market-1501-v15.09.15/bounding_box_test'
|
||||
bj_query_path = 'datasets/beijingStation/query'
|
||||
bj_gallery_path = 'datasets/beijingStation/test'
|
||||
|
||||
train_img_names = _process_dir(market_train_path) + _process_dir(duke_train_path) + _process_dir(bjStation_train_path)
|
||||
train_img_names = list()
|
||||
for d in cfg.DATASETS.NAMES:
|
||||
if d == 'market1501':
|
||||
train_img_names.extend(_process_dir(market_train_path))
|
||||
elif d == 'duke':
|
||||
train_img_names.extend(_process_dir(duke_train_path))
|
||||
elif d == 'beijing':
|
||||
train_img_names.extend(_process_dir(bjStation_train_path, True))
|
||||
else:
|
||||
raise NameError("{} is not available".format(d))
|
||||
|
||||
# train_img_names = _process_dir(market_train_path) + _process_dir(duke_train_path) + _process_dir(bjStation_train_path)
|
||||
# train_img_names = _process_dir(market_train_path)
|
||||
# train_img_names = CUHK03().train
|
||||
train_names = [i[0] for i in train_img_names]
|
||||
|
||||
query_names = _process_dir(query_path)
|
||||
gallery_names = _process_dir(gallery_path)
|
||||
query_names = _process_dir(bj_query_path)
|
||||
gallery_names = _process_dir(bj_gallery_path, True)
|
||||
|
||||
test_fnames = []
|
||||
test_labels = []
|
||||
for i in query_names+gallery_names:
|
||||
|
|
|
@ -1,64 +1,52 @@
|
|||
# encoding: utf-8
|
||||
"""
|
||||
@author: sherlock
|
||||
@author: liaoxingyu
|
||||
@contact: sherlockliao01@gmail.com
|
||||
"""
|
||||
import logging
|
||||
|
||||
import torch
|
||||
from ignite.engine import Engine
|
||||
from data.datasets.eval_reid import evaluate
|
||||
from fastai.vision import *
|
||||
|
||||
from utils.reid_metric import R1_mAP
|
||||
|
||||
|
||||
def create_supervised_evaluator(model, metrics,
|
||||
device=None):
|
||||
"""
|
||||
Factory function for creating an evaluator for supervised models
|
||||
|
||||
Args:
|
||||
model (`torch.nn.Module`): the model to train
|
||||
metrics (dict of str - :class:`ignite.metrics.Metric`): a map of metric names to Metrics
|
||||
device (str, optional): device type specification (default: None).
|
||||
Applies to both model and batches.
|
||||
Returns:
|
||||
Engine: an evaluator engine with supervised inference function
|
||||
"""
|
||||
if device:
|
||||
model.to(device)
|
||||
|
||||
def _inference(engine, batch):
|
||||
model.eval()
|
||||
with torch.no_grad():
|
||||
data, pids, camids = batch
|
||||
data = data.cuda()
|
||||
feat = model(data)
|
||||
return feat, pids, camids
|
||||
|
||||
engine = Engine(_inference)
|
||||
|
||||
for name, metric in metrics.items():
|
||||
metric.attach(engine, name)
|
||||
|
||||
return engine
|
||||
|
||||
|
||||
def inference(
|
||||
cfg,
|
||||
model,
|
||||
val_loader,
|
||||
data_bunch,
|
||||
test_labels,
|
||||
num_query
|
||||
):
|
||||
device = cfg.MODEL.DEVICE
|
||||
|
||||
logger = logging.getLogger("reid_baseline.inference")
|
||||
logger.info("Start inferencing")
|
||||
evaluator = create_supervised_evaluator(model, metrics={'r1_mAP': R1_mAP(num_query)},
|
||||
device=device)
|
||||
|
||||
evaluator.run(val_loader)
|
||||
cmc, mAP = evaluator.state.metrics['r1_mAP']
|
||||
logger.info('Validation Results')
|
||||
pids = []
|
||||
camids = []
|
||||
for p, c in test_labels:
|
||||
pids.append(p)
|
||||
camids.append(c)
|
||||
q_pids = np.asarray(pids[:num_query])
|
||||
g_pids = np.asarray(pids[num_query:])
|
||||
q_camids = np.asarray(camids[:num_query])
|
||||
g_camids = np.asarray(camids[num_query:])
|
||||
feats = []
|
||||
model.eval()
|
||||
for imgs, _ in data_bunch.test_dl:
|
||||
with torch.no_grad():
|
||||
feat = model(imgs)
|
||||
feats.append(feat)
|
||||
feats = torch.cat(feats, dim=0)
|
||||
|
||||
qf = feats[:num_query]
|
||||
gf = feats[num_query:]
|
||||
m, n = qf.shape[0], gf.shape[0]
|
||||
distmat = torch.pow(qf,2).sum(dim=1,keepdim=True).expand(m,n) + \
|
||||
torch.pow(gf,2).sum(dim=1,keepdim=True).expand(n,m).t()
|
||||
distmat.addmm_(1, -2, qf, gf.t())
|
||||
distmat = to_np(distmat)
|
||||
cmc, mAP = evaluate(distmat, q_pids, g_pids, q_camids, g_camids)
|
||||
logger.info('Test Results')
|
||||
logger.info("mAP: {:.1%}".format(mAP))
|
||||
for r in [1, 5, 10]:
|
||||
logger.info("CMC curve, Rank-{:<3}:{:.1%}".format(r, cmc[r - 1]))
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
@contact: sherlockliao01@gmail.com
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
|
||||
from data.datasets.eval_reid import evaluate
|
||||
from fastai.vision import *
|
||||
import torch.nn.functional as F
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -16,12 +18,12 @@ class TrackValue(Callback):
|
|||
logger: logging.Logger
|
||||
total_iter: int
|
||||
|
||||
def on_batch_end(self, num_batch, last_loss, **kwargs):
|
||||
if (num_batch+1) % (self.total_iter//3) == 0:
|
||||
self.logger.info('Iter [{}/{}], loss: {:.4f}'.format(num_batch, self.total_iter, last_loss.item()))
|
||||
# def on_batch_end(self, num_batch, last_loss, **kwargs):
|
||||
# if (num_batch+1) % (self.total_iter//3) == 0:
|
||||
# self.logger.info('Iter [{}/{}], loss: {:.4f}'.format(num_batch, self.total_iter, last_loss.item()))
|
||||
|
||||
def on_epoch_end(self, epoch, smooth_loss, **kwargs):
|
||||
self.logger.info('Epoch {}, loss: {:.4f}'.format(epoch, smooth_loss.item()))
|
||||
self.logger.info('Epoch {}[Iter {}], loss: {:.4f}'.format(epoch, self.total_iter, smooth_loss.item()))
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -113,4 +115,8 @@ def do_train(
|
|||
partial(TestModel, test_labels=test_labels, eval_period=eval_period, num_query=num_query, logger=logger)],
|
||||
callbacks=[TrackValue(logger, total_iter)])
|
||||
|
||||
learn.fit(epochs, lr=cfg.SOLVER.BASE_LR, wd=cfg.SOLVER.WEIGHT_DECAY)
|
||||
learn.fit(epochs, wd=cfg.SOLVER.WEIGHT_DECAY)
|
||||
learn.recorder.plot_losses()
|
||||
plt.savefig(os.path.join(output_dir, "loss.jpg"))
|
||||
learn.recorder.plot_lr()
|
||||
plt.savefig(os.path.join(output_dir, "lr.jpg"))
|
|
@ -1,47 +0,0 @@
|
|||
2019-07-29 20:56:09,448 reid_baseline INFO: Using 1 GPUs.
|
||||
2019-07-29 20:56:09,449 reid_baseline INFO: Namespace(config_file='configs/softmax_triplet.yml', opts=[])
|
||||
2019-07-29 20:56:09,449 reid_baseline INFO: Loaded configuration file configs/softmax_triplet.yml
|
||||
2019-07-29 20:56:09,449 reid_baseline INFO: Running with config:
|
||||
DATALOADER:
|
||||
NUM_INSTANCE: 4
|
||||
NUM_WORKERS: 8
|
||||
SAMPLER: softmax_triplet
|
||||
DATASETS:
|
||||
NAMES: market1501
|
||||
INPUT:
|
||||
PADDING: 10
|
||||
PIXEL_MEAN: [0.485, 0.456, 0.406]
|
||||
PIXEL_STD: [0.229, 0.224, 0.225]
|
||||
PROB: 0.5
|
||||
SIZE_TEST: [256, 128]
|
||||
SIZE_TRAIN: [256, 128]
|
||||
MODEL:
|
||||
DEVICE: cuda
|
||||
LAST_STRIDE: 1
|
||||
NAME: resnet50
|
||||
PRETRAIN_PATH: /export/home/lxy/.cache/torch/checkpoints/resnet50-19c8e357.pth
|
||||
OUTPUT_DIR: logs/co-train/test
|
||||
SOLVER:
|
||||
BASE_LR: 0.00035
|
||||
BIAS_LR_FACTOR: 2
|
||||
CHECKPOINT_PERIOD: 50
|
||||
EVAL_PERIOD: 30
|
||||
GAMMA: 0.1
|
||||
IMS_PER_BATCH: 64
|
||||
LOG_PERIOD: 100
|
||||
MARGIN: 0.3
|
||||
MAX_EPOCHS: 150
|
||||
MOMENTUM: 0.9
|
||||
OPTIMIZER_NAME: Adam
|
||||
STEPS: (40, 90)
|
||||
WARMUP_FACTOR: 0.01
|
||||
WARMUP_ITERS: 10
|
||||
WARMUP_METHOD: linear
|
||||
WEIGHT_DECAY: 0.0005
|
||||
WEIGHT_DECAY_BIAS: 0.0005
|
||||
TEST:
|
||||
IMS_PER_BATCH: 512
|
||||
WEIGHT: path
|
||||
2019-07-29 20:56:10,745 reid_baseline.train INFO: Start Training
|
||||
2019-07-29 20:56:37,530 reid_baseline.train INFO: Iter [60/185], loss: 8.0126
|
||||
2019-07-29 20:56:56,679 reid_baseline.train INFO: Iter [121/185], loss: 7.5083
|
|
@ -38,8 +38,10 @@ class Baseline(nn.Module):
|
|||
def __init__(self, num_classes, last_stride, model_path=None):
|
||||
super(Baseline, self).__init__()
|
||||
self.base = ResNet(last_stride)
|
||||
if model_path is not None:
|
||||
try:
|
||||
self.base.load_param(model_path)
|
||||
except:
|
||||
print("Not load imagenet pretrained model!")
|
||||
self.gap = nn.AdaptiveAvgPool2d(1)
|
||||
self.num_classes = num_classes
|
||||
|
||||
|
@ -59,3 +61,9 @@ class Baseline(nn.Module):
|
|||
return cls_score, global_feat # global feature for triplet loss
|
||||
else:
|
||||
return feat
|
||||
|
||||
def load_params_wo_fc(self, state_dict):
|
||||
for i in state_dict:
|
||||
if 'classifier' in i:
|
||||
continue
|
||||
self.state_dict()[i].copy_(state_dict[i])
|
|
@ -0,0 +1,6 @@
|
|||
gpu=3
|
||||
|
||||
CUDA_VISIBLE_DEVICES=$gpu python tools/test.py -cfg='configs/softmax_triplet.yml' \
|
||||
DATASETS.NAMES '("market1501","duke","beijing")' \
|
||||
OUTPUT_DIR 'logs/test' \
|
||||
TEST.WEIGHT 'logs/beijing/market+duke+bj/models/model_149.pth'
|
|
@ -0,0 +1,5 @@
|
|||
gpu=3
|
||||
|
||||
CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \
|
||||
DATASETS.NAMES '("beijing",)' \
|
||||
OUTPUT_DIR 'logs/beijing/market_duke_finetune'
|
|
@ -0,0 +1,5 @@
|
|||
gpu=3
|
||||
|
||||
CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \
|
||||
DATASETS.NAMES '("market1501",)' \
|
||||
OUTPUT_DIR 'logs/market/softmax_triplet_256_128_bs512'
|
|
@ -0,0 +1,5 @@
|
|||
gpu=2
|
||||
|
||||
CUDA_VISIBLE_DEVICES=$gpu python tools/train.py -cfg='configs/softmax_triplet.yml' \
|
||||
DATASETS.NAMES '("market1501","duke")' \
|
||||
OUTPUT_DIR 'logs/beijing/market_duke_softmax_triplet_256_128_bs512'
|
|
@ -16,12 +16,13 @@ sys.path.append('.')
|
|||
from config import cfg
|
||||
from data import get_data_bunch
|
||||
from engine.inference import inference
|
||||
from utils.logger import setup_logger
|
||||
from modeling import build_model
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="ReID Baseline Inference")
|
||||
parser.add_argument(
|
||||
parser.add_argument('-cfg',
|
||||
"--config_file", default="", help="path to config file", type=str
|
||||
)
|
||||
parser.add_argument("opts", help="Modify config options using the command-line", default=None,
|
||||
|
@ -36,28 +37,25 @@ def main():
|
|||
cfg.merge_from_list(args.opts)
|
||||
cfg.freeze()
|
||||
|
||||
output_dir = cfg.OUTPUT_DIR
|
||||
if output_dir and not os.path.exists(output_dir):
|
||||
mkdir(output_dir)
|
||||
if not os.path.exists(cfg.OUTPUT_DIR): os.makedirs(cfg.OUTPUT_DIR)
|
||||
|
||||
logger = setup_logger("reid_baseline", output_dir, 0)
|
||||
logger = setup_logger("reid_baseline", cfg.OUTPUT_DIR, 0)
|
||||
logger.info("Using {} GPUS".format(num_gpus))
|
||||
logger.info(args)
|
||||
|
||||
if args.config_file != "":
|
||||
logger.info("Loaded configuration file {}".format(args.config_file))
|
||||
with open(args.config_file, 'r') as cf:
|
||||
config_str = "\n" + cf.read()
|
||||
logger.info(config_str)
|
||||
logger.info("Running with config:\n{}".format(cfg))
|
||||
|
||||
cudnn.benchmark = True
|
||||
|
||||
train_databunch, test_databunch, num_query = get_data_bunch(cfg)
|
||||
model = build_model(cfg, train_databunch.c)
|
||||
model.load_state_dict(torch.load(cfg.TEST.WEIGHT))
|
||||
data_bunch, test_labels, num_query = get_data_bunch(cfg)
|
||||
model = build_model(cfg, data_bunch.c)
|
||||
state_dict = torch.load(cfg.TEST.WEIGHT)
|
||||
model.load_state_dict(state_dict['model'])
|
||||
model.cuda()
|
||||
|
||||
inference(cfg, model, test_databunch, num_query)
|
||||
inference(cfg, model, data_bunch, test_labels, num_query)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -27,6 +27,8 @@ def train(cfg):
|
|||
|
||||
# prepare model
|
||||
model = build_model(cfg, data_bunch.c)
|
||||
state_dict = torch.load("logs/beijing/market_duke_softmax_triplet_256_128_bs512/models/model_149.pth")
|
||||
model.load_params_wo_fc(state_dict['model'])
|
||||
|
||||
opt_func = partial(torch.optim.Adam)
|
||||
|
||||
|
@ -40,7 +42,8 @@ def train(cfg):
|
|||
warmup_factor = cfg.SOLVER.WARMUP_FACTOR * (1 - alpha) + alpha
|
||||
return start * warmup_factor * gamma ** bisect_right(milestones, pct)
|
||||
|
||||
lr_sched = Scheduler((cfg.SOLVER.BASE_LR, 0), cfg.SOLVER.MAX_EPOCHS, warmup_multistep)
|
||||
lr = cfg.SOLVER.BASE_LR * (cfg.SOLVER.IMS_PER_BATCH // 64)
|
||||
lr_sched = Scheduler(lr, cfg.SOLVER.MAX_EPOCHS, warmup_multistep)
|
||||
|
||||
loss_func = make_loss(cfg)
|
||||
|
||||
|
|
Loading…
Reference in New Issue