Como criar rótulo de classe para aumento do mosaico na classificação de imagens?
Para criar um rótulo de classe CutMix
ou MixUp
aumento de tipo, podemos usar beta
como np.random.beta
ou scipy.stats.beta
e fazer o seguinte para dois rótulos:
label = label_one*beta + (1-beta)*label_two
Mas e se tivermos mais de duas imagens? No YoLo4 , eles tentaram um aumento interessante chamado Aumento do mosaico para problemas de detecção de objetos. Ao contrário de CutMix
ou MixUp
, este aumento cria amostras aumentadas com 4 imagens. Em casos de detecção de objetos, podemos calcular a mudança das coordenadas de cada instância e, assim, ser possível obter a verdade básica adequada aqui . Mas apenas para casos de classificação de imagem, como podemos fazer isso?
Aqui está um começo .
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))
Aqui está uma função que escrevemos para este aumento; (muito feio com um inner-outer
loop! Por favor, sugira se podemos fazer isso de forma eficiente.)
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
As amostras aumentadas, atualmente com os rótulos errados.
data, label = mosaicmix(train_images, train_labels, 32)
plt.imshow(data[5]/255)

No entanto, aqui estão mais alguns exemplos de como motivar você. Os dados são do concurso Folha de Mandioca .
No entanto, para obter o rótulo adequado dessa amostra aumentada, tentamos algo assim, digamos que para cada interação sobre os lotes dentro do loop externo e do loop interno se pudermos calcular a distribuição das 4 amostras, como cada uma delas cobre a área interna mosaic_image
, de modo que possamos multiplicar cada uma com probabilidade de distribuição de 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)
Respostas
Já sabemos que, no CutMix , λ
é um número flutuante da distribuição beta Beta (α, α). Vimos, quando α=1
, ele tem o melhor desempenho. Agora, se concedermos α==1
sempre, podemos dizer que λ
é uma amostra da distribuição uniforme. .
Podemos simplesmente dizer que λ
é apenas um número de ponto flutuante cujo valor será de 0 a 1.
Portanto, apenas para 2 imagens, se usarmos λ
para a 1ª imagem, podemos calcular a parte desconhecida restante simplesmente por 1-λ
.
Mas para 3 imagens, se usarmos λ
para a 1ª imagem, não podemos calcular outras 2 incógnitas daquela única λ
. Se realmente quisermos fazer isso, precisamos de 2 números aleatórios para 3 imagens. Da mesma forma, podemos dizer que para o n
número de imagens, precisamos da n-1
variável aleatória número. E em todos os casos, o somatório deve ser 1
. (por exemplo, λ + (1-λ) == 1
). Se a soma não for 1
, o rótulo estará errado!
Para este propósito, a distribuição de Dirichlet pode ser útil porque ajuda a gerar quantidades que somam 1. Uma variável aleatória distribuída por Dirichlet pode ser vista como uma generalização multivariada de uma distribuição 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]])
No CutMix , o tamanho da parte recortada de uma imagem tem uma relação com a λ
qual pesa os rótulos correspondentes.


Portanto, para múltiplos λ
, você também precisa calculá-los de acordo.
# 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
Outra maneira de ver esse problema é considerar as linhas de separação para as dimensões de largura e altura. Ao construir a imagem em mosaico, o objetivo é combinar 4 imagens em uma única imagem. Podemos conseguir isso amostrando aleatoriamente os pontos médios (denotando os pontos de separação) em cada dimensão. Isso remove o requisito bastante complicado de amostrar 4 números somando 1. Em vez disso, o objetivo agora é amostrar 2 valores independentes de uma distribuição uniforme - uma alternativa muito mais simples e intuitiva.
Então, essencialmente, amostramos dois valores:
w = np.random.uniform(0, 1)
h = np.random.uniform(0, 1)
Para gerar mosaicos realistas onde cada imagem tem uma contribuição perceptível, podemos amostrar valores de [0,25 0,75], ao invés de [0, 1]
Esses dois valores são suficientes para parametrizar o problema do mosaico. Cada imagem no mosaico ocupa áreas abrangidas pelas seguintes coordenadas: Considere que a imagem do mosaico tem dimensões LxH e os pontos médios de cada dimensão são representados por w e h respectivamente.
- superior esquerdo - (0, 0) a (w, h)
- superior direito - (w, 0) a (W, h)
- inferior esquerdo - (0, h) a (w, H)
- inferior direito - (w, h) a (W, H)
Os pontos médios amostrados também ajudam no cálculo dos rótulos das classes. Vamos supor que decidamos usar a área que cada imagem ocupa dentro do mosaico como sua contribuição correspondente para o rótulo geral da classe. Por exemplo, considere 4 imagens pertencentes a 4 classes {0, 1, 2, 3}. Agora suponha que a imagem '0' ocupe a parte superior esquerda, '1' a parte superior direita, '2' a parte inferior esquerda e '3' a parte inferior direita. Podemos construir o rótulo de classe 'L' da seguinte maneira
você pode ver a equação neste link