Как создать метку класса для увеличения мозаики в классификации изображений?

Dec 07 2020

Чтобы создать метку класса CutMixили MixUpрасширение типа, мы можем использовать betaтакой как np.random.betaили scipy.stats.betaи сделать следующее для двух меток:

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

Но что, если у нас более двух изображений? В YoLo4 они попробовали интересное дополнение под названием Mosaic Augmentation для решения проблем с обнаружением объектов. В отличие от CutMixили MixUp, это расширение создает расширенные образцы с 4 изображениями. В случае обнаружения объекта, мы можем вычислить смещение каждого экземпляра со-ords и , таким образом , можно получить надлежащую землю правду, здесь . Но как мы можем это сделать только для случаев классификации изображений?

Вот стартер .

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))

Вот функция, которую мы написали для этого дополнения; (слишком уродливо с inner-outerпетлей! Пожалуйста, подскажите, сможем ли мы сделать это эффективно.)

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)


Однако вот еще несколько примеров, которые вас мотивируют. Данные взяты из конкурса листьев маниоки .


Однако, чтобы получить правильную метку из этого расширенного образца, мы попробовали что-то вроде этого, скажем, для каждого взаимодействия по пакетам внутри внешнего цикла и внутреннего цикла, если мы можем вычислить распределение 4 образцов, например, как каждый из них покрывает площадь внутри mosaic_image, так что мы можем умножить каждую с вероятностью распределения a.

    # Iterate over the full indices 
    for j in range(len(indices)): 
        
        b = tf.random.uniform([],0,1) # this is beta dist with alpha=1.0
        P = tf.cast( tf.random.uniform([],0,1)<=1.0, tf.int32) 

        for i in range(len(rand4indices)):
            ....
            WIDTH = tf.cast( DIM * tf.math.sqrt(1-b),tf.int32) * P  
            a = tf.cast(WIDTH*WIDTH/DIM/DIM,tf.float32)
            

Ответы

4 UzzalPodder Dec 07 2020 at 20:43

Мы уже знаем , что в CutMix , λявляется поплавок число от бета - бета - распределения (а, а). Мы видели, когда α=1это работает лучше всего. Теперь, если мы α==1всегда допускаем, мы можем сказать, что λэто выбрано из равномерного распределения. .

Мы можем λпросто сказать, что это просто число с плавающей запятой, значение которого будет от 0 до 1.

Итак, только для 2 изображений, если мы используем λдля 1-го изображения, мы можем вычислить оставшуюся неизвестную часть просто с помощью 1-λ.

Но для 3 изображений, если мы используем λдля 1-го изображения, мы не сможем вычислить другие 2 неизвестных из этого единственного λ. Если мы действительно этого хотим, нам нужно 2 случайных числа для 3 изображений. Таким же образом мы можем сказать, что для nколичества изображений нам нужна n-1числовая случайная величина. И во всех случаях суммирование должно быть 1. (например, λ + (1-λ) == 1). Если сумма не указана 1, этикетка будет неправильной!

Для этой цели может оказаться полезным распределение Дирихле, поскольку оно помогает генерировать величины, сумма которых равна 1. Случайную величину с распределением Дирихле можно рассматривать как многомерное обобщение бета-распределения.

>>> 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
1 MostlyClueless Jan 13 2021 at 13:46

Другой способ взглянуть на эту проблему - рассмотреть разделительные линии как по ширине, так и по высоте. При построении мозаичного изображения цель состоит в том, чтобы объединить 4 изображения в одно изображение. Мы можем добиться этого, произвольно выбирая средние точки (обозначающие точки разделения) в каждом измерении. Это устраняет довольно сложное требование выборки 4 чисел в сумме до 1. Вместо этого теперь цель состоит в том, чтобы выбрать 2 независимых значения из равномерного распределения - гораздо более простая и интуитивно понятная альтернатива.

По сути, мы выбираем два значения:

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

Чтобы создать реалистичную мозаику, в которой каждое изображение имеет заметный вклад, мы можем выбрать значения из [0,25 0,75], а не из [0, 1]

Этих двух значений достаточно, чтобы параметризовать задачу мозаики. Каждое изображение в мозаике занимает области, охватываемые следующими координатами: Учтите, что изображение мозаики имеет размеры WxH, а средние точки каждого измерения представлены значениями w и h соответственно.

  • вверху слева - от (0, 0) до (w, h)
  • вверху справа - от (w, 0) до (W, h)
  • внизу слева - от (0, h) до (w, H)
  • внизу справа - от (w, h) до (W, H)

Отобранные средние точки также помогают в вычислении меток классов. Предположим, мы решили использовать область, занимаемую каждым изображением в мозаике, как соответствующий вклад в общую метку класса. Например, рассмотрим 4 изображения, принадлежащие 4 классам {0, 1, 2, 3}. Теперь предположим, что изображение «0» занимает верхний левый угол, «1» - верхний правый угол, «2» - нижний левый угол и «3» - нижний правый угол. Мы можем построить метку класса L следующим образом

вы можете просмотреть уравнение по этой ссылке