[add]上传训练benchmark by z00560161
This commit is contained in:
+81
@@ -0,0 +1,81 @@
|
||||
import torch.utils.data as data
|
||||
import os
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import pickle
|
||||
import copy
|
||||
|
||||
class AttDataset(data.Dataset):
|
||||
"""
|
||||
person attribute dataset interface
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
dataset,
|
||||
partition,
|
||||
split='train',
|
||||
partition_idx=0,
|
||||
transform=None,
|
||||
target_transform=None,
|
||||
**kwargs):
|
||||
if os.path.exists( dataset ):
|
||||
file = open(dataset, 'rb')
|
||||
self.dataset = pickle.load(file)
|
||||
else:
|
||||
print (dataset + ' does not exist in dataset.')
|
||||
raise ValueError
|
||||
if os.path.exists( partition ):
|
||||
part = open(partition, 'rb')
|
||||
self.partition = pickle.load(part)
|
||||
else:
|
||||
print (partition + ' does not exist in dataset.')
|
||||
raise ValueError
|
||||
if split not in self.partition:
|
||||
print (split + ' does not exist in dataset.')
|
||||
raise ValueError
|
||||
|
||||
if partition_idx > len(self.partition[split])-1:
|
||||
print ('partition_idx is out of range in partition.')
|
||||
raise ValueError
|
||||
|
||||
self.transform = transform
|
||||
self.target_transform = target_transform
|
||||
|
||||
# create image, label based on the selected partition and dataset split
|
||||
self.root_path = self.dataset['root']
|
||||
self.att_name = [self.dataset['att_name'][i] for i in self.dataset['selected_attribute']]
|
||||
self.image = []
|
||||
self.label = []
|
||||
for idx in self.partition[split][partition_idx]:
|
||||
self.image.append(self.dataset['image'][idx])
|
||||
label_tmp = np.array(self.dataset['att'][idx])[self.dataset['selected_attribute']].tolist()
|
||||
self.label.append(label_tmp)
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""
|
||||
Args:
|
||||
index (int): Index
|
||||
Returns:
|
||||
tuple: (image, target) where target is the index of the target class
|
||||
"""
|
||||
imgname, target = self.image[index], self.label[index]
|
||||
# load image and labels
|
||||
imgname = os.path.join(self.dataset['root'], imgname)
|
||||
img = Image.open(imgname)
|
||||
if self.transform is not None:
|
||||
img = self.transform( img )
|
||||
|
||||
# default no transform
|
||||
target = np.array(target).astype(np.float32)
|
||||
target[target == 0] = -1
|
||||
target[target == 2] = 0
|
||||
if self.target_transform is not None:
|
||||
target = self.transform( target )
|
||||
|
||||
return img, target
|
||||
|
||||
# useless for personal batch sampler
|
||||
def __len__(self):
|
||||
return len(self.image)
|
||||
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import torch
|
||||
import numpy as np
|
||||
import numbers
|
||||
__all__ = ["AddPad", "AddCrop"]
|
||||
|
||||
class AddCrop(object):
|
||||
def __init__(self, size):
|
||||
self.size = size # two
|
||||
assert len(self.size) == 2
|
||||
def __repr__(self):
|
||||
return self.__class__.__name__ + '(size={0})'.format(self.size)
|
||||
def __call__(self, img):
|
||||
shape = img.shape # 3*H*W
|
||||
h_high = shape[1] - self.size[0]
|
||||
w_high = shape[2] - self.size[1]
|
||||
h_start = np.random.randint(low=0, high=h_high)
|
||||
w_start = np.random.randint(low=0, high=w_high)
|
||||
return img[:, h_start: h_start+self.size[0], w_start: w_start+self.size[1]]
|
||||
|
||||
class AddPad(object):
|
||||
def __init__(self, padding, fill=0):
|
||||
self.padding = padding
|
||||
self.fill = fill
|
||||
if isinstance(self.padding, numbers.Number):
|
||||
self.pad_l = int(self.padding)
|
||||
self.pad_r = int(self.padding)
|
||||
self.pad_u = int(self.padding)
|
||||
self.pad_d = int(self.padding)
|
||||
elif isinstance(self.padding, (list, tuple)) and len(self.padding) == 4:
|
||||
self.pad_l = int(self.padding[0])
|
||||
self.pad_r = int(self.padding[1])
|
||||
self.pad_u = int(self.padding[2])
|
||||
self.pad_d = int(self.padding[3])
|
||||
else:
|
||||
print ("The type of padding is not right.")
|
||||
raise ValueError
|
||||
if self.pad_l <0 or self.pad_r < 0 or self.pad_u < 0 or self.pad_d < 0:
|
||||
raise ValueError
|
||||
if isinstance(self.fill, numbers.Number):
|
||||
self.fill_value = [self.fill]
|
||||
elif isinstance(self.fill, list):
|
||||
self.fill_value = self.fill
|
||||
|
||||
def __repr__(self):
|
||||
return self.__class__.__name__ + '(padding={0})'.format(self.padding)
|
||||
|
||||
def __call__(self, img):
|
||||
"""
|
||||
Args:
|
||||
img: a 3-dimensional torch tensor with shape [R,G,B]*H*W
|
||||
Returns:
|
||||
img: a 3-dimensional padded tensor with shape [R,G,B]*H'*W'
|
||||
"""
|
||||
if not (self.pad_l or self.pad_r or self.pad_u or self.pad_d):
|
||||
return img
|
||||
shape = img.shape
|
||||
img_ = torch.rand(shape[0], shape[1]+self.pad_u+self.pad_d, \
|
||||
shape[2]+self.pad_l+self.pad_r)
|
||||
for i in range(shape[0]):
|
||||
img_[i, 0:self.pad_u, :] = self.fill_value[i%len(self.fill_value)]
|
||||
img_[i, -(self.pad_d+1):-1, :] = self.fill_value[i%len(self.fill_value)]
|
||||
img_[i, :, 0:self.pad_l] = self.fill_value[i%len(self.fill_value)]
|
||||
img_[i, :, -(self.pad_r+1):-1] = self.fill_value[i%len(self.fill_value)]
|
||||
img_[i, self.pad_u:self.pad_u+shape[1], self.pad_l:self.pad_l+shape[2]] = img[i, :, :]
|
||||
return img_
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.init as init
|
||||
import torch.nn.functional as F
|
||||
from torch.autograd import Variable
|
||||
import numpy as np
|
||||
from .resnet import resnet50
|
||||
|
||||
|
||||
class DeepMAR_ResNet50(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
**kwargs
|
||||
):
|
||||
super(DeepMAR_ResNet50, self).__init__()
|
||||
# init the necessary parameter for netwokr structure
|
||||
if 'num_att' in kwargs:
|
||||
self.num_att = kwargs['num_att']
|
||||
else:
|
||||
self.num_att = 35
|
||||
if 'last_conv_stride' in kwargs:
|
||||
self.last_conv_stride = kwargs['last_conv_stride']
|
||||
else:
|
||||
self.last_conv_stride = 2
|
||||
if 'drop_pool5' in kwargs:
|
||||
self.drop_pool5 = kwargs['drop_pool5']
|
||||
else:
|
||||
self.drop_pool5 = True
|
||||
if 'drop_pool5_rate' in kwargs:
|
||||
self.drop_pool5_rate = kwargs['drop_pool5_rate']
|
||||
else:
|
||||
self.drop_pool5_rate = 0.5
|
||||
if 'pretrained' in kwargs:
|
||||
self.pretrained = kwargs['pretrained']
|
||||
else:
|
||||
self.pretrained = True
|
||||
|
||||
self.base = resnet50(pretrained=self.pretrained, last_conv_stride=self.last_conv_stride)
|
||||
|
||||
self.classifier = nn.Linear(2048, self.num_att)
|
||||
init.normal_(self.classifier.weight, std=0.001)
|
||||
init.constant_(self.classifier.bias, 0)
|
||||
|
||||
def forward(self, x):
|
||||
|
||||
x = self.base(x)
|
||||
x = F.avg_pool2d(x, x.shape[2:])
|
||||
# x = x.view(x.size(0), -1)
|
||||
x = torch.flatten(x, 1)
|
||||
if self.drop_pool5:
|
||||
# x = x.to("cpu")
|
||||
x = F.dropout(x, p=self.drop_pool5_rate, training=self.training)
|
||||
# x = x.to("npu")
|
||||
x = self.classifier(x)
|
||||
return x
|
||||
|
||||
class DeepMAR_ResNet50_ExtractFeature(object):
|
||||
"""
|
||||
A feature extraction function
|
||||
"""
|
||||
def __init__(self, model, **kwargs):
|
||||
self.model = model
|
||||
|
||||
def __call__(self, imgs):
|
||||
old_train_eval_model = self.model.training
|
||||
|
||||
# set the model to be eval
|
||||
self.model.eval()
|
||||
|
||||
# imgs should be Variable
|
||||
if not isinstance(imgs, Variable):
|
||||
print ('imgs should be type: Variable')
|
||||
raise ValueError
|
||||
# compute output
|
||||
score = self.model(imgs)
|
||||
score = score.data.cpu().numpy()
|
||||
|
||||
# set the model to be training
|
||||
self.model.train(old_train_eval_model)
|
||||
|
||||
return score
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
import torch.nn as nn
|
||||
import math
|
||||
import torch.utils.model_zoo as model_zoo
|
||||
import ssl
|
||||
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
|
||||
|
||||
__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',
|
||||
'resnet152']
|
||||
|
||||
|
||||
model_urls = {
|
||||
'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
|
||||
'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
|
||||
'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
|
||||
'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
|
||||
'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
|
||||
}
|
||||
|
||||
|
||||
def conv3x3(in_planes, out_planes, stride=1):
|
||||
"""3x3 convolution with padding"""
|
||||
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
|
||||
padding=1, bias=False)
|
||||
|
||||
|
||||
class BasicBlock(nn.Module):
|
||||
expansion = 1
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None):
|
||||
super(BasicBlock, self).__init__()
|
||||
self.conv1 = conv3x3(inplanes, planes, stride)
|
||||
self.bn1 = nn.BatchNorm2d(planes)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.conv2 = conv3x3(planes, planes)
|
||||
self.bn2 = nn.BatchNorm2d(planes)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
|
||||
def forward(self, x):
|
||||
residual = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
residual = self.downsample(x)
|
||||
|
||||
out += residual
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class Bottleneck(nn.Module):
|
||||
expansion = 4
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None):
|
||||
super(Bottleneck, self).__init__()
|
||||
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(planes)
|
||||
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
|
||||
padding=1, bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(planes)
|
||||
self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
|
||||
self.bn3 = nn.BatchNorm2d(planes * 4)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
|
||||
def forward(self, x):
|
||||
residual = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv3(out)
|
||||
out = self.bn3(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
residual = self.downsample(x)
|
||||
|
||||
out += residual
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class ResNet(nn.Module):
|
||||
|
||||
def __init__(self, block, layers, last_conv_stride=2):
|
||||
self.inplanes = 64
|
||||
super(ResNet, self).__init__()
|
||||
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
|
||||
bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(64)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
||||
self.layer1 = self._make_layer(block, 64, layers[0])
|
||||
self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
|
||||
self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
|
||||
self.layer4 = self._make_layer(block, 512, layers[3], stride=last_conv_stride)
|
||||
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
|
||||
m.weight.data.normal_(0, math.sqrt(2. / n))
|
||||
elif isinstance(m, nn.BatchNorm2d):
|
||||
m.weight.data.fill_(1)
|
||||
m.bias.data.zero_()
|
||||
|
||||
def _make_layer(self, block, planes, blocks, stride=1):
|
||||
downsample = None
|
||||
if stride != 1 or self.inplanes != planes * block.expansion:
|
||||
downsample = nn.Sequential(
|
||||
nn.Conv2d(self.inplanes, planes * block.expansion,
|
||||
kernel_size=1, stride=stride, bias=False),
|
||||
nn.BatchNorm2d(planes * block.expansion),
|
||||
)
|
||||
|
||||
layers = []
|
||||
layers.append(block(self.inplanes, planes, stride, downsample))
|
||||
self.inplanes = planes * block.expansion
|
||||
for i in range(1, blocks):
|
||||
layers.append(block(self.inplanes, planes))
|
||||
|
||||
return nn.Sequential(*layers)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.conv1(x)
|
||||
x = self.bn1(x)
|
||||
x = self.relu(x)
|
||||
x = self.maxpool(x)
|
||||
|
||||
x = self.layer1(x)
|
||||
x = self.layer2(x)
|
||||
x = self.layer3(x)
|
||||
x = self.layer4(x)
|
||||
|
||||
return x
|
||||
|
||||
def remove_fc(state_dict):
|
||||
""" Remove the fc layer parameter from state_dict. """
|
||||
for key, value in list(state_dict.items()):
|
||||
if key.startswith('fc.'):
|
||||
del state_dict[key]
|
||||
return state_dict
|
||||
|
||||
|
||||
def resnet18(pretrained=False, **kwargs):
|
||||
"""Constructs a ResNet-18 model.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)
|
||||
if pretrained:
|
||||
model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet18'])))
|
||||
return model
|
||||
|
||||
|
||||
def resnet34(pretrained=False, **kwargs):
|
||||
"""Constructs a ResNet-34 model.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs)
|
||||
if pretrained:
|
||||
model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet34'])))
|
||||
return model
|
||||
|
||||
|
||||
def resnet50(pretrained=False, **kwargs):
|
||||
"""Constructs a ResNet-50 model.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs)
|
||||
if pretrained:
|
||||
model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet50'])))
|
||||
return model
|
||||
|
||||
|
||||
def resnet101(pretrained=False, **kwargs):
|
||||
"""Constructs a ResNet-101 model.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs)
|
||||
if pretrained:
|
||||
model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet101'])))
|
||||
return model
|
||||
|
||||
|
||||
def resnet152(pretrained=False, **kwargs):
|
||||
"""Constructs a ResNet-152 model.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs)
|
||||
if pretrained:
|
||||
model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet152'])))
|
||||
return model
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
import os
|
||||
import torch
|
||||
from torch.autograd import Variable
|
||||
import numpy as np
|
||||
import copy
|
||||
import time
|
||||
import sys
|
||||
|
||||
|
||||
def extract_feat(feat_func, dataset, device_id, **kwargs):
|
||||
"""
|
||||
extract feature for images
|
||||
"""
|
||||
test_loader = torch.utils.data.DataLoader(
|
||||
dataset=dataset, batch_size=32,
|
||||
num_workers=32, pin_memory=True,
|
||||
drop_last=True)
|
||||
# extract feature for all the images of test/val identities
|
||||
start_time = time.time()
|
||||
total_eps = len(test_loader)
|
||||
N = len(dataset.image)
|
||||
start = 0
|
||||
with torch.no_grad():
|
||||
for ep, (imgs, labels) in enumerate(test_loader):
|
||||
# imgs_var = Variable(imgs).cuda()
|
||||
# imgs_var = Variable(imgs)
|
||||
imgs_var = Variable(imgs).to(device_id)
|
||||
feat_tmp = feat_func(imgs_var)
|
||||
batch_size = feat_tmp.shape[0]
|
||||
if ep == 0:
|
||||
feat = np.zeros((N, int(feat_tmp.size/batch_size)))
|
||||
feat[start:start+batch_size, :] = feat_tmp.reshape((batch_size, -1))
|
||||
start += batch_size
|
||||
end_time = time.time()
|
||||
print('{} batches done, total {:.2f}s'.format(total_eps, end_time-start_time))
|
||||
return feat
|
||||
|
||||
# attribute recognition evaluation
|
||||
def attribute_evaluate(feat_func, dataset, device_id, **kwargs):
|
||||
print ("extracting features for attribute recognition")
|
||||
pt_result = extract_feat(feat_func, dataset, device_id)
|
||||
# obain the attributes from the attribute dictionary
|
||||
print ("computing attribute recognition result")
|
||||
N = pt_result.shape[0]
|
||||
L = pt_result.shape[1]
|
||||
gt_result = np.zeros(pt_result.shape)
|
||||
# get the groundtruth attributes
|
||||
for idx, label in enumerate(dataset.label):
|
||||
gt_result[idx, :] = label
|
||||
pt_result[pt_result>=0] = 1
|
||||
pt_result[pt_result<0] = 0
|
||||
return attribute_evaluate_lidw(gt_result, pt_result)
|
||||
|
||||
def attribute_evaluate_lidw(gt_result, pt_result):
|
||||
"""
|
||||
Input:
|
||||
gt_result, pt_result, N*L, with 0/1
|
||||
Output:
|
||||
result
|
||||
a dictionary, including label-based and instance-based evaluation
|
||||
label-based: label_pos_acc, label_neg_acc, label_acc
|
||||
instance-based: instance_acc, instance_precision, instance_recall, instance_F1
|
||||
"""
|
||||
# obtain the label-based and instance-based accuracy
|
||||
# compute the label-based accuracy
|
||||
if gt_result.shape != pt_result.shape:
|
||||
print ('Shape beteen groundtruth and predicted results are different')
|
||||
# compute the label-based accuracy
|
||||
result = {}
|
||||
gt_pos = np.sum((gt_result == 1).astype(float), axis=0)
|
||||
gt_neg = np.sum((gt_result == 0).astype(float), axis=0)
|
||||
pt_pos = np.sum((gt_result == 1).astype(float) * (pt_result == 1).astype(float), axis=0)
|
||||
pt_neg = np.sum((gt_result == 0).astype(float) * (pt_result == 0).astype(float), axis=0)
|
||||
label_pos_acc = 1.0*pt_pos/gt_pos
|
||||
label_neg_acc = 1.0*pt_neg/gt_neg
|
||||
label_acc = (label_pos_acc + label_neg_acc)/2
|
||||
result['label_pos_acc'] = label_pos_acc
|
||||
result['label_neg_acc'] = label_neg_acc
|
||||
result['label_acc'] = label_acc
|
||||
# compute the instance-based accuracy
|
||||
# precision
|
||||
gt_pos = np.sum((gt_result == 1).astype(float), axis=1)
|
||||
pt_pos = np.sum((pt_result == 1).astype(float), axis=1)
|
||||
floatersect_pos = np.sum((gt_result == 1).astype(float)*(pt_result == 1).astype(float), axis=1)
|
||||
union_pos = np.sum(((gt_result == 1)+(pt_result == 1)).astype(float),axis=1)
|
||||
# avoid empty label in predicted results
|
||||
cnt_eff = float(gt_result.shape[0])
|
||||
for iter, key in enumerate(gt_pos):
|
||||
if key == 0:
|
||||
union_pos[iter] = 1
|
||||
pt_pos[iter] = 1
|
||||
gt_pos[iter] = 1
|
||||
cnt_eff = cnt_eff - 1
|
||||
continue
|
||||
if pt_pos[iter] == 0:
|
||||
pt_pos[iter] = 1
|
||||
instance_acc = np.sum(floatersect_pos/union_pos)/cnt_eff
|
||||
instance_precision = np.sum(floatersect_pos/pt_pos)/cnt_eff
|
||||
instance_recall = np.sum(floatersect_pos/gt_pos)/cnt_eff
|
||||
floatance_F1 = 2*instance_precision*instance_recall/(instance_precision+instance_recall)
|
||||
result['instance_acc'] = instance_acc
|
||||
result['instance_precision'] = instance_precision
|
||||
result['instance_recall'] = instance_recall
|
||||
result['instance_F1'] = floatance_F1
|
||||
return result
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
import os
|
||||
import pickle
|
||||
import datetime
|
||||
import time
|
||||
# from contextlib import contextmanger
|
||||
import torch
|
||||
from torch.autograd import Variable
|
||||
import random
|
||||
import numpy as np
|
||||
import torch.backends.cudnn as cudnn
|
||||
|
||||
def time_str(fmt=None):
|
||||
if fmt is None:
|
||||
fmt = '%Y-%m-%d_%H:%M:%S'
|
||||
return datetime.datetime.today().strftime(fmt)
|
||||
|
||||
def str2bool(v):
|
||||
return v.lower() in ("yes", "true", "1")
|
||||
|
||||
def is_iterable(obj):
|
||||
return hasattr(obj, '__len__')
|
||||
|
||||
def to_scalar(vt):
|
||||
"""
|
||||
transform a 1-length pytorch Variable or Tensor to scalar
|
||||
"""
|
||||
if isinstance(vt, Variable):
|
||||
return vt.data.cpu().numpy().flatten()[0]
|
||||
if torch.is_tensor(vt):
|
||||
return vt.cpu().numpy().flatten()[0]
|
||||
raise TypeError('Input should be a variable or tensor')
|
||||
|
||||
def set_seed(rand_seed):
|
||||
np.random.seed( rand_seed )
|
||||
random.seed( rand_seed )
|
||||
torch.backends.cudnn.enabled = True
|
||||
torch.manual_seed( rand_seed )
|
||||
torch.cuda.manual_seed( rand_seed )
|
||||
|
||||
def seed_everything(seed):
|
||||
random.seed(seed)
|
||||
os.environ['PYTHONHASHSEED'] = str(seed)
|
||||
np.random.seed(seed)
|
||||
torch.manual_seed(seed)
|
||||
torch.cuda.manual_seed(seed)
|
||||
torch.cuda.manual_seed_all(seed)
|
||||
cudnn.deterministic = True
|
||||
torch.backends.cudnn.deterministic = True
|
||||
torch.backends.cudnn.benchmark = False
|
||||
|
||||
def may_mkdir(fname):
|
||||
if not os.path.exists(os.path.dirname(os.path.abspath(fname))):
|
||||
os.makedirs(os.path.dirname(os.path.abspath(fname)))
|
||||
|
||||
class AverageMeter(object):
|
||||
"""
|
||||
Computes and stores the average and current value
|
||||
"""
|
||||
def __init__(self):
|
||||
self.val = 0
|
||||
self.avg = 0
|
||||
self.sum = 0
|
||||
self.count = 0
|
||||
def reset(self):
|
||||
self.val = 0
|
||||
self.avg = 0
|
||||
self.sum = 0
|
||||
self.count = 0
|
||||
def update(self, val, n=1):
|
||||
self.val = val
|
||||
self.sum += val * n
|
||||
self.count += n
|
||||
self.avg = float(self.sum) / (self.count + 1e-10)
|
||||
|
||||
class RunningAverageMeter(object):
|
||||
"""
|
||||
Computes and stores the running average and current value
|
||||
"""
|
||||
def __init__(self, hist=0.99):
|
||||
self.val = None
|
||||
self.avg = None
|
||||
self.hist = hist
|
||||
|
||||
def reset(self):
|
||||
self.val = None
|
||||
self.avg = None
|
||||
|
||||
def update(self, val):
|
||||
if self.avg is None:
|
||||
self.avg = val
|
||||
else:
|
||||
self.avg = self.avg * self.hist + val * (1 - self.hist)
|
||||
self.val = val
|
||||
|
||||
class RecentAverageMeter(object):
|
||||
"""
|
||||
Stores and computes the average of recent values
|
||||
"""
|
||||
def __init__(self, hist_size=100):
|
||||
self.hist_size = hist_size
|
||||
self.fifo = []
|
||||
self.val = 0
|
||||
|
||||
def reset(self):
|
||||
self.fifo = []
|
||||
self.val = 0
|
||||
|
||||
def update(self, val):
|
||||
self.val = val
|
||||
self.fifo.append(val)
|
||||
if len(self.fifo) > self.hist_size:
|
||||
del self.fifo[0]
|
||||
@property
|
||||
def avg(self):
|
||||
assert len(self.fifo) > 0
|
||||
return float(sum(self.fifo)) / len(self.fifo)
|
||||
|
||||
class ReDirectSTD(object):
|
||||
"""
|
||||
overwrites the sys.stdout or sys.stderr
|
||||
Args:
|
||||
fpath: file path
|
||||
console: one of ['stdout', 'stderr']
|
||||
immediately_visiable: False
|
||||
Usage example:
|
||||
ReDirectSTD('stdout.txt', 'stdout', False)
|
||||
ReDirectSTD('stderr.txt', 'stderr', False)
|
||||
"""
|
||||
def __init__(self, fpath=None, console='stdout', immediately_visiable=False):
|
||||
import sys
|
||||
import os
|
||||
assert console in ['stdout', 'stderr']
|
||||
self.console = sys.stdout if console == "stdout" else sys.stderr
|
||||
self.file = fpath
|
||||
self.f = None
|
||||
self.immediately_visiable = immediately_visiable
|
||||
if fpath is not None:
|
||||
# Remove existing log file
|
||||
if os.path.exists(fpath):
|
||||
os.remove(fpath)
|
||||
if console == 'stdout':
|
||||
sys.stdout = self
|
||||
else:
|
||||
sys.stderr = self
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
def __exit__(self, **args):
|
||||
self.close()
|
||||
|
||||
def write(self, msg):
|
||||
self.console.write(msg)
|
||||
if self.file is not None:
|
||||
if not os.path.exists(os.path.dirname(os.path.abspath(self.file))):
|
||||
os.mkdir(os.path.dirname(os.path.abspath(self.file)))
|
||||
if self.immediately_visiable:
|
||||
with open(self.file, 'a') as f:
|
||||
f.write(msg)
|
||||
else:
|
||||
if self.f is None:
|
||||
self.f = open(self.file, 'w')
|
||||
self.f.write(msg)
|
||||
|
||||
def flush(self):
|
||||
self.console.flush()
|
||||
if self.f is not None:
|
||||
self.f.flush()
|
||||
import os
|
||||
os.fsync(self.f.fileno())
|
||||
|
||||
def close(self):
|
||||
self.console.close()
|
||||
if self.f is not None:
|
||||
self.f.close()
|
||||
|
||||
def find_index(seq, item):
|
||||
for i, x in enumerate(seq):
|
||||
if item == x:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def set_devices(sys_device_ids):
|
||||
"""
|
||||
Args:
|
||||
sys_device_ids: a tuple; which GPUs to use
|
||||
e.g. sys_device_ids = (), only use cpu
|
||||
sys_device_ids = (3,), use the 4-th gpu
|
||||
sys_device_ids = (0, 1, 2, 3,), use the first 4 gpus
|
||||
sys_device_ids = (0, 2, 4,), use the 1, 3 and 5 gpus
|
||||
"""
|
||||
import os
|
||||
visiable_devices = ''
|
||||
for i in sys_device_ids:
|
||||
visiable_devices += '{}, '.format(i)
|
||||
os.environ['CUDA_VISIBLE_DEVICES'] = visiable_devices
|
||||
# Return wrappers
|
||||
# Models and user defined Variables/Tensors would be transferred to
|
||||
# the first device
|
||||
device_id = 0 if len(sys_device_ids) > 0 else -1
|
||||
|
||||
def transfer_optims(optims, device_id=-1):
|
||||
for optim in optims:
|
||||
if isinstance(optim, torch.optim.Optimizer):
|
||||
transfer_optim_state(optim.state, device_id=device_id)
|
||||
|
||||
def transfer_optim_state(state, device_id=-1):
|
||||
for key, val in state.items():
|
||||
if isinstance(val, dict):
|
||||
transfer_optim_state(val, device_id=device_id)
|
||||
elif isinstance(val, Variable):
|
||||
raise RuntimeError("Oops, state[{}] is a Variable!".format(key))
|
||||
elif isinstance(val, torch.nn.Parameter):
|
||||
raise RuntimeError("Oops, state[{}] is a Parameter!".format(key))
|
||||
else:
|
||||
try:
|
||||
if device_id == -1:
|
||||
state[key] = val.cpu()
|
||||
else:
|
||||
#state[key] = val.cuda(device=device_id)
|
||||
state[key] = val.npu(device=device_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def load_state_dict(model, src_state_dict):
|
||||
"""
|
||||
copy parameter from src_state_dict to model
|
||||
Arguments:
|
||||
model: A torch.nn.Module object
|
||||
src_state_dict: a dict containing parameters and persistent buffers
|
||||
"""
|
||||
from torch.nn import Parameter
|
||||
dest_state_dict = model.state_dict()
|
||||
for name, param in src_state_dict.items():
|
||||
if name not in dest_state_dict:
|
||||
continue
|
||||
if isinstance(param, Parameter):
|
||||
param = param.data
|
||||
try:
|
||||
dest_state_dict[name].copy_(param)
|
||||
except Exception:
|
||||
print("Warning: Error occurs when copying '{}'".format(name))
|
||||
|
||||
src_missing = set(dest_state_dict.keys()) - set(src_state_dict.keys())
|
||||
if len(src_missing) > 0:
|
||||
print ("Keys not found in source state_dict: ")
|
||||
for n in src_missing:
|
||||
print('\t', n)
|
||||
|
||||
dest_missint = set(src_state_dict.keys()) - set(dest_state_dict.keys())
|
||||
if len(dest_missint):
|
||||
print ("Keys not found in destination state_dict: ")
|
||||
for n in dest_missint:
|
||||
print('\t', n)
|
||||
|
||||
def load_ckpt(modules_optims, ckpt_file, load_to_cpu=True, verbose=True):
|
||||
"""
|
||||
load state_dict of module & optimizer from file
|
||||
Args:
|
||||
modules_optims: A two-element list which contains module and optimizer
|
||||
ckpt_file: the check point file
|
||||
load_to_cpu: Boolean, whether to transform tensors in model & optimizer to cpu type
|
||||
"""
|
||||
map_location = (lambda storage, loc: storage) if load_to_cpu else None
|
||||
ckpt = torch.load(ckpt_file, map_location=map_location)
|
||||
for m, sd in zip(modules_optims, ckpt['state_dicts']):
|
||||
m.load_state_dict(sd)
|
||||
if verbose:
|
||||
print("Resume from ckpt {}, \nepoch: {}, scores: {}".format(
|
||||
ckpt_file, ckpt['ep'], ckpt['scores']))
|
||||
return ckpt['ep'], ckpt['scores']
|
||||
|
||||
def save_ckpt(modules_optims, ep, scores, ckpt_file):
|
||||
"""
|
||||
save state_dict of modules/optimizers to file
|
||||
Args:
|
||||
modules_optims: a two-element list which contains a module and a optimizer
|
||||
ep: the current epoch number
|
||||
scores: the performance of current module
|
||||
ckpt_file: the check point file path
|
||||
Note:
|
||||
torch.save() reserves device type and id of tensors to save.
|
||||
So when loading ckpt, you have to inform torch.load() to load these tensors
|
||||
to cpu or your desired gpu, if you change devices.
|
||||
"""
|
||||
state_dicts = [m.state_dict() for m in modules_optims]
|
||||
ckpt = dict(state_dicts = state_dicts,
|
||||
ep = ep,
|
||||
scores = scores)
|
||||
if not os.path.exists(os.path.dirname(os.path.abspath(ckpt_file))):
|
||||
os.mkdir(os.path.dirname(os.path.abspath(ckpt_file)))
|
||||
torch.save(ckpt, ckpt_file)
|
||||
|
||||
def adjust_lr_staircase(param_groups, base_lrs, ep, decay_at_epochs, factor):
|
||||
""" Multiplied by a factor at the beging of specified epochs. Different
|
||||
params groups specify thier own base learning rates.
|
||||
Args:
|
||||
param_groups: a list of params
|
||||
base_lrs: starting learning rate, len(base_lrs) = len(params_groups)
|
||||
ep: current epoch, ep >= 1
|
||||
decay_at_epochs: a list or tuple; learning rates are multiplied by a factor
|
||||
at the begining of these epochs
|
||||
factor: a number in range (0, 1)
|
||||
Example:
|
||||
base_lrs = [0.1, 0.01]
|
||||
decay_at_epochs = [51, 101]
|
||||
factor = 0.1
|
||||
Note:
|
||||
It is meant to be called at the begining of an epoch
|
||||
"""
|
||||
assert len(base_lrs) == len(param_groups), \
|
||||
'You should specify base lr for each param group.'
|
||||
assert ep >= 1, "Current epoch number should be >= 1"
|
||||
|
||||
if ep not in decay_at_epochs:
|
||||
return
|
||||
|
||||
ind = find_index(decay_at_epochs, ep)
|
||||
for i, (g, base_lr) in enumerate(zip(param_groups, base_lrs)):
|
||||
g['lr'] = base_lr * factor ** (ind + 1)
|
||||
print('=====> Param group {}: lr adjusted to {:.10f}'
|
||||
.format(i, g['lr']).rstrip('0'))
|
||||
|
||||
def adjust_lr(optimizer, ep, finetuned_params_lr):
|
||||
"""Sets the learning rate to the initial LR decayed by 10 every 30 epochs"""
|
||||
# lr = args.lr * (0.1 ** (ep// 30))
|
||||
lr = finetuned_params_lr * (0.96 ** (ep // 8)) #decreasing the learning rate by 4% every 8 epoch
|
||||
for param_group in optimizer.param_groups:
|
||||
param_group['lr'] = lr
|
||||
|
||||
def may_set_mode(maybe_modules, mode):
|
||||
"""
|
||||
maybe_modules, an object or a list of objects.
|
||||
"""
|
||||
assert mode in ['train', 'eval']
|
||||
if not is_iterable(maybe_modules):
|
||||
maybe_modules = [maybe_modules]
|
||||
for m in maybe_modules:
|
||||
if isinstance(m, torch.nn.Module):
|
||||
if mode == 'train':
|
||||
m.train()
|
||||
else:
|
||||
m.eval()
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,141 @@
|
||||
import sys
|
||||
import os
|
||||
import numpy as np
|
||||
import random
|
||||
import math
|
||||
|
||||
import torch
|
||||
import torchvision.transforms as transforms
|
||||
from torch.autograd import Variable
|
||||
from torch.nn.parallel import DataParallel
|
||||
import pickle
|
||||
import time
|
||||
import argparse
|
||||
from PIL import Image, ImageFont, ImageDraw
|
||||
|
||||
from baseline.model.DeepMAR import DeepMAR_ResNet50
|
||||
from baseline.utils.utils import str2bool
|
||||
from baseline.utils.utils import save_ckpt, load_ckpt
|
||||
from baseline.utils.utils import load_state_dict
|
||||
from baseline.utils.utils import set_devices
|
||||
from baseline.utils.utils import set_seed
|
||||
|
||||
|
||||
class Config(object):
|
||||
def __init__(self):
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-d', '--sys_device_ids', type=eval, default=(0,))
|
||||
parser.add_argument('--set_seed', type=str2bool, default=False)
|
||||
# model
|
||||
parser.add_argument('--resize', type=eval, default=(224, 224))
|
||||
parser.add_argument('--last_conv_stride', type=int, default=2, choices=[1,2])
|
||||
# demo image
|
||||
parser.add_argument('--demo_image', type=str, default='./dataset/demo/demo_image.png')
|
||||
## dataset parameter
|
||||
parser.add_argument('--dataset', type=str, default='peta',
|
||||
choices=['peta','rap', 'pa100k'])
|
||||
# utils
|
||||
parser.add_argument('--load_model_weight', type=str2bool, default=True)
|
||||
parser.add_argument('--model_weight_file', type=str, default='./exp/deepmar_resnet50/peta/partition0/run1/model/ckpt_epoch150.pth')
|
||||
args = parser.parse_args()
|
||||
|
||||
# gpu ids
|
||||
self.sys_device_ids = args.sys_device_ids
|
||||
|
||||
# random
|
||||
self.set_seed = args.set_seed
|
||||
if self.set_seed:
|
||||
self.rand_seed = 0
|
||||
else:
|
||||
self.rand_seed = None
|
||||
self.resize = args.resize
|
||||
self.mean = [0.485, 0.456, 0.406]
|
||||
self.std = [0.229, 0.224, 0.225]
|
||||
|
||||
# utils
|
||||
self.load_model_weight = args.load_model_weight
|
||||
self.model_weight_file = args.model_weight_file
|
||||
if self.load_model_weight:
|
||||
if self.model_weight_file == '':
|
||||
print ('Please input the model_weight_file if you want to load model weight')
|
||||
raise ValueError
|
||||
# dataset
|
||||
datasets = dict()
|
||||
datasets['peta'] = './dataset/peta/peta_dataset.pkl'
|
||||
datasets['rap'] = './dataset/rap/rap_dataset.pkl'
|
||||
datasets['pa100k'] = './dataset/pa100k/pa100k_dataset.pkl'
|
||||
|
||||
if args.dataset in datasets:
|
||||
dataset = pickle.load(open(datasets[args.dataset]))
|
||||
else:
|
||||
print ('%s does not exist.'%(args.dataset))
|
||||
raise ValueError
|
||||
self.att_list = [dataset['att_name'][i] for i in dataset['selected_attribute']]
|
||||
|
||||
# demo image
|
||||
self.demo_image = args.demo_image
|
||||
|
||||
# model
|
||||
model_kwargs = dict()
|
||||
model_kwargs['num_att'] = len(self.att_list)
|
||||
model_kwargs['last_conv_stride'] = args.last_conv_stride
|
||||
self.model_kwargs = model_kwargs
|
||||
|
||||
### main function ###
|
||||
cfg = Config()
|
||||
|
||||
# dump the configuration to log.
|
||||
import pprint
|
||||
print('-' * 60)
|
||||
print('cfg.__dict__')
|
||||
pprint.pprint(cfg.__dict__)
|
||||
print('-' * 60)
|
||||
|
||||
# set the random seed
|
||||
if cfg.set_seed:
|
||||
set_seed( cfg.rand_seed )
|
||||
# init the gpu ids
|
||||
set_devices(cfg.sys_device_ids)
|
||||
|
||||
# dataset
|
||||
normalize = transforms.Normalize(mean=cfg.mean, std=cfg.std)
|
||||
test_transform = transforms.Compose([
|
||||
transforms.Resize(cfg.resize),
|
||||
transforms.ToTensor(),
|
||||
normalize,])
|
||||
|
||||
### Att model ###
|
||||
model = DeepMAR_ResNet50(**cfg.model_kwargs)
|
||||
|
||||
# load model weight if necessary
|
||||
if cfg.load_model_weight:
|
||||
map_location = (lambda storage, loc:storage)
|
||||
ckpt = torch.load(cfg.model_weight_file, map_location=map_location)
|
||||
model.load_state_dict(ckpt['state_dicts'][0])
|
||||
|
||||
model.cuda()
|
||||
model.eval()
|
||||
|
||||
# load one image
|
||||
img = Image.open(cfg.demo_image)
|
||||
img_trans = test_transform( img )
|
||||
img_trans = torch.unsqueeze(img_trans, dim=0)
|
||||
img_var = Variable(img_trans).cuda()
|
||||
score = model(img_var).data.cpu().numpy()
|
||||
|
||||
# show the score in command line
|
||||
for idx in range(len(cfg.att_list)):
|
||||
if score[0, idx] >= 0:
|
||||
print ('%s: %.2f'%(cfg.att_list[idx], score[0, idx]))
|
||||
|
||||
# show the score in the image
|
||||
img = img.resize(size=(256, 512), resample=Image.BILINEAR)
|
||||
draw = ImageDraw.Draw(img)
|
||||
positive_cnt = 0
|
||||
for idx in range(len(cfg.att_list)):
|
||||
if score[0, idx] >= 0:
|
||||
txt = '%s: %.2f'%(cfg.att_list[idx], score[0, idx])
|
||||
draw.text((10, 10 + 10*positive_cnt), txt, (255, 0, 0))
|
||||
positive_cnt += 1
|
||||
img.save('./dataset/demo/demo_image_result.png')
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
import sys
|
||||
import os
|
||||
import numpy as np
|
||||
import random
|
||||
import math
|
||||
|
||||
import torch
|
||||
import torch.optim as optim
|
||||
import torchvision.transforms as transforms
|
||||
import torch.nn.functional as F
|
||||
import torch.backends.cudnn as cudnn
|
||||
from torch.autograd import Variable
|
||||
from torch.nn.parallel import DataParallel
|
||||
import pickle
|
||||
import time
|
||||
import argparse
|
||||
import pdb
|
||||
import sys
|
||||
from torch.utils.tensorboard import SummaryWriter
|
||||
|
||||
from baseline.dataset import add_transforms
|
||||
from baseline.dataset.Dataset import AttDataset
|
||||
from baseline.model.DeepMAR import DeepMAR_ResNet50
|
||||
from baseline.model.DeepMAR import DeepMAR_ResNet50_ExtractFeature
|
||||
from baseline.utils.evaluate import attribute_evaluate
|
||||
from baseline.utils.utils import str2bool
|
||||
from baseline.utils.utils import transfer_optim_state
|
||||
from baseline.utils.utils import time_str
|
||||
from baseline.utils.utils import save_ckpt, load_ckpt
|
||||
from baseline.utils.utils import load_state_dict
|
||||
from baseline.utils.utils import ReDirectSTD
|
||||
from baseline.utils.utils import adjust_lr_staircase
|
||||
from baseline.utils.utils import adjust_lr
|
||||
from baseline.utils.utils import set_devices
|
||||
from baseline.utils.utils import AverageMeter
|
||||
from baseline.utils.utils import to_scalar
|
||||
from baseline.utils.utils import may_set_mode
|
||||
from baseline.utils.utils import may_mkdir
|
||||
from baseline.utils.utils import set_seed
|
||||
from baseline.utils.utils import seed_everything
|
||||
|
||||
# Apex
|
||||
import numpy as np
|
||||
from apex import amp
|
||||
import torch.npu
|
||||
|
||||
from benchmark_log import hwlog
|
||||
from benchmark_log.basic_utils import get_environment_info
|
||||
from benchmark_log.basic_utils import get_model_parameter
|
||||
|
||||
hwlog.ROOT_DIR = os.path.split(os.path.abspath(__file__))[0]
|
||||
cpu_info, npu_info, framework_info, os_info, benchmark_version = get_environment_info("pytorch")
|
||||
config_info = get_model_parameter("pytorch_config")
|
||||
initinal_data = {"base_lr": 0.1, "dataset": "imagenet", "optimizer": "SGD", "loss_scale": 1024}
|
||||
hwlog.remark_print(key=hwlog.CPU_INFO, value=cpu_info)
|
||||
hwlog.remark_print(key=hwlog.NPU_INFO, value=npu_info)
|
||||
hwlog.remark_print(key=hwlog.OS_INFO, value=os_info)
|
||||
hwlog.remark_print(key=hwlog.FRAMEWORK_INFO, value=framework_info)
|
||||
hwlog.remark_print(key=hwlog.BENCHMARK_VERSION, value=benchmark_version)
|
||||
hwlog.remark_print(key=hwlog.CONFIG_INFO, value=config_info)
|
||||
hwlog.remark_print(key=hwlog.BASE_LR, value=initinal_data.get("base_lr"))
|
||||
hwlog.remark_print(key=hwlog.DATASET, value=initinal_data.get("dataset"))
|
||||
hwlog.remark_print(key=hwlog.OPT_NAME, value=initinal_data.get("optimizer"))
|
||||
hwlog.remark_print(key=hwlog.LOSS_SCALE, value=initinal_data.get("loss_scale"))
|
||||
|
||||
CALCULATE_DEVICE = "npu:7"
|
||||
PRINT_DEVICE = "cpu"
|
||||
|
||||
class Config(object):
|
||||
def __init__(self):
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--npu', type=int, default=0, help='NPU id to use.')
|
||||
parser.add_argument('--set_seed', type=str2bool, default=False)
|
||||
## dataset parameter
|
||||
parser.add_argument('--dataset', type=str, default='peta',
|
||||
choices=['peta','rap', 'pa100k', 'rap2'])
|
||||
parser.add_argument('--save_dir', type=str, default='/home/zhusiyi/dataset/peta/')
|
||||
parser.add_argument('--split', type=str, default='trainval',
|
||||
choices=['trainval', 'train'])
|
||||
parser.add_argument('--test_split', type=str, default='test')
|
||||
parser.add_argument('--partition_idx', type=int, default=0)
|
||||
parser.add_argument('--resize', type=eval, default=(224, 224))
|
||||
parser.add_argument('--mirror', type=str2bool, default=True)
|
||||
parser.add_argument('--batch_size', type=int, default=32)
|
||||
parser.add_argument('--workers', type=int, default=2)
|
||||
# model
|
||||
parser.add_argument('--num_att', type=int, default=35)
|
||||
parser.add_argument('--pretrained', type=str2bool, default=True)
|
||||
parser.add_argument('--last_conv_stride', type=int, default=2, choices=[1,2])
|
||||
parser.add_argument('--drop_pool5', type=str2bool, default=True)
|
||||
parser.add_argument('--drop_pool5_rate', type=float, default=0.5)
|
||||
|
||||
parser.add_argument('--sgd_weight_decay', type=float, default=0.0005)
|
||||
parser.add_argument('--sgd_momentum', type=float, default=0.9)
|
||||
parser.add_argument('--new_params_lr', type=float, default=0.001)
|
||||
parser.add_argument('--finetuned_params_lr', type=float, default=0.001)
|
||||
parser.add_argument('--staircase_decay_at_epochs', type=eval,
|
||||
default=(51, ))
|
||||
parser.add_argument('--staircase_decay_multiple_factor', type=float,
|
||||
default=0.1)
|
||||
parser.add_argument('--total_epochs', type=int, default=150)
|
||||
parser.add_argument('--weighted_entropy', type=str2bool, default=True)
|
||||
# utils
|
||||
parser.add_argument('--resume', type=str2bool, default=False)
|
||||
parser.add_argument('--ckpt_file', type=str, default='')
|
||||
parser.add_argument('--load_model_weight', type=str2bool, default=False)
|
||||
parser.add_argument('--model_weight_file', type=str, default='')
|
||||
parser.add_argument('--test_only', type=str2bool, default=False)
|
||||
parser.add_argument('--exp_dir', type=str, default='')
|
||||
parser.add_argument('--exp_subpath', type=str, default='deepmar_resnet50')
|
||||
parser.add_argument('--log_to_file', type=str2bool, default=True)
|
||||
parser.add_argument('--steps_per_log', type=int, default=20)
|
||||
parser.add_argument('--epochs_per_val', type=int, default=10)
|
||||
parser.add_argument('--epochs_per_save', type=int, default=50)
|
||||
parser.add_argument('--run', type=int, default=1)
|
||||
# apex
|
||||
parser.add_argument('--amp', default=False, action='store_true',
|
||||
help='use amp to train the model')
|
||||
parser.add_argument('--loss_scale', default=-1., type=float,
|
||||
help='loss scale using in amp, default -1 means dynamic')
|
||||
parser.add_argument('--opt_level', default='O1', type=str,
|
||||
help='opt level using in amp, default O1 means FP16')
|
||||
args = parser.parse_args()
|
||||
|
||||
# gpu ids
|
||||
self.npu = args.npu
|
||||
# random
|
||||
self.set_seed = args.set_seed
|
||||
if self.set_seed:
|
||||
self.seed = 0
|
||||
else:
|
||||
self.seed = None
|
||||
# amp
|
||||
self.amp = args.amp
|
||||
self.loss_scale = args.loss_scale
|
||||
self.opt_level = args.opt_level
|
||||
# run time index
|
||||
self.run = args.run
|
||||
# Dataset #
|
||||
datasets = dict()
|
||||
#datasets['peta'] = '/home/zhusiyi/dataset/peta/peta_dataset.pkl'
|
||||
#datasets['peta'] = os.path.join(os.path.abspath(os.path.dirname(__file__)),'dataset/peta/peta_dataset.pkl')
|
||||
datasets['peta'] = args.save_dir + '/peta_dataset.pkl'
|
||||
partitions = dict()
|
||||
#partitions['peta'] = '/home/zhusiyi/dataset/peta/peta_partition.pkl'
|
||||
#partitions['peta'] = os.path.join(os.path.abspath(os.path.dirname(__file__)),'dataset/peta/peta_partition.pkl')
|
||||
partitions['peta'] = args.save_dir + '/peta_partition.pkl'
|
||||
|
||||
self.dataset_name = args.dataset
|
||||
if args.dataset not in datasets or args.dataset not in partitions:
|
||||
print ("Please select the right dataset name.")
|
||||
raise ValueError
|
||||
else:
|
||||
self.dataset = datasets[args.dataset]
|
||||
self.partition = partitions[args.dataset]
|
||||
self.partition_idx = args.partition_idx
|
||||
self.split = args.split
|
||||
self.test_split = args.test_split
|
||||
self.resize = args.resize
|
||||
self.mirror = args.mirror
|
||||
self.mean = [0.485, 0.456, 0.406]
|
||||
self.std = [0.229, 0.224, 0.225]
|
||||
self.batch_size = args.batch_size
|
||||
self.workers = args.workers
|
||||
# optimization
|
||||
self.sgd_momentum = args.sgd_momentum
|
||||
self.sgd_weight_decay = args.sgd_weight_decay
|
||||
self.new_params_lr = args.new_params_lr
|
||||
self.finetuned_params_lr = args.finetuned_params_lr
|
||||
self.staircase_decay_at_epochs = args.staircase_decay_at_epochs
|
||||
self.staircase_decay_multiple_factor = args.staircase_decay_multiple_factor
|
||||
self.total_epochs = args.total_epochs
|
||||
self.weighted_entropy = args.weighted_entropy
|
||||
|
||||
# utils
|
||||
self.resume = args.resume
|
||||
self.ckpt_file = args.ckpt_file
|
||||
if self.resume:
|
||||
if self.ckpt_file == '':
|
||||
print ('Please input the ckpt_file if you want to resume training')
|
||||
raise ValueError
|
||||
self.load_model_weight = args.load_model_weight
|
||||
self.model_weight_file = args.model_weight_file
|
||||
if self.load_model_weight:
|
||||
if self.model_weight_file == '':
|
||||
print ('Please input the model_weight_file if you want to load model weight')
|
||||
raise ValueError
|
||||
self.test_only = args.test_only
|
||||
self.exp_dir = args.exp_dir
|
||||
self.exp_subpath = args.exp_subpath
|
||||
self.log_to_file = args.log_to_file
|
||||
self.steps_per_log = args.steps_per_log
|
||||
self.epochs_per_val = args.epochs_per_val
|
||||
self.epochs_per_save = args.epochs_per_save
|
||||
self.run = args.run
|
||||
|
||||
# for model
|
||||
model_kwargs = dict()
|
||||
model_kwargs['num_att'] = args.num_att
|
||||
model_kwargs['last_conv_stride'] = args.last_conv_stride
|
||||
model_kwargs['drop_pool5'] = args.drop_pool5
|
||||
model_kwargs['drop_pool5_rate'] = args.drop_pool5_rate
|
||||
self.model_kwargs = model_kwargs
|
||||
# for evaluation
|
||||
self.test_kwargs = dict()
|
||||
|
||||
if self.exp_dir == '':
|
||||
self.exp_dir = os.path.join('exp',
|
||||
'{}'.format(self.exp_subpath),
|
||||
'{}'.format(self.dataset_name),
|
||||
'partition{}'.format(self.partition_idx),
|
||||
'run{}'.format(self.run))
|
||||
self.stdout_file = os.path.join(self.exp_dir, \
|
||||
'log', 'stdout_{}.txt'.format(time_str()))
|
||||
self.stderr_file = os.path.join(self.exp_dir, \
|
||||
'log', 'stderr_{}.txt'.format(time_str()))
|
||||
may_mkdir(self.stdout_file)
|
||||
|
||||
### main function ###
|
||||
cfg = Config()
|
||||
|
||||
# log
|
||||
if cfg.log_to_file:
|
||||
ReDirectSTD(cfg.stdout_file, 'stdout', False)
|
||||
ReDirectSTD(cfg.stderr_file, 'stderr', False)
|
||||
|
||||
# dump the configuration to log.
|
||||
import pprint
|
||||
print('-' * 60)
|
||||
print('cfg.__dict__')
|
||||
pprint.pprint(cfg.__dict__)
|
||||
print('-' * 60)
|
||||
|
||||
# set the random seed
|
||||
print(cfg.seed)
|
||||
if cfg.set_seed:
|
||||
set_seed(cfg.seed)
|
||||
seed_everything(cfg.seed)
|
||||
|
||||
# init the npu ids
|
||||
CALCULATE_DEVICE = "npu:{}".format(cfg.npu)
|
||||
torch.npu.set_device(CALCULATE_DEVICE)
|
||||
|
||||
# dataset
|
||||
normalize = transforms.Normalize(mean=cfg.mean, std=cfg.std)
|
||||
transform = transforms.Compose([
|
||||
transforms.Resize(cfg.resize),
|
||||
transforms.RandomHorizontalFlip(),
|
||||
transforms.ToTensor(), # 3*H*W, [0, 1]
|
||||
normalize,]) # normalize with mean/std
|
||||
# by a subset of attributes
|
||||
train_set = AttDataset(
|
||||
dataset = cfg.dataset,
|
||||
partition = cfg.partition,
|
||||
split = cfg.split,
|
||||
partition_idx= cfg.partition_idx,
|
||||
transform = transform)
|
||||
|
||||
num_att = len(train_set.dataset['selected_attribute'])
|
||||
cfg.model_kwargs['num_att'] = num_att
|
||||
|
||||
train_loader = torch.utils.data.DataLoader(
|
||||
dataset = train_set,
|
||||
batch_size = cfg.batch_size,
|
||||
shuffle = True,
|
||||
num_workers = cfg.workers,
|
||||
pin_memory = True,
|
||||
drop_last = True)
|
||||
|
||||
test_transform = transforms.Compose([
|
||||
transforms.Resize(cfg.resize),
|
||||
transforms.ToTensor(),
|
||||
normalize,])
|
||||
|
||||
test_set = AttDataset(
|
||||
dataset = cfg.dataset,
|
||||
partition = cfg.partition,
|
||||
split = cfg.test_split,
|
||||
partition_idx = cfg.partition_idx,
|
||||
transform = test_transform)
|
||||
|
||||
### Att model ###
|
||||
model = DeepMAR_ResNet50(**cfg.model_kwargs)
|
||||
|
||||
# Optimizer
|
||||
finetuned_params = []
|
||||
new_params = []
|
||||
for n, p in model.named_parameters():
|
||||
if n.find('classifier') >=0:
|
||||
new_params.append(p)
|
||||
else:
|
||||
finetuned_params.append(p)
|
||||
param_groups = [{'params': finetuned_params, 'lr': cfg.finetuned_params_lr},
|
||||
{'params': new_params, 'lr': cfg.new_params_lr}]
|
||||
|
||||
optimizer = optim.SGD(
|
||||
param_groups,
|
||||
momentum = cfg.sgd_momentum,
|
||||
weight_decay = cfg.sgd_weight_decay)
|
||||
|
||||
model = model.to(CALCULATE_DEVICE)
|
||||
# apex
|
||||
if cfg.amp:
|
||||
# Initialization
|
||||
model, optimizer = amp.initialize(model, optimizer, opt_level=cfg.opt_level, loss_scale=cfg.loss_scale)
|
||||
print("=> Using amp mode.")
|
||||
|
||||
|
||||
# using the weighted cross entropy loss
|
||||
if cfg.weighted_entropy:
|
||||
rate = np.array(train_set.partition['weight_' + cfg.split][cfg.partition_idx])
|
||||
rate = rate[train_set.dataset['selected_attribute']].tolist()
|
||||
else:
|
||||
rate = None
|
||||
# compute the weight of positive and negative
|
||||
if rate is None:
|
||||
weight_pos = [1 for i in range(num_att)]
|
||||
weight_neg = [1 for i in range(num_att)]
|
||||
else:
|
||||
if len(rate) != num_att:
|
||||
print ("the length of rate should be equal to %d" % (num_att))
|
||||
raise ValueError
|
||||
weight_pos = []
|
||||
weight_neg = []
|
||||
for idx, v in enumerate(rate):
|
||||
weight_pos.append(math.exp(1.0 - v))
|
||||
weight_neg.append(math.exp(v))
|
||||
|
||||
# bind the model and optimizer
|
||||
modules_optims = [model, optimizer]
|
||||
|
||||
# load model weight if necessary
|
||||
if cfg.load_model_weight:
|
||||
map_location = (lambda storage, loc:storage)
|
||||
ckpt = torch.load(cfg.model_weight_file, map_location=map_location)
|
||||
model.load_state_dict(ckpt['state_dicts'][0], strict=False)
|
||||
# print(ckpt['state_dicts'][0])
|
||||
|
||||
### Resume or not ###
|
||||
if cfg.resume:
|
||||
# store the model, optimizer, epoch
|
||||
start_epoch, scores = load_ckpt(modules_optims, cfg.ckpt_file)
|
||||
else:
|
||||
start_epoch = 0
|
||||
|
||||
model = torch.nn.DataParallel(model)
|
||||
# model_w.cuda()
|
||||
transfer_optim_state(state=optimizer.state, device_id=cfg.npu)
|
||||
|
||||
# cudnn.benchmark = True
|
||||
# for evaluation
|
||||
feat_func_att = DeepMAR_ResNet50_ExtractFeature(model=model)
|
||||
|
||||
def attribute_evaluate_subfunc(feat_func, test_set, device_id, **test_kwargs):
|
||||
""" evaluate the attribute recognition precision """
|
||||
result = attribute_evaluate(feat_func, test_set, device_id, **test_kwargs)
|
||||
print ('-' * 60)
|
||||
print ('Evaluation on %s set:' % (cfg.test_split))
|
||||
print ('Label-based evaluation: \n mA: %.4f'%(np.mean(result['label_acc'])))
|
||||
print ('Instance-based evaluation: \n Acc: %.4f, Prec: %.4f, Rec: %.4f, F1: %.4f' \
|
||||
%(result['instance_acc'], result['instance_precision'], result['instance_recall'], result['instance_F1']))
|
||||
print ('-' * 60)
|
||||
hwlog.remark_print(key=hwlog.ACC, value="{:.4f}".format(result['instance_acc']))
|
||||
hwlog.remark_print(key=hwlog.PREC, value="{:.4f}".format(result['instance_precision']))
|
||||
hwlog.remark_print(key=hwlog.REC, value="{:.4f}".format(result['instance_recall']))
|
||||
hwlog.remark_print(key=hwlog.F1, value="{:.4f}".format(result['instance_recall']))
|
||||
return result['instance_acc']
|
||||
|
||||
|
||||
# print the model into log
|
||||
# test only
|
||||
if cfg.test_only:
|
||||
print ('test with feat_func_att')
|
||||
attribute_evaluate_subfunc(feat_func_att, test_set, **cfg.test_kwargs)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
# writer = SummaryWriter(os.path.join('runs/deepmar', str(cfg.npu)))
|
||||
|
||||
# training
|
||||
for epoch in range(start_epoch, cfg.total_epochs):
|
||||
if cfg.seed is not None:
|
||||
cfg.seed += 1
|
||||
seed_everything(cfg.seed)
|
||||
# adjust the learning rate
|
||||
adjust_lr_staircase(
|
||||
optimizer.param_groups,
|
||||
[cfg.finetuned_params_lr, cfg.new_params_lr],
|
||||
epoch + 1,
|
||||
cfg.staircase_decay_at_epochs,
|
||||
cfg.staircase_decay_multiple_factor)
|
||||
# adjust_lr(optimizer,epoch+1,cfg.finetuned_params_lr)n
|
||||
|
||||
may_set_mode(modules_optims, 'train')
|
||||
# recording loss
|
||||
loss_meter = AverageMeter()
|
||||
dataset_L = len(train_loader) # crop batch data
|
||||
ep_st = time.time()
|
||||
ep_st_mark=ep_st
|
||||
# runing every batch data
|
||||
for step, (imgs, targets) in enumerate(train_loader):
|
||||
|
||||
step_st = time.time()
|
||||
# measure data loading time
|
||||
data_time = step_st-ep_st
|
||||
|
||||
imgs_var = Variable(imgs)
|
||||
targets_var = Variable(targets)
|
||||
|
||||
# compute the weight
|
||||
weights = torch.zeros(targets_var.shape)
|
||||
for i in range(targets_var.shape[0]):
|
||||
for j in range(targets_var.shape[1]):
|
||||
if targets_var.data.cpu()[i, j] == -1:
|
||||
weights[i, j] = weight_neg[j]
|
||||
elif targets_var.data.cpu()[i, j] == 1:
|
||||
weights[i, j] = weight_pos[j]
|
||||
else:
|
||||
weights[i, j] = 0
|
||||
|
||||
targets_var[targets_var == -1] = 0
|
||||
targets_var = targets_var.to(CALCULATE_DEVICE)
|
||||
imgs_var = imgs_var.to(CALCULATE_DEVICE)
|
||||
weights = weights.to(CALCULATE_DEVICE)
|
||||
score = model(imgs_var)
|
||||
|
||||
criterion = torch.nn.BCEWithLogitsLoss(weight=Variable(weights)).to(CALCULATE_DEVICE)
|
||||
loss = criterion(score, targets_var) * num_att
|
||||
optimizer.zero_grad()
|
||||
if cfg.amp:
|
||||
with amp.scale_loss(loss, optimizer) as scaled_loss:
|
||||
scaled_loss.backward()
|
||||
else:
|
||||
loss.backward()
|
||||
|
||||
optimizer.step()
|
||||
|
||||
|
||||
############
|
||||
# step log #
|
||||
############
|
||||
loss_meter.update(to_scalar(loss))
|
||||
# one batch time using backward calculation
|
||||
batch_time = time.time() - ep_st # include data load time
|
||||
ep_st = time.time()
|
||||
fps = cfg.batch_size / batch_time
|
||||
# do not include data load time
|
||||
|
||||
if (step + 1) % cfg.steps_per_log == 0 or (step + 1) % len(train_loader) == 0:
|
||||
log = '{}, Step {}/{} in Ep {}, {:.2f}s, datatime:{:.6f}, batchtime:{:.6f}, FPS:{:.2f}, loss:{:.4f}'.format( \
|
||||
time_str(), step + 1, dataset_L, epoch + 1, time.time() - step_st, data_time, batch_time, fps, loss_meter.val)
|
||||
|
||||
print(log)
|
||||
|
||||
hwlog.remark_print(key=hwlog.FPS, value='{:.2f}'.format(fps))
|
||||
|
||||
##############
|
||||
# epoch log #
|
||||
##############
|
||||
epoch_time = time.time() - ep_st_mark
|
||||
log = 'Ep{}, {:.2f}s, loss {:.4f}'.format(
|
||||
epoch+1, epoch_time, loss_meter.avg)
|
||||
print(log)
|
||||
|
||||
# writer.add_scalar('Train/Time', epoch_time, epoch+1)
|
||||
# writer.add_scalar('Train/Loss', loss_meter.avg, epoch+1)
|
||||
# writer.add_scalar('Train/LR', optimizer.param_groups[0]['lr'], epoch+1)
|
||||
|
||||
|
||||
# model ckpt
|
||||
if (epoch + 1) % cfg.epochs_per_save == 0 or epoch+1 == cfg.total_epochs:
|
||||
ckpt_file = os.path.join(cfg.exp_dir, 'model', 'ckpt_epoch%d.pth'%(epoch+1))
|
||||
save_ckpt(modules_optims, epoch+1, 0, ckpt_file)
|
||||
|
||||
##########################
|
||||
# test on validation set #
|
||||
##########################
|
||||
if (epoch + 1) % cfg.epochs_per_val == 0 or epoch+1 == cfg.total_epochs:
|
||||
print ('att test with feat_func_att')
|
||||
res = attribute_evaluate_subfunc(feat_func_att, test_set, CALCULATE_DEVICE, **cfg.test_kwargs)
|
||||
|
||||
# writer.add_scalar('Val/Acc', res, epoch)
|
||||
+587
@@ -0,0 +1,587 @@
|
||||
import os
|
||||
import random
|
||||
import math
|
||||
|
||||
import torch
|
||||
import torch.optim as optim
|
||||
import torchvision.transforms as transforms
|
||||
import torch.nn.functional as F
|
||||
import torch.backends.cudnn as cudnn
|
||||
from torch.autograd import Variable
|
||||
from torch.nn.parallel import DataParallel
|
||||
import pickle
|
||||
import time
|
||||
import argparse
|
||||
import pdb
|
||||
import sys
|
||||
from torch.utils.tensorboard import SummaryWriter
|
||||
|
||||
from baseline.dataset import add_transforms
|
||||
from baseline.dataset.Dataset import AttDataset
|
||||
from baseline.model.DeepMAR import DeepMAR_ResNet50
|
||||
from baseline.model.DeepMAR import DeepMAR_ResNet50_ExtractFeature
|
||||
from baseline.utils.evaluate import attribute_evaluate
|
||||
from baseline.utils.utils import str2bool
|
||||
from baseline.utils.utils import transfer_optim_state
|
||||
from baseline.utils.utils import time_str
|
||||
from baseline.utils.utils import save_ckpt, load_ckpt
|
||||
from baseline.utils.utils import load_state_dict
|
||||
from baseline.utils.utils import ReDirectSTD
|
||||
from baseline.utils.utils import adjust_lr_staircase
|
||||
from baseline.utils.utils import adjust_lr
|
||||
from baseline.utils.utils import set_devices
|
||||
from baseline.utils.utils import AverageMeter
|
||||
from baseline.utils.utils import to_scalar
|
||||
from baseline.utils.utils import may_set_mode
|
||||
from baseline.utils.utils import may_mkdir
|
||||
from baseline.utils.utils import set_seed
|
||||
from baseline.utils.utils import seed_everything
|
||||
import torch.distributed as dist
|
||||
import torch.multiprocessing as mp
|
||||
import torch.utils.data.distributed
|
||||
|
||||
# Apex
|
||||
import numpy as np
|
||||
from apex import amp
|
||||
import torch.npu
|
||||
|
||||
from benchmark_log import hwlog
|
||||
from benchmark_log.basic_utils import get_environment_info
|
||||
from benchmark_log.basic_utils import get_model_parameter
|
||||
|
||||
|
||||
class Config(object):
|
||||
def __init__(self):
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--sys_device_ids', type=eval, default=6)
|
||||
parser.add_argument('--npu', default=None, type=int, help='NPU id to use.')
|
||||
parser.add_argument('--set_seed', type=str2bool, default=False)
|
||||
## dataset parameter
|
||||
parser.add_argument('--dataset', type=str, default='peta',
|
||||
choices=['peta','rap', 'pa100k', 'rap2'])
|
||||
parser.add_argument('--save_dir', type=str, default='/home/zhusiyi/dataset/peta/')
|
||||
parser.add_argument('--split', type=str, default='trainval',
|
||||
choices=['trainval', 'train'])
|
||||
parser.add_argument('--test_split', type=str, default='test')
|
||||
parser.add_argument('--partition_idx', type=int, default=0)
|
||||
parser.add_argument('--resize', type=eval, default=(224, 224))
|
||||
parser.add_argument('--mirror', type=str2bool, default=True)
|
||||
parser.add_argument('--batch_size', type=int, default=32)
|
||||
parser.add_argument('--workers', type=int, default=2)
|
||||
# model
|
||||
parser.add_argument('--num_att', type=int, default=35)
|
||||
parser.add_argument('--pretrained', type=str2bool, default=True)
|
||||
parser.add_argument('--last_conv_stride', type=int, default=2, choices=[1,2])
|
||||
parser.add_argument('--drop_pool5', type=str2bool, default=True)
|
||||
parser.add_argument('--drop_pool5_rate', type=float, default=0.5)
|
||||
|
||||
parser.add_argument('--sgd_weight_decay', type=float, default=0.0005)
|
||||
parser.add_argument('--sgd_momentum', type=float, default=0.9)
|
||||
parser.add_argument('--new_params_lr', type=float, default=0.001)
|
||||
parser.add_argument('--finetuned_params_lr', type=float, default=0.001)
|
||||
parser.add_argument('--staircase_decay_at_epochs', type=eval,
|
||||
default=(51, ))
|
||||
parser.add_argument('--staircase_decay_multiple_factor', type=float,
|
||||
default=0.1)
|
||||
parser.add_argument('--total_epochs', type=int, default=150)
|
||||
parser.add_argument('--weighted_entropy', type=str2bool, default=True)
|
||||
# utils
|
||||
parser.add_argument('--resume', type=str2bool, default=False)
|
||||
parser.add_argument('--ckpt_file', type=str, default='')
|
||||
parser.add_argument('--load_model_weight', type=str2bool, default=False)
|
||||
parser.add_argument('--model_weight_file', type=str, default='')
|
||||
parser.add_argument('--test_only', type=str2bool, default=False)
|
||||
parser.add_argument('--exp_dir', type=str, default='')
|
||||
parser.add_argument('--exp_subpath', type=str, default='deepmar_resnet50')
|
||||
parser.add_argument('--log_to_file', type=str2bool, default=True)
|
||||
parser.add_argument('--steps_per_log', type=int, default=20)
|
||||
parser.add_argument('--epochs_per_val', type=int, default=10)
|
||||
parser.add_argument('--epochs_per_save', type=int, default=50)
|
||||
parser.add_argument('--run', type=int, default=1)
|
||||
# apex
|
||||
parser.add_argument('--amp', default=False, action='store_true',
|
||||
help='use amp to train the model')
|
||||
parser.add_argument('--loss_scale', default=-1., type=float,
|
||||
help='loss scale using in amp, default -1 means dynamic')
|
||||
parser.add_argument('--opt_level', default='O1', type=str,
|
||||
help='opt level using in amp, default O1 means FP16')
|
||||
# distributed
|
||||
parser.add_argument('--addr', default='90.90.176.152', type=str,
|
||||
help='master addr')
|
||||
parser.add_argument('--world_size', default=-1, type=int,
|
||||
help='number of nodes for distributed training')
|
||||
parser.add_argument('--rank', default=-1, type=int,
|
||||
help='node rank for distributed training')
|
||||
parser.add_argument('--dist_url', default='tcp://224.66.41.62:23456', type=str,
|
||||
help='url used to set up distributed training')
|
||||
parser.add_argument('--dist_backend', default='nccl', type=str,
|
||||
help='distributed backend')
|
||||
parser.add_argument('--multiprocessing_distributed', action='store_true',
|
||||
help='Use multi-processing distributed training to launch '
|
||||
'N processes per node, which has N NPUs. This is the '
|
||||
'fastest way to use PyTorch for either single node or '
|
||||
'multi node data parallel training')
|
||||
parser.add_argument('--npus_per_node', default=None, type=int,
|
||||
help='number of npus to use for distributed train on each node')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# gpu ids
|
||||
# self.sys_device_ids = args.sys_device_ids
|
||||
self.npus_per_node=args.npus_per_node
|
||||
self.npu = args.npu
|
||||
# random
|
||||
self.set_seed = args.set_seed
|
||||
if self.set_seed:
|
||||
self.seed = 0
|
||||
else:
|
||||
self.seed = None
|
||||
# amp
|
||||
self.amp = args.amp
|
||||
self.loss_scale = args.loss_scale
|
||||
self.opt_level = args.opt_level
|
||||
# run time index
|
||||
self.run = args.run
|
||||
# Dataset #
|
||||
datasets = dict()
|
||||
datasets['peta'] = args.save_dir + '/peta_dataset.pkl'
|
||||
partitions = dict()
|
||||
partitions['peta'] = args.save_dir + '/peta_partition.pkl'
|
||||
|
||||
self.dataset_name = args.dataset
|
||||
if args.dataset not in datasets or args.dataset not in partitions:
|
||||
print ("Please select the right dataset name.")
|
||||
raise ValueError
|
||||
else:
|
||||
self.dataset = datasets[args.dataset]
|
||||
self.partition = partitions[args.dataset]
|
||||
self.partition_idx = args.partition_idx
|
||||
self.split = args.split
|
||||
self.test_split = args.test_split
|
||||
self.resize = args.resize
|
||||
self.mirror = args.mirror
|
||||
self.mean = [0.485, 0.456, 0.406]
|
||||
self.std = [0.229, 0.224, 0.225]
|
||||
self.batch_size = args.batch_size
|
||||
self.workers = args.workers
|
||||
# optimization
|
||||
self.sgd_momentum = args.sgd_momentum
|
||||
self.sgd_weight_decay = args.sgd_weight_decay
|
||||
self.new_params_lr = args.new_params_lr
|
||||
self.finetuned_params_lr = args.finetuned_params_lr
|
||||
self.staircase_decay_at_epochs = args.staircase_decay_at_epochs
|
||||
self.staircase_decay_multiple_factor = args.staircase_decay_multiple_factor
|
||||
self.total_epochs = args.total_epochs
|
||||
self.weighted_entropy = args.weighted_entropy
|
||||
# distributed
|
||||
self.addr = args.addr
|
||||
self.world_size = args.world_size
|
||||
self.rank = args.rank
|
||||
self.dist_url = args.dist_url
|
||||
self.dist_backend = args.dist_backend
|
||||
self.multiprocessing_distributed = args.multiprocessing_distributed
|
||||
# utils
|
||||
self.resume = args.resume
|
||||
self.ckpt_file = args.ckpt_file
|
||||
if self.resume:
|
||||
if self.ckpt_file == '':
|
||||
print ('Please input the ckpt_file if you want to resume training')
|
||||
raise ValueError
|
||||
self.load_model_weight = args.load_model_weight
|
||||
self.model_weight_file = args.model_weight_file
|
||||
if self.load_model_weight:
|
||||
if self.model_weight_file == '':
|
||||
print ('Please input the model_weight_file if you want to load model weight')
|
||||
raise ValueError
|
||||
self.test_only = args.test_only
|
||||
self.exp_dir = args.exp_dir
|
||||
self.exp_subpath = args.exp_subpath
|
||||
self.log_to_file = args.log_to_file
|
||||
self.steps_per_log = args.steps_per_log
|
||||
self.epochs_per_val = args.epochs_per_val
|
||||
self.epochs_per_save = args.epochs_per_save
|
||||
self.run = args.run
|
||||
|
||||
# for model
|
||||
model_kwargs = dict()
|
||||
model_kwargs['num_att'] = args.num_att
|
||||
model_kwargs['last_conv_stride'] = args.last_conv_stride
|
||||
model_kwargs['drop_pool5'] = args.drop_pool5
|
||||
model_kwargs['drop_pool5_rate'] = args.drop_pool5_rate
|
||||
self.model_kwargs = model_kwargs
|
||||
# for evaluation
|
||||
self.test_kwargs = dict()
|
||||
|
||||
if self.exp_dir == '':
|
||||
self.exp_dir = os.path.join('exp',
|
||||
'{}'.format(self.exp_subpath),
|
||||
'{}'.format(self.dataset_name),
|
||||
'partition{}'.format(self.partition_idx),
|
||||
'run{}'.format(self.run))
|
||||
self.stdout_file = os.path.join(self.exp_dir, \
|
||||
'log', 'stdout_{}.txt'.format(time_str()))
|
||||
self.stderr_file = os.path.join(self.exp_dir, \
|
||||
'log', 'stderr_{}.txt'.format(time_str()))
|
||||
may_mkdir(self.stdout_file)
|
||||
|
||||
def main():
|
||||
### main function ###
|
||||
# pdb.set_trace()
|
||||
cfg = Config()
|
||||
|
||||
# log
|
||||
if cfg.log_to_file:
|
||||
ReDirectSTD(cfg.stdout_file, 'stdout', False)
|
||||
ReDirectSTD(cfg.stderr_file, 'stderr', False)
|
||||
|
||||
# dump the configuration to log.
|
||||
import pprint
|
||||
print('-' * 60)
|
||||
print('cfg.__dict__')
|
||||
pprint.pprint(cfg.__dict__)
|
||||
print('-' * 60)
|
||||
|
||||
os.environ['KERNEL_NAME_ID'] = str(0)
|
||||
print("+++++++++++++++++++++++++++KERNEL_NAME_ID:",os.environ['KERNEL_NAME_ID'])
|
||||
|
||||
# set the random seed
|
||||
print(cfg.seed)
|
||||
if cfg.set_seed:
|
||||
set_seed(cfg.seed)
|
||||
seed_everything(cfg.seed)
|
||||
|
||||
os.environ['MASTER_ADDR'] = cfg.addr
|
||||
os.environ['MASTER_PORT'] = '29501'
|
||||
if cfg.dist_url == "env://" and cfg.world_size == -1:
|
||||
cfg.world_size = int(os.environ["WORLD_SIZE"])
|
||||
|
||||
npus_per_node=cfg.npus_per_node
|
||||
#npus_per_node = torch.npu.device_count()
|
||||
if cfg.multiprocessing_distributed:
|
||||
# Since we have ngpus_per_node processes per node, the total world_size needs to be adjusted accordingly
|
||||
cfg.world_size = npus_per_node * cfg.world_size # world_size means nums of all devices or nums of processes
|
||||
mp.spawn(main_worker, nprocs=npus_per_node, args=(npus_per_node, cfg))
|
||||
|
||||
def main_worker(npu, npus_per_node, cfg):
|
||||
cfg.npu = npu
|
||||
print("[npu id:", npu, "]", "+++++++++++++++++++++++++++ before set KERNEL_NAME_ID:", os.environ['KERNEL_NAME_ID'])
|
||||
os.environ['KERNEL_NAME_ID'] = str(npu)
|
||||
|
||||
print("[npu id:", npu, "]", "+++++++++++++++++++++++++++KERNEL_NAME_ID:", os.environ['KERNEL_NAME_ID'])
|
||||
|
||||
if npu is not None:
|
||||
print("[npu id:", npu, "]", "Use NPU: {} for training".format(npu))
|
||||
|
||||
if cfg.dist_url == "env://" and cfg.rank == -1:
|
||||
cfg.rank = int(os.environ["RANK"])
|
||||
if cfg.multiprocessing_distributed:
|
||||
# For multiprocessing distributed training, rank needs to be the
|
||||
# global rank among all the processes
|
||||
#cfg.rank = cfg.rank * npus_per_node + npu
|
||||
cfg.rank = npu
|
||||
print("rank:",cfg.rank)
|
||||
dist.init_process_group(backend=cfg.dist_backend, #init_method=cfg.dist_url,
|
||||
world_size=cfg.world_size, rank=cfg.rank)
|
||||
|
||||
CALCULATE_DEVICE = 'npu:{}'.format(npu)
|
||||
print(CALCULATE_DEVICE)
|
||||
torch.npu.set_device(CALCULATE_DEVICE)
|
||||
|
||||
# DistributedDataParallel, we need to divide the batch size
|
||||
# ourselves based on the total number of NPUs we have
|
||||
cfg.batch_size = int(cfg.batch_size / npus_per_node)
|
||||
cfg.workers = int((cfg.workers + npus_per_node - 1) / npus_per_node)
|
||||
print("batchsize:", cfg.batch_size)
|
||||
print("workers", cfg.workers)
|
||||
|
||||
# dataset
|
||||
normalize = transforms.Normalize(mean=cfg.mean, std=cfg.std)
|
||||
transform = transforms.Compose([
|
||||
transforms.Resize(cfg.resize),
|
||||
transforms.RandomHorizontalFlip(),
|
||||
transforms.ToTensor(), # 3*H*W, [0, 1]
|
||||
normalize,]) # normalize with mean/std
|
||||
# by a subset of attributes
|
||||
train_set = AttDataset(
|
||||
dataset = cfg.dataset,
|
||||
partition = cfg.partition,
|
||||
split = cfg.split,
|
||||
partition_idx= cfg.partition_idx,
|
||||
transform = transform)
|
||||
|
||||
num_att = len(train_set.dataset['selected_attribute'])
|
||||
cfg.model_kwargs['num_att'] = num_att
|
||||
|
||||
distributed = cfg.world_size > 1 or cfg.multiprocessing_distributed
|
||||
if distributed:
|
||||
train_sampler = torch.utils.data.distributed.DistributedSampler(train_set)
|
||||
else:
|
||||
train_sampler = None
|
||||
|
||||
train_loader = torch.utils.data.DataLoader(
|
||||
dataset = train_set,
|
||||
batch_size = cfg.batch_size,
|
||||
shuffle=(train_sampler is None),
|
||||
num_workers = cfg.workers,
|
||||
pin_memory = True,
|
||||
sampler=train_sampler,
|
||||
drop_last = True)
|
||||
|
||||
test_transform = transforms.Compose([
|
||||
transforms.Resize(cfg.resize),
|
||||
transforms.ToTensor(),
|
||||
normalize,])
|
||||
|
||||
test_set = AttDataset(
|
||||
dataset = cfg.dataset,
|
||||
partition = cfg.partition,
|
||||
split = cfg.test_split,
|
||||
partition_idx = cfg.partition_idx,
|
||||
transform = test_transform)
|
||||
|
||||
### Att model ###
|
||||
model = DeepMAR_ResNet50(**cfg.model_kwargs)
|
||||
|
||||
# Optimizer
|
||||
finetuned_params = []
|
||||
new_params = []
|
||||
for n, p in model.named_parameters():
|
||||
if n.find('classifier') >=0:
|
||||
new_params.append(p)
|
||||
else:
|
||||
finetuned_params.append(p)
|
||||
param_groups = [{'params': finetuned_params, 'lr': cfg.finetuned_params_lr},
|
||||
{'params': new_params, 'lr': cfg.new_params_lr}]
|
||||
|
||||
optimizer = optim.SGD(
|
||||
param_groups,
|
||||
momentum = cfg.sgd_momentum,
|
||||
weight_decay = cfg.sgd_weight_decay)
|
||||
|
||||
# model = model.cuda()
|
||||
model = model.to(CALCULATE_DEVICE)
|
||||
# apex
|
||||
if cfg.amp:
|
||||
# Initialization
|
||||
model, optimizer = amp.initialize(model, optimizer, opt_level=cfg.opt_level, loss_scale=cfg.loss_scale)
|
||||
print("=> Using amp mode.")
|
||||
|
||||
# Wrap the model after set_devices, data parallel
|
||||
# model_w = torch.nn.DataParallel(model)
|
||||
model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[cfg.npu], broadcast_buffers=False)
|
||||
|
||||
# using the weighted cross entropy loss
|
||||
if cfg.weighted_entropy:
|
||||
rate = np.array(train_set.partition['weight_' + cfg.split][cfg.partition_idx])
|
||||
rate = rate[train_set.dataset['selected_attribute']].tolist()
|
||||
else:
|
||||
rate = None
|
||||
# compute the weight of positive and negative
|
||||
if rate is None:
|
||||
weight_pos = [1 for i in range(num_att)]
|
||||
weight_neg = [1 for i in range(num_att)]
|
||||
else:
|
||||
if len(rate) != num_att:
|
||||
print ("the length of rate should be equal to %d" % (num_att))
|
||||
raise ValueError
|
||||
weight_pos = []
|
||||
weight_neg = []
|
||||
for idx, v in enumerate(rate):
|
||||
weight_pos.append(math.exp(1.0 - v))
|
||||
weight_neg.append(math.exp(v))
|
||||
|
||||
# bind the model and optimizer
|
||||
modules_optims = [model, optimizer]
|
||||
|
||||
# load model weight if necessary
|
||||
if cfg.load_model_weight:
|
||||
map_location = (lambda storage, loc:storage)
|
||||
ckpt = torch.load(cfg.model_weight_file, map_location=map_location)
|
||||
model.load_state_dict(ckpt['state_dicts'][0], strict=False)
|
||||
|
||||
### Resume or not ###
|
||||
if cfg.resume:
|
||||
# store the model, optimizer, epoch
|
||||
start_epoch, scores = load_ckpt(modules_optims, cfg.ckpt_file)
|
||||
else:
|
||||
start_epoch = 0
|
||||
|
||||
#model = torch.nn.DataParallel(model)
|
||||
#transfer_optim_state(state=optimizer.state, device_id=npu)
|
||||
|
||||
# cudnn.benchmark = True
|
||||
# for evaluation
|
||||
feat_func_att = DeepMAR_ResNet50_ExtractFeature(model=model)
|
||||
|
||||
# print the model into log
|
||||
# print (model)
|
||||
# test only
|
||||
if cfg.test_only:
|
||||
print ('test with feat_func_att')
|
||||
attribute_evaluate_subfunc(feat_func_att, test_set, **cfg.test_kwargs)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
# writer = SummaryWriter('runs/deepmar/6')
|
||||
|
||||
# training
|
||||
for epoch in range(start_epoch, cfg.total_epochs):
|
||||
if cfg.seed is not None:
|
||||
cfg.seed += 1
|
||||
seed_everything(cfg.seed)
|
||||
|
||||
if distributed:
|
||||
train_sampler.set_epoch(epoch)
|
||||
# adjust the learning rate
|
||||
adjust_lr_staircase(
|
||||
optimizer.param_groups,
|
||||
[cfg.finetuned_params_lr, cfg.new_params_lr],
|
||||
epoch + 1,
|
||||
cfg.staircase_decay_at_epochs,
|
||||
cfg.staircase_decay_multiple_factor)
|
||||
# adjust_lr(optimizer,epoch+1,cfg.finetuned_params_lr)n
|
||||
|
||||
may_set_mode(modules_optims, 'train')
|
||||
# recording loss
|
||||
loss_meter = AverageMeter()
|
||||
dataset_L = len(train_loader) # crop batch data
|
||||
ep_st = time.time()
|
||||
ep_st_mark=ep_st
|
||||
# runing every batch data
|
||||
for step, (imgs, targets) in enumerate(train_loader):
|
||||
|
||||
step_st = time.time()
|
||||
# measure data loading time
|
||||
data_time = step_st-ep_st
|
||||
|
||||
imgs_var = Variable(imgs)
|
||||
targets_var = Variable(targets)
|
||||
# if 'npu' in CALCULATE_DEVICE:
|
||||
# targets = targets.to(torch.int32)
|
||||
# imgs, targets = imgs.to(CALCULATE_DEVICE, non_blocking=True), targets.to(CALCULATE_DEVICE, non_blocking=True)
|
||||
# compute the weight
|
||||
weights = torch.zeros(targets_var.shape)
|
||||
for i in range(targets_var.shape[0]):
|
||||
for j in range(targets_var.shape[1]):
|
||||
if targets_var.data.cpu()[i, j] == -1:
|
||||
weights[i, j] = weight_neg[j]
|
||||
elif targets_var.data.cpu()[i, j] == 1:
|
||||
weights[i, j] = weight_pos[j]
|
||||
else:
|
||||
weights[i, j] = 0
|
||||
|
||||
# loss for the attribute classification, average over the batch size
|
||||
targets_var[targets_var == -1] = 0
|
||||
targets_var = targets_var.to(CALCULATE_DEVICE)
|
||||
imgs_var = imgs_var.to(CALCULATE_DEVICE)
|
||||
weights = weights.to(CALCULATE_DEVICE)
|
||||
score = model(imgs_var)
|
||||
|
||||
criterion = torch.nn.BCEWithLogitsLoss(weight=Variable(weights)).to(CALCULATE_DEVICE)
|
||||
loss = criterion(score, targets_var) * num_att
|
||||
optimizer.zero_grad()
|
||||
if cfg.amp:
|
||||
with amp.scale_loss(loss, optimizer) as scaled_loss:
|
||||
scaled_loss.backward()
|
||||
else:
|
||||
loss.backward()
|
||||
# for name, parms in model.named_parameters():
|
||||
# print('-->name:', name, ' -->grad_value_max:', torch.max(parms.grad), ' -->grad_value_min:',
|
||||
# torch.min(parms.grad))
|
||||
optimizer.step()
|
||||
|
||||
|
||||
############
|
||||
# step log #
|
||||
############
|
||||
loss_meter.update(to_scalar(loss))
|
||||
# one batch time using backward calculation
|
||||
batch_time = time.time() - ep_st # include data load time
|
||||
ep_st = time.time()
|
||||
fps = npus_per_node*cfg.batch_size / batch_time
|
||||
# do not include data load time
|
||||
|
||||
if (step + 1) % cfg.steps_per_log == 0 or (step + 1) % len(train_loader) == 0:
|
||||
log = '{}, Step {}/{} in Ep {}, {:.2f}s, datatime:{:.6f}, batchtime:{:.6f}, FPS:{:.2f}, loss:{:.4f}'.format( \
|
||||
time_str(), step + 1, dataset_L, epoch + 1, time.time() - step_st, data_time, batch_time, fps, loss_meter.val)
|
||||
print(log)
|
||||
|
||||
hwlog.remark_print(key=hwlog.FPS, value='{:.2f}'.format(fps))
|
||||
|
||||
|
||||
##############
|
||||
# epoch log #
|
||||
##############
|
||||
epoch_time = time.time() - ep_st_mark
|
||||
log = 'Ep{}, {:.2f}s, loss {:.4f}'.format(
|
||||
epoch+1, epoch_time, loss_meter.avg)
|
||||
print(log)
|
||||
|
||||
# writer.add_scalar('Train/Time', epoch_time, epoch+1)
|
||||
# writer.add_scalar('Train/Loss', loss_meter.avg, epoch+1)
|
||||
# # writer.add_scalar('Train/Acc', res['instance_acc'], epoch+1)
|
||||
# writer.add_scalar('Train/LR', optimizer.param_groups[0]['lr'], epoch+1)
|
||||
|
||||
|
||||
# model ckpt
|
||||
if (epoch + 1) % cfg.epochs_per_save == 0 or epoch+1 == cfg.total_epochs:
|
||||
ckpt_file = os.path.join(cfg.exp_dir, 'model', 'ckpt_epoch%d.pth'%(epoch+1))
|
||||
save_ckpt(modules_optims, epoch+1, 0, ckpt_file)
|
||||
|
||||
##########################
|
||||
# test on validation set #
|
||||
##########################
|
||||
if (epoch + 1) % cfg.epochs_per_val == 0 or epoch+1 == cfg.total_epochs:
|
||||
print ('att test with feat_func_att')
|
||||
res = attribute_evaluate_subfunc(feat_func_att, test_set, CALCULATE_DEVICE, cfg, **cfg.test_kwargs)
|
||||
|
||||
# writer.add_scalar('Val/Acc', res, epoch)
|
||||
# writer.close()
|
||||
|
||||
def attribute_evaluate_subfunc(feat_func, test_set, device_id, cfg, **test_kwargs):
|
||||
""" evaluate the attribute recognition precision """
|
||||
result = attribute_evaluate(feat_func, test_set, device_id, **test_kwargs)
|
||||
print ('-' * 60)
|
||||
print ('Evaluation on %s set:' % (cfg.test_split))
|
||||
print ('Label-based evaluation: \n mA: %.4f'%(np.mean(result['label_acc'])))
|
||||
print ('Instance-based evaluation: \n Acc: %.4f, Prec: %.4f, Rec: %.4f, F1: %.4f' \
|
||||
%(result['instance_acc'], result['instance_precision'], result['instance_recall'], result['instance_F1']))
|
||||
print ('-' * 60)
|
||||
hwlog.remark_print(key=hwlog.ACC, value="{:.4f}".format(result['instance_acc']))
|
||||
hwlog.remark_print(key=hwlog.PREC, value="{:.4f}".format(result['instance_precision']))
|
||||
hwlog.remark_print(key=hwlog.REC, value="{:.4f}".format(result['instance_recall']))
|
||||
hwlog.remark_print(key=hwlog.F1, value="{:.4f}".format(result['instance_recall']))
|
||||
return result['instance_acc']
|
||||
|
||||
# intermediate variable
|
||||
inter_feature = {}
|
||||
inter_gradient = {}
|
||||
def make_hook(name, flag):
|
||||
if flag == 'forward':
|
||||
def hook(m, input, output):
|
||||
inter_feature[name] = input
|
||||
return hook
|
||||
elif flag == 'backward':
|
||||
def hook(m, input, output):
|
||||
inter_gradient[name] = output
|
||||
return hook
|
||||
else:
|
||||
assert False
|
||||
|
||||
if __name__ == '__main__':
|
||||
hwlog.ROOT_DIR = os.path.split(os.path.abspath(__file__))[0]
|
||||
cpu_info, npu_info, framework_info, os_info, benchmark_version = get_environment_info("pytorch")
|
||||
config_info = get_model_parameter("pytorch_config")
|
||||
initinal_data = {"base_lr": 0.1, "dataset": "imagenet", "optimizer": "SGD", "loss_scale": 1024}
|
||||
hwlog.remark_print(key=hwlog.CPU_INFO, value=cpu_info)
|
||||
hwlog.remark_print(key=hwlog.NPU_INFO, value=npu_info)
|
||||
hwlog.remark_print(key=hwlog.OS_INFO, value=os_info)
|
||||
hwlog.remark_print(key=hwlog.FRAMEWORK_INFO, value=framework_info)
|
||||
hwlog.remark_print(key=hwlog.BENCHMARK_VERSION, value=benchmark_version)
|
||||
hwlog.remark_print(key=hwlog.CONFIG_INFO, value=config_info)
|
||||
hwlog.remark_print(key=hwlog.BASE_LR, value=initinal_data.get("base_lr"))
|
||||
hwlog.remark_print(key=hwlog.DATASET, value=initinal_data.get("dataset"))
|
||||
hwlog.remark_print(key=hwlog.OPT_NAME, value=initinal_data.get("optimizer"))
|
||||
hwlog.remark_print(key=hwlog.LOSS_SCALE, value=initinal_data.get("loss_scale"))
|
||||
main()
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import random
|
||||
import cPickle as pickle
|
||||
from scipy.io import loadmat
|
||||
|
||||
np.random.seed(0)
|
||||
random.seed(0)
|
||||
|
||||
def make_dir(path):
|
||||
if os.path.exists(path):
|
||||
pass
|
||||
else:
|
||||
os.mkdir(path)
|
||||
|
||||
def generate_data_description(save_dir):
|
||||
"""
|
||||
create a dataset description file, which consists of images, labels
|
||||
"""
|
||||
dataset = dict()
|
||||
dataset['description'] = 'pa100k'
|
||||
dataset['root'] = './dataset/pa100k/data/'
|
||||
dataset['image'] = []
|
||||
dataset['att'] = []
|
||||
dataset['att_name'] = []
|
||||
dataset['selected_attribute'] = range(26)
|
||||
# load ANNOTATION.MAT
|
||||
data = loadmat(open('./dataset/pa100k/annotation.mat', 'r'))
|
||||
for idx in range(26):
|
||||
dataset['att_name'].append(data['attributes'][idx][0][0])
|
||||
|
||||
for idx in range(80000):
|
||||
dataset['image'].append(data['train_images_name'][idx][0][0])
|
||||
dataset['att'].append(data['train_label'][idx, :].tolist())
|
||||
|
||||
for idx in range(10000):
|
||||
dataset['image'].append(data['val_images_name'][idx][0][0])
|
||||
dataset['att'].append(data['val_label'][idx, :].tolist())
|
||||
|
||||
for idx in range(10000):
|
||||
dataset['image'].append(data['test_images_name'][idx][0][0])
|
||||
dataset['att'].append(data['test_label'][idx, :].tolist())
|
||||
|
||||
with open(os.path.join(save_dir, 'pa100k_dataset.pkl'), 'w+') as f:
|
||||
pickle.dump(dataset, f)
|
||||
|
||||
def create_trainvaltest_split(traintest_split_file):
|
||||
"""
|
||||
create a dataset split file, which consists of index of the train/val/test splits
|
||||
"""
|
||||
partition = dict()
|
||||
partition['trainval'] = []
|
||||
partition['train'] = []
|
||||
partition['val'] = []
|
||||
partition['test'] = []
|
||||
partition['weight_trainval'] = []
|
||||
partition['weight_train'] = []
|
||||
# load ANNOTATION.MAT
|
||||
data = loadmat(open('./dataset/pa100k/annotation.mat', 'r'))
|
||||
train = range(80000)
|
||||
val = [i+80000 for i in range(10000)]
|
||||
test = [i+90000 for i in range(10000)]
|
||||
trainval = train + val
|
||||
partition['train'].append(train)
|
||||
partition['val'].append(val)
|
||||
partition['trainval'].append(trainval)
|
||||
partition['test'].append(test)
|
||||
# weight
|
||||
train_label = data['train_label'].astype('float32')
|
||||
trainval_label = np.concatenate((data['train_label'], data['val_label']), axis=0).astype('float32')
|
||||
weight_train = np.mean(train_label==1, axis=0).tolist()
|
||||
weight_trainval = np.mean(trainval_label==1, axis=0).tolist()
|
||||
|
||||
partition['weight_trainval'].append(weight_trainval)
|
||||
partition['weight_train'].append(weight_train)
|
||||
|
||||
with open(traintest_split_file, 'w+') as f:
|
||||
pickle.dump(partition, f)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description="pa100k dataset")
|
||||
parser.add_argument(
|
||||
'--save_dir',
|
||||
type=str,
|
||||
default='./dataset/pa100k/')
|
||||
parser.add_argument(
|
||||
'--traintest_split_file',
|
||||
type=str,
|
||||
default="./dataset/pa100k/pa100k_partition.pkl")
|
||||
args = parser.parse_args()
|
||||
save_dir = args.save_dir
|
||||
traintest_split_file = args.traintest_split_file
|
||||
|
||||
generate_data_description(save_dir)
|
||||
create_trainvaltest_split(traintest_split_file)
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import random
|
||||
import pickle
|
||||
from scipy.io import loadmat
|
||||
|
||||
np.random.seed(0)
|
||||
random.seed(0)
|
||||
|
||||
def make_dir(path):
|
||||
if os.path.exists(path):
|
||||
pass
|
||||
else:
|
||||
os.mkdir(path)
|
||||
|
||||
def generate_data_description(save_dir):
|
||||
"""
|
||||
create a dataset description file, which consists of images, labels
|
||||
"""
|
||||
dataset = dict()
|
||||
dataset['description'] = 'peta'
|
||||
dataset['root'] = save_dir + '/images/'
|
||||
dataset['image'] = []
|
||||
dataset['att'] = []
|
||||
dataset['att_name'] = []
|
||||
dataset['selected_attribute'] = range(35)
|
||||
# load PETA.MAT
|
||||
data = loadmat(save_dir + '/PETA.mat')
|
||||
for idx in range(105):
|
||||
dataset['att_name'].append(data['peta'][0][0][1][idx,0][0])
|
||||
|
||||
for idx in range(19000):
|
||||
dataset['image'].append('%05d.png'%(idx+1))
|
||||
dataset['att'].append(data['peta'][0][0][0][idx, 4:].tolist())
|
||||
with open(os.path.join(save_dir, 'peta_dataset.pkl'), 'wb') as f:
|
||||
pickle.dump(dataset, f)
|
||||
|
||||
def create_trainvaltest_split(traintest_split_file):
|
||||
"""
|
||||
create a dataset split file, which consists of index of the train/val/test splits
|
||||
"""
|
||||
partition = dict()
|
||||
partition['trainval'] = []
|
||||
partition['train'] = []
|
||||
partition['val'] = []
|
||||
partition['test'] = []
|
||||
partition['weight_trainval'] = []
|
||||
partition['weight_train'] = []
|
||||
# load PETA.MAT
|
||||
data = loadmat(save_dir + '/PETA.mat')
|
||||
for idx in range(5):
|
||||
train = (data['peta'][0][0][3][idx][0][0][0][0][:,0]-1).tolist()
|
||||
val = (data['peta'][0][0][3][idx][0][0][0][1][:,0]-1).tolist()
|
||||
test = (data['peta'][0][0][3][idx][0][0][0][2][:,0]-1).tolist()
|
||||
trainval = train + val
|
||||
partition['train'].append(train)
|
||||
partition['val'].append(val)
|
||||
partition['trainval'].append(trainval)
|
||||
partition['test'].append(test)
|
||||
# weight
|
||||
weight_trainval = np.mean(data['peta'][0][0][0][trainval, 4:].astype('float32')==1, axis=0).tolist()
|
||||
weight_train = np.mean(data['peta'][0][0][0][train, 4:].astype('float32')==1, axis=0).tolist()
|
||||
partition['weight_trainval'].append(weight_trainval)
|
||||
partition['weight_train'].append(weight_train)
|
||||
with open(traintest_split_file, 'wb') as f:
|
||||
pickle.dump(partition, f)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description="peta dataset")
|
||||
parser.add_argument(
|
||||
'--save_dir',
|
||||
type=str,
|
||||
default='/home/zhusiyi/dataset/peta/')
|
||||
parser.add_argument(
|
||||
'--traintest_split_file',
|
||||
type=str,
|
||||
default="/home/zhusiyi/dataset/peta/peta_partition.pkl")
|
||||
args = parser.parse_args()
|
||||
save_dir = args.save_dir
|
||||
traintest_split_file = args.traintest_split_file
|
||||
|
||||
generate_data_description(save_dir)
|
||||
create_trainvaltest_split(traintest_split_file)
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import random
|
||||
import cPickle as pickle
|
||||
from scipy.io import loadmat
|
||||
|
||||
np.random.seed(0)
|
||||
random.seed(0)
|
||||
|
||||
def make_dir(path):
|
||||
if os.path.exists(path):
|
||||
pass
|
||||
else:
|
||||
os.mkdir(path)
|
||||
|
||||
def generate_data_description(save_dir):
|
||||
"""
|
||||
create a dataset description file, which consists of images, labels
|
||||
"""
|
||||
dataset = dict()
|
||||
dataset['description'] = 'rap'
|
||||
dataset['root'] = './dataset/rap/RAP_dataset/'
|
||||
dataset['image'] = []
|
||||
dataset['att'] = []
|
||||
dataset['att_name'] = []
|
||||
dataset['selected_attribute'] = range(51)
|
||||
# load Rap_annotation.mat
|
||||
data = loadmat(open('./dataset/rap/RAP_annotation/RAP_annotation.mat', 'r'))
|
||||
for idx in range(51):
|
||||
dataset['att_name'].append(data['RAP_annotation'][0][0][6][idx][0][0])
|
||||
|
||||
for idx in range(41585):
|
||||
dataset['image'].append(data['RAP_annotation'][0][0][5][idx][0][0])
|
||||
dataset['att'].append(data['RAP_annotation'][0][0][1][idx, :].tolist())
|
||||
|
||||
with open(os.path.join(save_dir, 'rap_dataset.pkl'), 'w+') as f:
|
||||
pickle.dump(dataset, f)
|
||||
|
||||
def create_trainvaltest_split(traintest_split_file):
|
||||
"""
|
||||
create a dataset split file, which consists of index of the train/val/test splits
|
||||
"""
|
||||
partition = dict()
|
||||
partition['trainval'] = []
|
||||
partition['test'] = []
|
||||
partition['weight_trainval'] = []
|
||||
# load RAP_annotation.mat
|
||||
data = loadmat(open('./dataset/rap/RAP_annotation/RAP_annotation.mat', 'r'))
|
||||
for idx in range(5):
|
||||
trainval = (data['RAP_annotation'][0][0][0][idx][0][0][0][0][0,:]-1).tolist()
|
||||
test = (data['RAP_annotation'][0][0][0][idx][0][0][0][1][0,:]-1).tolist()
|
||||
partition['trainval'].append(trainval)
|
||||
partition['test'].append(test)
|
||||
# weight
|
||||
weight_trainval = np.mean(data['RAP_annotation'][0][0][1][trainval, :].astype('float32')==1, axis=0).tolist()
|
||||
partition['weight_trainval'].append(weight_trainval)
|
||||
with open(traintest_split_file, 'w+') as f:
|
||||
pickle.dump(partition, f)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description="rap dataset")
|
||||
parser.add_argument(
|
||||
'--save_dir',
|
||||
type=str,
|
||||
default='./dataset/rap/')
|
||||
parser.add_argument(
|
||||
'--traintest_split_file',
|
||||
type=str,
|
||||
default="./dataset/rap/rap_partition.pkl")
|
||||
args = parser.parse_args()
|
||||
save_dir = args.save_dir
|
||||
traintest_split_file = args.traintest_split_file
|
||||
|
||||
generate_data_description(save_dir)
|
||||
create_trainvaltest_split(traintest_split_file)
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import random
|
||||
import cPickle as pickle
|
||||
from scipy.io import loadmat
|
||||
|
||||
np.random.seed(0)
|
||||
random.seed(0)
|
||||
|
||||
def make_dir(path):
|
||||
if os.path.exists(path):
|
||||
pass
|
||||
else:
|
||||
os.mkdir(path)
|
||||
|
||||
def generate_data_description(save_dir):
|
||||
"""
|
||||
create a dataset description file, which consists of images, labels
|
||||
"""
|
||||
dataset = dict()
|
||||
dataset['description'] = 'rap2'
|
||||
dataset['root'] = './dataset/rap2/RAP_dataset/'
|
||||
dataset['image'] = []
|
||||
dataset['att'] = []
|
||||
dataset['att_name'] = []
|
||||
# load RAP_annotation.mat
|
||||
data = loadmat(open('./dataset/rap2/RAP_annotation/RAP_annotation.mat', 'r'))
|
||||
dataset['selected_attribute'] = (data['RAP_annotation'][0][0][3][0,:]-1).tolist()
|
||||
for idx in range(152):
|
||||
dataset['att_name'].append(data['RAP_annotation'][0][0][2][idx][0][0])
|
||||
|
||||
for idx in range(84928):
|
||||
dataset['image'].append(data['RAP_annotation'][0][0][0][idx][0][0])
|
||||
dataset['att'].append(data['RAP_annotation'][0][0][1][idx, :].tolist())
|
||||
|
||||
with open(os.path.join(save_dir, 'rap2_dataset.pkl'), 'w+') as f:
|
||||
pickle.dump(dataset, f)
|
||||
|
||||
def create_trainvaltest_split(traintest_split_file):
|
||||
"""
|
||||
create a dataset split file, which consists of index of the train/val/test splits
|
||||
"""
|
||||
partition = dict()
|
||||
partition['train'] = []
|
||||
partition['val'] = []
|
||||
partition['trainval'] = []
|
||||
partition['test'] = []
|
||||
partition['weight_train'] = []
|
||||
partition['weight_trainval'] = []
|
||||
# load RAP_annotation.mat
|
||||
data = loadmat(open('./dataset/rap2/RAP_annotation/RAP_annotation.mat', 'r'))
|
||||
for idx in range(5):
|
||||
train = (data['RAP_annotation'][0][0][4][0, idx][0][0][0][0,:]-1).tolist()
|
||||
val = (data['RAP_annotation'][0][0][4][0, idx][0][0][1][0,:]-1).tolist()
|
||||
test = (data['RAP_annotation'][0][0][4][0, idx][0][0][2][0,:]-1).tolist()
|
||||
trainval = train + val
|
||||
partition['trainval'].append(trainval)
|
||||
partition['train'].append(train)
|
||||
partition['val'].append(val)
|
||||
partition['test'].append(test)
|
||||
# weight
|
||||
weight_train = np.mean(data['RAP_annotation'][0][0][1][train, :].astype('float32')==1, axis=0).tolist()
|
||||
weight_trainval = np.mean(data['RAP_annotation'][0][0][1][trainval, :].astype('float32')==1, axis=0).tolist()
|
||||
partition['weight_train'].append(weight_train)
|
||||
partition['weight_trainval'].append(weight_trainval)
|
||||
|
||||
with open(traintest_split_file, 'w+') as f:
|
||||
pickle.dump(partition, f)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description="rap2 dataset")
|
||||
parser.add_argument(
|
||||
'--save_dir',
|
||||
type=str,
|
||||
default='./dataset/rap2/')
|
||||
parser.add_argument(
|
||||
'--traintest_split_file',
|
||||
type=str,
|
||||
default="./dataset/rap2/rap2_partition.pkl")
|
||||
args = parser.parse_args()
|
||||
save_dir = args.save_dir
|
||||
traintest_split_file = args.traintest_split_file
|
||||
|
||||
generate_data_description(save_dir)
|
||||
create_trainvaltest_split(traintest_split_file)
|
||||
Reference in New Issue
Block a user