Skip to content

Commit

Permalink
Merge pull request #4 from beesk135/cosface
Browse files Browse the repository at this point in the history
Cosface
  • Loading branch information
thanit456 authored Oct 11, 2020
2 parents 81a1005 + d35f3bf commit be524d2
Show file tree
Hide file tree
Showing 17 changed files with 814 additions and 99 deletions.
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

0 comments on commit be524d2

Please sign in to comment.