Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosface #4

Merged
merged 9 commits into from
Oct 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"python.linting.pylintEnabled": true,
"python.linting.enabled": true
}
4 changes: 2 additions & 2 deletions Experiment-AGW-market.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
# weight regularized triplet loss
# generalized mean pooling
# non local blocks
python3 tools/main.py --config_file='configs/AGW_baseline.yml' MODEL.DEVICE_ID "('3')" \
DATASETS.NAMES "('market1501')" OUTPUT_DIR "('./log/market1501/Experiment-AGW-baseline')"
python3 tools/main.py --config_file='configs/AGW_baseline.yml' MODEL.DEVICE_ID "('0')" \
DATASETS.NAMES "('market1501')" OUTPUT_DIR "('./log/market1501/cosface-1')"
13 changes: 9 additions & 4 deletions config/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# ID number of GPU
_C.MODEL.DEVICE_ID = '0'
# Name of backbone
_C.MODEL.NAME = 'resnet50'
_C.MODEL.BACKBONE = 'resnet50'
# Last stride of backbone
_C.MODEL.LAST_STRIDE = 1
# Path to pretrained model of backbone
Expand All @@ -36,9 +36,14 @@
_C.MODEL.CENTER_FEAT_DIM = 2048
# If train with weighted regularized triplet loss, options: 'on', 'off'
_C.MODEL.WEIGHT_REGULARIZED_TRIPLET = 'off'
# If train with generalized mean pooling, options: 'on', 'off'
_C.MODEL.GENERALIZED_MEAN_POOL = 'off'

# custom config
_C.MODEL.POOL_TYPE = 'avg'
_C.MODEL.COSINE_LOSS_TYPE = ''
_C.MODEL.SCALING_FACTOR = 60.0
_C.MODEL.MARGIN = 0.35
_C.MODEL.USE_BNBIAS = False
_C.MODEL.USE_DROPOUT = True
_C.MODEL.USE_SESTN = False

# -----------------------------------------------------------------------------
# INPUT
Expand Down
18 changes: 13 additions & 5 deletions configs/AGW_baseline.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
MODEL:
PRETRAIN_CHOICE: 'self'
PRETRAIN_PATH: "/content/drive/Shared drives/REID/ReId-Survey-Paper/ReID-Survey/log/market1501/Experiment-AGW-baseline/resnet50_nl_model_160.pth"
# PRETRAIN_PATH: 'C:/Users/60310249/.torch/models/resnet50-19c8e357.pth'
PRETRAIN_CHOICE: 'imagenet'
# PRETRAIN_PATH: "/content/drive/Shared drives/REID/ReId-Survey-Paper/ReID-Survey/log/market1501/local-AGW-baseline/resnet50_nl_model_120.pth"
PRETRAIN_PATH: '/home/thanit456/torch/weights/resnet50-19c8e357.pth'
TRANSFER_MODE : 'off'
CENTER_LOSS: 'on'
CENTER_FEAT_DIM: 2048
NAME: 'resnet50_nl'
BACKBONE: 'resnet50_nl'
WEIGHT_REGULARIZED_TRIPLET: 'on'
GENERALIZED_MEAN_POOL: 'on'
POOL_TYPE: 'avg'
COSINE_LOSS_TYPE: 'CosFace'
SCALING_FACTOR: 60.0
MARGIN: 0.35
USE_BNBIAS: False
USE_DROPOUT: False
USE_SESTN: False

INPUT:
IMG_SIZE: [256, 128]
Expand All @@ -32,6 +38,8 @@ SOLVER:

WEIGHT_DECAY: 0.0005
IMS_PER_BATCH: 64
# IMS_PER_BATCH: 32


STEPS: [40, 70]
GAMMA: 0.1
Expand Down
12 changes: 12 additions & 0 deletions evaluate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import torch

from .eval_reid import eval_func

def euclidean_dist(x, y):
m, n = x.size(0), y.size(0)
xx = torch.pow(x, 2).sum(1, keepdim=True).expand(m, n)
yy = torch.pow(y, 2).sum(1, keepdim=True).expand(n, m).t()
dist = xx + yy
dist.addmm_(1, -2, x, y.t())
dist = dist.clamp(min=1e-12).sqrt()
return dist
65 changes: 65 additions & 0 deletions evaluate/eval_reid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import numpy as np

def eval_func(distmat, q_pids, g_pids, q_camids, g_camids, max_rank=200):
"""Evaluation with market1501 metric
Key: for each query identity, its gallery images from the same camera view are discarded.
"""
num_q, num_g = distmat.shape
if num_g < max_rank:
max_rank = num_g
print("Note: number of gallery samples is quite small, got {}".format(num_g))
indices = np.argsort(distmat, axis=1)
matches = (g_pids[indices] == q_pids[:, np.newaxis]).astype(np.int32)

