Jak utworzyć etykietę klasy dla rozszerzania mozaiki w klasyfikacji obrazu?
Aby utworzyć etykietę klasy w rozszerzeniu CutMix
lub MixUp
typie rozszerzenia, możemy użyć beta
takich jak np.random.beta
lub scipy.stats.beta
i wykonać następujące czynności dla dwóch etykiet:
label = label_one*beta + (1-beta)*label_two
Ale co, jeśli mamy więcej niż dwa obrazy? W YoLo4 wypróbowali interesujące rozszerzenie o nazwie Mosaic Augmentation , które rozwiązuje problemy z wykrywaniem obiektów. W przeciwieństwie do CutMix
or MixUp
, to ulepszenie tworzy powiększone próbki z 4 obrazami. W przypadkach wykrywania obiektów możemy obliczyć przesunięcie współrzędnych każdego wystąpienia, a tym samym uzyskać tutaj właściwą prawdę o podłożu . Ale jak możemy to zrobić tylko w przypadku klasyfikacji obrazów?
Oto przystawka .
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))
Oto funkcja, którą napisaliśmy dla tego rozszerzenia; (zbyt brzydkie z inner-outer
pętlą! Proszę zasugerować, czy możemy to zrobić efektywnie).
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
Wzbogacone próbki, obecnie z niewłaściwymi etykietami.
data, label = mosaicmix(train_images, train_labels, 32)
plt.imshow(data[5]/255)

Jednak oto kilka innych przykładów motywacji. Dane pochodzą z konkursu Liść Manioku .
Jednak aby uzyskać odpowiednią etykietę z tej rozszerzonej próbki, próbowaliśmy czegoś takiego, powiedzmy dla każdej interakcji na partiach wewnątrz zewnętrznej pętli i wewnętrznej pętli, jeśli możemy obliczyć rozkład 4 próbek, na przykład sposób, w jaki każda z nich pokrywa obszar wewnątrz mosaic_image
, abyśmy mogli pomnożyć każdy z prawdopodobieństwem rozkładu równym 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)
Odpowiedzi
Wiemy już, że w CutMix , λ
jest liczbą pływak z Beta dystrybucji beta (a, a). Widzieliśmy, kiedy α=1
działa najlepiej. Teraz, jeśli α==1
zawsze przyznajemy , możemy powiedzieć, że λ
jest pobierane z rozkładu jednorodnego. .
Po prostu możemy powiedzieć, że λ
jest to po prostu liczba zmiennoprzecinkowa, której wartość będzie wynosić od 0 do 1.
Tak więc, tylko dla 2 obrazów, jeśli użyjemy λ
pierwszego obrazu, możemy obliczyć pozostałą nieznaną część po prostu przez 1-λ
.
Ale dla 3 obrazów, jeśli użyjemy λ
pierwszego obrazu, nie możemy obliczyć innych 2 niewiadomych z tego singla λ
. Jeśli naprawdę chcemy to zrobić, potrzebujemy 2 losowych liczb dla 3 obrazów. W ten sam sposób możemy powiedzieć, że dla n
liczby obrazów potrzebujemy n-1
zmiennej losowej liczby. I we wszystkich przypadkach sumowanie powinno być 1
. (na przykład λ + (1-λ) == 1
). Jeśli suma nie jest 1
, etykieta będzie błędna!
W tym celu rozkład Dirichleta może być pomocny, ponieważ pomaga wygenerować wielkości, których suma jest równa 1. Zmienna losowa o rozkładzie Dirichleta może być postrzegana jako wielowymiarowe uogólnienie rozkładu 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]])
W CutMix rozmiar przyciętej części obrazu ma związek z λ
ważeniem odpowiednich etykiet.


Tak więc w przypadku wielu λ
musisz również odpowiednio je obliczyć.
# 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
Innym sposobem spojrzenia na ten problem jest rozważenie linii separacji zarówno dla wymiarów szerokości, jak i wysokości. Podczas budowania obrazu mozaiki celem jest połączenie 4 obrazów w jeden obraz. Możemy to osiągnąć poprzez losowe próbkowanie punktów środkowych (oznaczających punkty separacji) w każdym wymiarze. Eliminuje to dość skomplikowany wymóg próbkowania 4 liczb sumujących się do 1. Zamiast tego celem jest teraz próbkowanie 2 niezależnych wartości z jednorodnego rozkładu - znacznie prostsza i bardziej intuicyjna alternatywa.
Zasadniczo więc próbkujemy dwie wartości:
w = np.random.uniform(0, 1)
h = np.random.uniform(0, 1)
Aby wygenerować realistyczne mozaiki, w których każdy obraz ma zauważalny udział, możemy próbkować wartości z [0,25 0,75], a nie z [0, 1]
Te dwie wartości są wystarczające do sparametryzowania problemu mozaiki. Każdy obraz w mozaice zajmuje obszary rozciągnięte przez następujące współrzędne: Należy wziąć pod uwagę, że obraz mozaiki ma wymiary WxH, a punkty środkowe każdego wymiaru są reprezentowane odpowiednio przez w i h .
- lewy górny - (0, 0) do (w, h)
- prawy górny róg - (w, 0) do (W, h)
- na dole po lewej - (0, h) do (w, H)
- prawy dolny - (w, h) do (W, H)
Próbkowane punkty środkowe również pomagają w obliczaniu etykiet klas. Załóżmy, że zdecydujemy się użyć obszaru zajmowanego przez każdy obraz w mozaice jako odpowiadającego mu udziału w ogólnej etykiecie klasy. Na przykład rozważ 4 obrazy należące do 4 klas {0, 1, 2, 3}. Teraz załóżmy, że obraz „0” zajmuje górny lewy, „1” górny prawy, „2” dolny lewy i „3” dolny prawy. Możemy zbudować etykietę klasy „L” w następujący sposób
możesz wyświetlić równanie pod tym linkiem