如何为图像分类中的马赛克增强创建类标签?

Posted

技术标签:

【中文标题】如何为图像分类中的马赛克增强创建类标签?【英文标题】:How to Create Class Label for Mosaic Augmentation in Image Classification? 【发布时间】:2021-03-18 17:36:47 【问题描述】:

要在CutMixMixUp 类型扩充中创建类标签,我们可以使用beta,例如np.random.betascipy.stats.beta,并对两个标签执行以下操作:

label = label_one*beta + (1-beta)*label_two

但如果我们有两个以上图像怎么办?在YoLo4 中,他们尝试了一种有趣的增强方法,称为Mosaic Augmentation 来解决对象检测问题。与 CutMixMixUp 不同,这种增强创建了具有 4 图像的增强样本。在目标检测案例中,我们可以计算每个实例坐标的偏移,从而有可能获得正确的基本事实,here。但是对于只有图像分类的情况,我们该怎么做呢?

这是一个入门

import tensorflow as tf
import matplotlib.pyplot as plt 
import random

(train_images, train_labels), (test_images, test_labels) = \
tf.keras.datasets.cifar10.load_data()
train_images = train_images[:10,:,:]
train_labels = train_labels[:10]
train_images.shape, train_labels.shape

((10, 32, 32, 3), (10, 1))

这是我们为此增强功能编写的一个函数; (“内-外循环”太丑了!请建议我们是否可以有效地做到这一点。)

def mosaicmix(image, label, DIM, minfrac=0.25, maxfrac=0.75):
    '''image, label: batches of samples 
    '''
    xc, yc  = np.random.randint(DIM * minfrac, DIM * maxfrac, (2,))
    indices = np.random.permutation(int(image.shape[0]))
    mosaic_image = np.zeros((DIM, DIM, 3), dtype=np.float32)
    final_imgs, final_lbs = [], []

    # Iterate over the full indices 
    for j in range(len(indices)): 
        # Take 4 sample for to create a mosaic sample randomly 
        rand4indices = [j] + random.sample(list(indices), 3) 
        
        # Make mosaic with 4 samples 
        for i in range(len(rand4indices)):
            if i == 0:    # top left
                x1a, y1a, x2a, y2a =  0,  0, xc, yc
                x1b, y1b, x2b, y2b = DIM - xc, DIM - yc, DIM, DIM # from bottom right        
            elif i == 1:  # top right
                x1a, y1a, x2a, y2a = xc, 0, DIM , yc
                x1b, y1b, x2b, y2b = 0, DIM - yc, DIM - xc, DIM # from bottom left
            elif i == 2:  # bottom left
                x1a, y1a, x2a, y2a = 0, yc, xc, DIM
                x1b, y1b, x2b, y2b = DIM - xc, 0, DIM, DIM-yc   # from top right
            elif i == 3:  # bottom right
                x1a, y1a, x2a, y2a = xc, yc,  DIM, DIM
                x1b, y1b, x2b, y2b = 0, 0, DIM-xc, DIM-yc    # from top left
                
            # Copy-Paste
            mosaic_image[y1a:y2a, x1a:x2a] = image[i,][y1b:y2b, x1b:x2b]

        # Append the Mosiac samples
        final_imgs.append(mosaic_image)
        
    return final_imgs, label

增强样本,当前标签错误。

data, label = mosaicmix(train_images, train_labels, 32)
plt.imshow(data[5]/255)


但是,这里还有一些可以激励您的示例。数据来自Cassava Leaf 比赛。

【问题讨论】:

【参考方案1】:

我们已经知道,在 CutMix 中,λ 是来自 beta 分布 Beta(α,α) 的浮点数。我们已经看到,当α=1 时,它表现最好。现在,如果我们总是授予α==1,我们可以说λ 是从均匀分布中采样的。

简单地说,λ 只是一个浮点数,其值为 0 到 1。

