def color_skew(image):
h, s, v = cv2.split(image)
h = h * np.random.uniform(low=0, high=6)
s = s * np.random.uniform(low=1, high=4)
v = v * np.random.uniform(low=0, high=6)
return cv2.merge((h, s, v))
def rgb_norm(image):
r, g, b = cv2.split(image)
r = (r - np.mean(r)) / np.std(r)
g = (g - np.mean(g)) / np.std(g)
b = (b - np.mean(b)) / np.std(b)
return cv2.merge((r, g, b))
cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def ben_graham(image):
image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
image = cv2.GaussianBlur(image, (5, 5), 0)
return image
cv2.cvtColor(image, cv2.COLOR_RGB2HLS)
cv2.cvtColor(image, cv2.COLOR_RGB2LUV)
cv2.cvtColor(image, cv2.COLOR_RGB2RGBA)
cv2.cvtColor(image, cv2.COLOR_RGB2XYZ)
cv2.cvtColor(image, cv2.COLOR_RGB2YCrCb)
cv2.cvtColor(image, cv2.COLOR_RGB2Lab)
cv2.cvtColor(image, cv2.COLOR_RGB2YUV)
transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5, hue=0.5)
transforms.CenterCrop((100, 100))
def flippings(image):
if np.random.uniform() < 0.5:
image = cv2.flip(image, 1)
return image
transforms.RandomCrop((100, 100))
transforms.RandomResizedCrop((100, 100))
transforms.RandomAffine(degrees=45, translate=(0.1, 0.1), scale=(0.5, 2.0), shear=45)
transforms.RandomHorizontalFlip()
transforms.RandomVerticalFlip()
transforms.RandomPerspective()
transforms.RandomRotation(degrees=45)
transforms.RandomInvert()
transforms.RandomPosterize(bits=4)
transforms.RandomSolarize(threshold=128)
transforms.RandomAutocontrast()
transforms.RandomEqualize()
from autoaugment import AutoAugment
auto_augment = AutoAugment()
image = auto_augment(image)
from fast_autoaugment import FastAutoAugment
fast_auto_augment = FastAutoAugment()
image = fast_auto_augment(image)
from augmix import AugMix
aug_mix = AugMix()
image = aug_mix(image)
x=lambda*x1+(1-lambda)x2
y=lambda*x1+(1-lambda)y2
添加验证集数据增强将提高模型在测试时间增强上的性能,从而提高绝对性能。但如果寻求获得更好的性能,则使用一些验证集进行数据增强实验或在训练期间进行数据增强实验,并使用另一部分增加性能参数,这将减少模型过的拟合。
增强不仅在训练中有用,在测试时也有用。简单地将它们应用于预测和平均结果。
添加更多的层是有益的,因为可以使用它们来学习更高级的功能,同时它也可以对大型预训练模型进行微调。
一个简单的技巧可以让你有一个微小的改善,那就是随着训练的进行,解冻你预先训练过的主干网络。
增加更多的层,并且冻结其他的层:事实证明,许多解决方案甚至可以通过在预先训练的模型训练后加入另一个训练阶段来进一步改进!这可以通过冻结预训练的模型并在其之后添加密集层来实现。
在PyTorch中冻结和解冻权重
# Weight freezing
for param in model.parameters():
param.requires_grad = False # unfreeze weights in at all
# Weight unfreezing
for param in model.parameters():
param.requires_grad = True # unfreeze weights in at all
TensorFlow中的冻结和解冻权重
# Weight freezing
layer.trainable = False
# Weight unfreezing
layer.trainable = True
学习率和学习率调度器会影响模型的训练性能。改变学习率会对性能和训练收敛产生很大的影响。
最近,单周期余弦计划已经证明可以在多个NLP任务中提供更好的结果,可以这样使用它:
pytorch中一个余弦周期
from torch.optim.lr_scheduler import CosineAnnealingLR
optimizer = torch.optim.AdamW(optimizer_grouped_parameters, lr=args.learning_rate, eps=args.adam_epsilon)
scheduler = CosineAnnealingLR(optimizer, T_max=num_train_optimization_steps)
num_training_steps = num_train_optimization_steps / args.gradient_accumulation_steps
# Update the scheduler
scheduler.step()
# step the learning rate scheduler here, you will want to step the learning rate scheduler only once per optimizer step nothing more nothing less. So in this case, it should be called before you expect the gradients to be applied.
tensorflow中一个余弦周期
optimizer = tf.keras.optimizers.Adam(learning_rate)
scheduler = tf.keras.optimizers.schedules.CosineDecay(learning_rate, decay_steps=num_training_steps)
Triangular
或One Cyclic
方法进行学习率调度可以提供微妙但显著的改进,这些智能学习率调度方法可以克服一些批处理大小问题。如果你想从Adam优化器中获得最佳性能,有几件事你需要知道:
beta1
和beta2
,选择最佳值取决于您的任务和数据。许多新任务可以从较低的beta1
和较高的beta2
中受益,而对于已建立的任务,它们将执行相反的操作。ε
值的重要性。寻找最佳权值衰减超参数的原理同样适用于这里。dropout
!在层之间添加层dropout
通常会产生更多的训练稳定性和更健壮的结果,而且应该在隐藏层中使用。L1
或L2
正则化是可以的,但也可以尝试使用添加层和隐藏层。现在每个人都在用Adam或AdamW。但是需要考虑的是,如果你的SGD有足够的动量进行超参数搜索,你可能会得到更好的结果。但这同样需要大量的调整。
有几个值得注意的重要优化器需要了解:
基本上是一个简单的技巧: y _ t r u e = y _ t r u e ∗ ( 1.0 − ε ) + 0.5 ∗ ε [ e x a m p l e : ε = 0.001 ] y\_true=y\_true*(1.0-\varepsilon)+0.5*\varepsilon [example: \varepsilon = 0.001] y_true=y_true∗(1.0−ε)+0.5∗ε[example:ε=0.001],通常效果很好。
Tensorflow
loss = BinaryCrossentropy(label_smoothing = label_smoothing)
pytorch
from torch.nn.modules.loss import _WeightedLoss
class SmoothBCEwLogits(_WeightedLoss):
def __init__(self, weight = None, reduction = 'mean', smoothing = 0.0, pos_weight = None):
super().__init__(weight=weight, reduction=reduction)
self.smoothing = smoothing
self.weight = weight
self.reduction = reduction
self.pos_weight = pos_weight
@staticmethod
def _smooth(targets, n_labels, smoothing = 0.0):
assert 0 <= smoothing < 1
with torch.no_grad(): targets = targets * (1.0 - smoothing) + 0.5 * smoothing
return targets
def forward(self, inputs, targets):
targets = SmoothBCEwLogits._smooth(targets, inputs.size(-1), self.smoothing)
loss = F.binary_cross_entropy_with_logits(inputs, targets,self.weight, pos_weight = self.pos_weight)
if self.reduction == 'sum': loss = loss.sum()
elif self.reduction == 'mean': loss = loss.mean()
return loss
用一个大的教师网来指导一个小的教师网的学习。
使用一个模型来标记未标记的数据(例如测试数据),然后使用新的标记数据来训练模型。
如何进行CV伪标注?简单:将未标记的数据连接到OOF,并像使用堆叠一样简单地使用它们。
一个可以为您节省大量时间的重要实践是使用您的模型来查找更难或破碎的数据样本。
对于你的模型来说,一个图像“更难”的原因有很多,例如,小的目标对象,不同的颜色,被切断的目标,无效的注释等等。
有错误反而是好消息!
如果你很难解释你的模型发生了什么,看看你的模型遇到的验证样本可能是个好主意。
发现错误最简单的方法是根据模型的置信度评分对验证样本进行排序,并查看哪些样本被预测的置信度最低。
mistakes_idx = [img_idx for img_idx in range(len(train)) if int(pred[img_idx] > 0.5) != target[img_idx]]
mistakes_preds = pred[mistakes_idx]
sorted_idx = np.argsort(mistakes_preds)[:20]
# Show the images of the sorted idx here..
Image Classification Tips & Tricks