Bagaimana Cara Membuat Label Kelas untuk Augmentasi Mosaik pada Klasifikasi Gambar?

Dec 07 2020

Untuk membuat label kelas dalam CutMixatau MixUptipe augmentasi, kita dapat menggunakan betaseperti np.random.betaatau scipy.stats.betadan melakukan hal berikut untuk dua label:

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

Tetapi bagaimana jika kita memiliki lebih dari dua gambar? Di YoLo4 , mereka telah mencoba augmentasi menarik yang disebut Augmentasi Mosaic untuk masalah deteksi objek. Tidak seperti CutMixatau MixUp, augmentasi ini membuat sampel yang ditambah dengan 4 gambar. Dalam kasus deteksi objek, kita dapat menghitung pergeseran setiap co-ords instance dan dengan demikian memungkinkan untuk mendapatkan kebenaran dasar yang tepat, di sini . Tetapi hanya untuk kasus klasifikasi gambar, bagaimana kita bisa melakukannya?

Ini permulaannya .

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

Berikut adalah fungsi yang telah kami tulis untuk augmentasi ini; (terlalu jelek dengan inner-outerlingkaran! Sarankan jika kami dapat melakukannya secara efisien.)

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

Sampel yang ditambah, saat ini dengan label yang salah.

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


Namun, berikut beberapa contoh memotivasi Anda. Data berasal dari kompetisi Daun Singkong .


Namun, untuk mendapatkan label yang tepat dari sampel yang ditambah ini, kami mencoba sesuatu seperti ini, katakanlah untuk setiap interaksi pada kumpulan di dalam loop luar dan loop dalam jika kami dapat menghitung distribusi dari 4 sampel, seperti bagaimana masing-masing mencakup area di dalamnya mosaic_image, sehingga kita dapat mengalikan masing-masing dengan probabilitas distribusi 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)
            

Jawaban

4 UzzalPodder Dec 07 2020 at 20:43

Kita sudah tahu bahwa, di CutMix , λadalah angka float dari distribusi beta Beta (α, α). Kami telah melihat, kapan α=1, kinerjanya terbaik. Sekarang, Jika kita α==1selalu mengabulkan , kita dapat mengatakan itu λadalah sampel dari distribusi seragam. .

Sederhananya bisa kita katakan λhanyalah bilangan floating-point yang nilainya akan menjadi 0 hingga 1.

Jadi, hanya untuk 2 gambar saja, jika kita menggunakan λuntuk gambar pertama maka kita dapat menghitung sisa bagian yang belum diketahui hanya dengan cara 1-λ.

Tetapi untuk 3 gambar, jika kita menggunakan λuntuk gambar pertama, kita tidak bisa menghitung 2 ketidaktahuan lainnya dari single itu λ. Jika kita benar-benar ingin melakukannya, kita membutuhkan 2 angka acak untuk 3 gambar. Dengan cara yang sama, kita dapat mengatakan bahwa untuk njumlah gambar, kita membutuhkan n-1variabel angka acak. Dan dalam semua kasus, penjumlahan seharusnya 1. (misalnya, λ + (1-λ) == 1). Jika jumlahnya tidak 1, labelnya akan salah!

Untuk tujuan ini, distribusi Dirichlet mungkin berguna karena membantu menghasilkan jumlah yang berjumlah 1. Variabel acak terdistribusi Dirichlet dapat dilihat sebagai generalisasi multivariat dari distribusi 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]])

Di CutMix , ukuran bagian gambar yang dipotong memiliki hubungan dengan λpembobotan label yang sesuai.

Jadi, untuk kelipatan λ, Anda juga perlu menghitungnya dengan tepat.

# 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

Cara lain untuk melihat masalah ini adalah dengan mempertimbangkan garis pemisah untuk dimensi lebar dan tinggi. Saat membuat gambar mosaik, tujuannya adalah menggabungkan 4 gambar menjadi satu gambar. Kita dapat mencapai ini dengan mengambil sampel titik tengah secara acak (menunjukkan titik pemisah) di setiap dimensi. Ini menghilangkan persyaratan yang agak rumit dari pengambilan sampel 4 angka yang berjumlah 1. Sebaliknya, tujuan sekarang adalah untuk mengambil sampel 2 nilai independen dari distribusi seragam - alternatif yang jauh lebih sederhana dan lebih intuitif.

Jadi intinya, kami mengambil sampel dua nilai:

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

Untuk menghasilkan mosaik realistis di mana setiap gambar memiliki kontribusi yang nyata, kita dapat mengambil sampel nilai dari [0,25 0,75], bukan dari [0, 1]

Kedua nilai ini cukup untuk menentukan parameter masalah mozaik. Setiap gambar dalam mozaik menempati area yang direntangkan oleh koordinat berikut: Pertimbangkan bahwa gambar mozaik memiliki dimensi WxH dan titik tengah masing-masing dimensi diwakili oleh w dan h .

  • kiri atas - (0, 0) sampai (w, h)
  • kanan atas - (w, 0) hingga (W, h)
  • kiri bawah - (0, h) sampai (w, H)
  • kanan bawah - (w, h) to (W, H)

Titik tengah sampel juga membantu dalam menghitung label kelas. Misalkan kita memutuskan untuk menggunakan area yang ditempati setiap gambar dalam mozaik sebagai kontribusinya yang sesuai untuk label kelas secara keseluruhan. Misalnya Pertimbangkan 4 gambar milik 4 kelas {0, 1, 2, 3}. Sekarang asumsikan bahwa gambar '0' menempati kiri atas, '1' di kanan atas, '2' di kiri bawah dan '3' di kanan bawah. Kita dapat membuat label kelas 'L' sebagai berikut

Anda dapat melihat persamaan di tautan ini