# compute cmc curve for each query
all_cmc = []
all_AP = []
num_valid_q = 0. # number of valid query
for q_idx in range(num_q):
# get query pid and camid
q_pid = q_pids[q_idx]
q_camid = q_camids[q_idx]

# remove gallery samples that have the same pid and camid with query
order = indices[q_idx]
remove = (g_pids[order] == q_pid) & (g_camids[order] == q_camid)
keep = np.invert(remove)

# compute cmc curve
# binary vector, positions with value 1 are correct matches
orig_cmc = matches[q_idx][keep]
if not np.any(orig_cmc):
# this condition is true when query identity does not appear in gallery
# [update:20191029] divide by query
all_AP.append(0)
continue

cmc = orig_cmc.cumsum()
cmc[cmc > 1] = 1

all_cmc.append(cmc[:max_rank])
num_valid_q += 1.

# compute average precision
# reference: https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Average_precision
# [update:20191029] support for map@max_rank
orig_cmc = orig_cmc[:max_rank]
if not np.any(orig_cmc):
all_AP.append(0)
continue
num_rel = orig_cmc.sum()
tmp_cmc = orig_cmc.cumsum()
tmp_cmc = [x / (i + 1.) for i, x in enumerate(tmp_cmc)]
tmp_cmc = np.asarray(tmp_cmc) * orig_cmc
AP = tmp_cmc.sum() / num_rel
all_AP.append(AP)

# assert num_valid_q > 0, "Error: all query identities do not appear in gallery"

all_cmc = np.asarray(all_cmc).astype(np.float32)
# [update:20191029] divide by query
all_cmc = all_cmc.sum(0) / num_q

mAP = np.mean(all_AP)

return all_cmc, mAP,all_AP
14 changes: 12 additions & 2 deletions modeling/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
from .baseline import Baseline

def build_model(cfg, num_classes):
model = Baseline(num_classes, cfg.MODEL.LAST_STRIDE, cfg.MODEL.PRETRAIN_PATH, cfg.MODEL.NAME,
cfg.MODEL.GENERALIZED_MEAN_POOL, cfg.MODEL.PRETRAIN_CHOICE)
model = Baseline(num_classes=num_classes,
last_stride=cfg.MODEL.LAST_STRIDE,
model_path=cfg.MODEL.PRETRAIN_PATH,
backbone=cfg.MODEL.BACKBONE,
pool_type=cfg.MODEL.POOL_TYPE,
use_dropout=cfg.MODEL.USE_DROPOUT,
cosine_loss_type=cfg.MODEL.COSINE_LOSS_TYPE,
s=cfg.MODEL.SCALING_FACTOR,
m=cfg.MODEL.MARGIN,
use_bnbias=cfg.MODEL.USE_BNBIAS,
use_sestn=cfg.MODEL.USE_SESTN,
pretrain_choice=cfg.MODEL.PRETRAIN_CHOICE)
return model
16 changes: 15 additions & 1 deletion modeling/backbones/resnet_ibn_a.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import math
import torch.utils.model_zoo as model_zoo

from ..layer.attention import SESTNLayer

__all__ = ['ResNet_IBN', 'resnet50_ibn_a', 'resnet101_ibn_a',
'resnet152_ibn_a']
Expand Down Expand Up @@ -76,7 +77,7 @@ def forward(self, x):

class ResNet_IBN(nn.Module):

def __init__(self, last_stride, block, layers, num_classes=1000):
def __init__(self, last_stride, block, layers, num_classes=1000, use_sestn=False):
scale = 64
self.inplanes = scale
super(ResNet_IBN, self).__init__()
Expand All @@ -92,6 +93,11 @@ def __init__(self, last_stride, block, layers, num_classes=1000):
self.avgpool = nn.AvgPool2d(7)
self.fc = nn.Linear(scale * 8 * block.expansion, num_classes)

self.use_sestn = use_sestn
if use_sestn:
self.sestn1 = SESTNLayer(256, 16)
self.sestn2 = SESTNLayer(512, 32)

for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
Expand Down Expand Up @@ -130,7 +136,15 @@ def forward(self, x):
x = self.maxpool(x)

x = self.layer1(x)

if self.use_sestn:
x = self.sestn1(x)

x = self.layer2(x)

if self.use_sestn:
x = self.sestn2(x)

x = self.layer3(x)
x = self.layer4(x)

Expand Down
Loading