目录
Warmup:
Random Erasing Data Augmentation:
以config/defaults.py为例
学习率的变化:上升--平稳--下降
【开始训练以很小的学习率训练,随着训练学习率慢慢上升,再以一定的学习率平稳训练,最后在减小学习率】
# warm up factor
_C.SOLVER.WARMUP_FACTOR = 1.0 / 3
# iterations of warm up
_C.SOLVER.WARMUP_ITERS = 500
# method of warm up, option: 'constant','linear'
_C.SOLVER.WARMUP_METHOD = "linear"
softmax_triplet_with_center.yml中:
WARMUP_FACTOR: 0.01
WARMUP_ITERS: 10
WARMUP_METHOD: 'linear'
WarmupMultiStepLR( )函数:
# encoding: utf-8
"""
@author: liaoxingyu
@contact: [email protected]
"""
from bisect import bisect_right
import torch
# FIXME ideally this would be achieved with a CombinedLRScheduler,
# separating MultiStepLR with WarmupLR
# but the current LRScheduler design doesn't allow it
class WarmupMultiStepLR(torch.optim.lr_scheduler._LRScheduler):
def __init__(
self,
optimizer,
milestones,
gamma=0.1,
warmup_factor=1.0 / 3,
warmup_iters=500,
warmup_method="linear",
last_epoch=-1,
):
if not list(milestones) == sorted(milestones):
raise ValueError(
"Milestones should be a list of" " increasing integers. Got {}",
milestones,
)
if warmup_method not in ("constant", "linear"):
raise ValueError(
"Only 'constant' or 'linear' warmup_method accepted"
"got {}".format(warmup_method)
)
self.milestones = milestones
self.gamma = gamma
self.warmup_factor = warmup_factor #初始学习率
self.warmup_iters = warmup_iters #停止epoch
self.warmup_method = warmup_method
super(WarmupMultiStepLR, self).__init__(optimizer, last_epoch)
def get_lr(self):
warmup_factor = 1
if self.last_epoch < self.warmup_iters: #当还在使用warmup方法epoch范围内
if self.warmup_method == "constant": #constant
warmup_factor = self.warmup_factor #学习率在使用warmup之内保持恒定warmup_factor
elif self.warmup_method == "linear": #linear
alpha = self.last_epoch / self.warmup_iters #相当于计算线性变化的斜率
warmup_factor = self.warmup_factor * (1 - alpha) + alpha #计算新的warmup_factor
return [
base_lr
* warmup_factor
* self.gamma ** bisect_right(self.milestones, self.last_epoch)
for base_lr in self.base_lrs
]
利用随机擦除的方式,将原数据集中的一部分样本随机擦除一个矩形区域。
INPUT:
SIZE_TRAIN: [384, 384]
SIZE_TEST: [384, 384]
PROB: 0.5 # random horizontal flip
RE_PROB: 0.5 # random erasing 随机擦除的概率 一半一半
PADDING: 10
# encoding: utf-8
"""
@author: liaoxingyu
@contact: [email protected]
"""
import math
import random
class RandomErasing(object):
""" Randomly selects a rectangle region in an image and erases its pixels.
'Random Erasing Data Augmentation' by Zhong et al.
See https://arxiv.org/pdf/1708.04896.pdf
Args:
probability: The probability that the Random Erasing operation will be performed.
sl: Minimum proportion of erased area against input image.
sh: Maximum proportion of erased area against input image.
r1: Minimum aspect ratio of erased area.
mean: Erasing value.
"""
def __init__(self, probability=0.5, sl=0.02, sh=0.4, r1=0.3, mean=(0.4914, 0.4822, 0.4465)):
self.probability = probability
self.mean = mean
self.sl = sl
self.sh = sh
self.r1 = r1
def __call__(self, img):
if random.uniform(0, 1) >= self.probability:#随机选择样本
return img
for attempt in range(100):
area = img.size()[1] * img.size()[2]#图像的区域大小
target_area = random.uniform(self.sl, self.sh) * area #擦除面积的比率
aspect_ratio = random.uniform(self.r1, 1 / self.r1) #长宽比的上下界
#求长宽area=wh,ar=h/w,所以:area*ar=h*h;area/ar=w*w
h = int(round(math.sqrt(target_area * aspect_ratio)))
w = int(round(math.sqrt(target_area / aspect_ratio)))
#如果长宽满足要求,就设置为均值
if w < img.size()[2] and h < img.size()[1]:
#找到随机的一个矩形区域的左上角坐标,定矩形位置
x1 = random.randint(0, img.size()[1] - h)
y1 = random.randint(0, img.size()[2] - w)
#根据通道数设置区域像素值
if img.size()[0] == 3:
img[0, x1:x1 + h, y1:y1 + w] = self.mean[0]
img[1, x1:x1 + h, y1:y1 + w] = self.mean[1]
img[2, x1:x1 + h, y1:y1 + w] = self.mean[2]
else:
img[0, x1:x1 + h, y1:y1 + w] = self.mean[0]
return img
return img