因此,仅适用于 2 张图片, 如果我们将λ 用于第一张图像,那么我们可以简单地通过1-λ 计算剩余的未知部分。

但是对于 3 张图像,如果我们将 λ 用于第一张图像,我们无法从该单个 λ 计算其他 2 个未知数。如果我们真的想这样做,我们需要 3 个图像的 2 个随机数。同样,我们可以说对于n 个图像,我们需要n-1 个随机变量。在所有情况下,总和应该是1。 (例如,λ + (1-λ) == 1)。如果总和不是1,标签就会出错!

为此,Dirichlet 分布 可能会有所帮助,因为它有助于生成总和为 1 的数量。Dirichlet 分布的随机变量可以看作是Beta 分布。

>>> np.random.dirichlet((1, 1), 1)  # for 2 images. Equivalent to λ and (1-λ)
array([[0.92870347, 0.07129653]])  
>>> np.random.dirichlet((1, 1, 1), 1)  # for 3 images.
array([[0.38712673, 0.46132787, 0.1515454 ]])
>>> np.random.dirichlet((1, 1, 1, 1), 1)  # for 4 images.
array([[0.59482542, 0.0185333 , 0.33322484, 0.05341645]])

CutMix中,图像被裁剪部分的大小与λ相关,λ对相应的标签进行加权。

所以,对于多个λ,也需要进行相应的计算。

# let's say for 4 images
# I am not sure the proper way. 

image_list = [4 images]
label_list = [4 label]
new_img = np.zeros((w, h))

beta_list = np.random.dirichlet((1, 1, 1, 1), 1)[0]
for idx, beta in enumerate(beta_list):
    x0, y0, w, h = get_cropping_params(beta, full_img)  # something like this
    new_img[x0, y0, w, h] = image_list[idx][x0, y0, w, h]
    label_list[idx] = label_list[idx] * beta

【讨论】:

【参考方案2】:

查看此问题的另一种方法是考虑宽度和高度尺寸的分隔线。在构建马赛克图像时,目标是将 4 个图像组合成一个图像。我们可以通过在每个维度中随机采样中点(表示分离点)来实现这一点。这消除了采样 4 个数字总和为 1 的相当复杂的要求。相反,现在的目标是从均匀分布中采样 2 个独立值 - 一个更简单和更直观的替代方案。

所以本质上,我们采样了两个值:

w = np.random.uniform(0, 1)
h = np.random.uniform(0, 1)

要生成逼真的马赛克,其中每张图像都有明显的贡献,我们可以从[0.25 0.75] 中采样值,而不是从[0, 1] 中采样

这两个值足以参数化镶嵌问题。马赛克中的每个图像都占据由以下坐标跨越的区域: 假设马赛克图像有维度W x H,每个维度的中点分别用wh表示。

 - top left     - (0, 0) to (w, h)
 - top right    - (w, 0) to (W, h)
 - bottom left  - (0, h) to (w, H)
 - bottom right - (w, h) to (W, H)

采样的中点也有助于计算类标签。假设我们决定使用每个图像在马赛克中占据的区域作为其对整体类标签的相应贡献。例如,考虑属于 40, 1, 2, 34 个图像。现在假设0 图像占据左上角,1 占据右上角,2 占据左下角,3 占据右下角。我们可以如下构建类标签L

【讨论】:

等式有点不清楚。也许你可以在某个地方重写它 @Willysatrionugroho 对不起。我已经用更清晰的图像更新了答案。

以上是关于如何为图像分类中的马赛克增强创建类标签?的主要内容,如果未能解决你的问题,请参考以下文章

如何为图像分类准备训练数据

如何为 LSTM 重塑数据 - 时间序列多类分类

如何为数据增强创建噪声图像

如何为多标签分类器/一对休息分类器腌制 sklearn 管道?

图像分类竞赛涨分小技巧——以智能硬件语音控制的时频图分类挑战赛为例

使用 PyTorch 的多标签、多类图像分类器 (ConvNet)