이미지 분류에서 모자이크 확대를위한 클래스 레이블을 만드는 방법은 무엇입니까?
에서 클래스 레이블을 만들려면 CutMix
또는 MixUp
형의 확대, 우리가 사용할 수있는 beta
등 np.random.beta
이나 scipy.stats.beta
와 같은 두 개의 레이블을 위해 다음을 수행하십시오
label = label_one*beta + (1-beta)*label_two
하지만 이미지 가 두 개 이상 이면 어떨까요? 에서 YoLo4 , 그들은라는 흥미로운 확대 노력했습니다 모자이크 증원 물체 검출 문제를. 달리 CutMix
또는 MixUp
이러한 보강은로 보강 된 샘플을 생성 4 개 이미지. 물체 감지의 경우 각 인스턴스 좌표의 이동을 계산할 수 있으므로 여기 에서 적절한 근거를 얻을 수 있습니다 . 그러나 이미지 분류의 경우에만 어떻게 할 수 있습니까?
여기에 스타터가 있습니다.
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)

그러나 여기에 동기를 부여하는 몇 가지 예가 더 있습니다. 데이터는 Cassava Leaf 대회 에서 가져온 것입니다.
그러나이 증가 된 샘플에서 적절한 레이블을 얻기 위해 우리는 다음과 같은 것을 시도했습니다. 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)
답변
우리는 이미 알고에 CutMix , λ
베타 분포 베타 (α, α)로부터 float 번호입니다. ,이 (가 α=1
) 가장 잘 수행 되는 것을 보았습니다 . 이제 α==1
항상 승인 λ
하면 균일 분포에서 샘플링 되었다고 말할 수 있습니다 . .
간단히 우리는 λ
값이 0에서 1이되는 부동 소수점 숫자 라고 말할 수 있습니다 .
따라서 2 개의 이미지에 대해서만 λ
첫 번째 이미지에 사용하면 미지의 나머지 부분을 간단히 계산할 수 있습니다 1-λ
.
그러나 3 개의 이미지 λ
에 대해 첫 번째 이미지에 사용하면 해당 단일에서 다른 2 개의 미지수 를 계산할 수 없습니다λ
. 정말로 그렇게하려면 3 개의 이미지에 대해 2 개의 난수가 필요합니다. 같은 방식 n
으로 이미지 수에 대해 n-1
숫자 랜덤 변수 가 필요 하다고 말할 수 있습니다 . 그리고 모든 경우에 합계는 1
. (예 λ + (1-λ) == 1
:). 합계가 아닌 1
경우 레이블이 잘못됩니다!
이 목적을 위해 Dirichlet 분포 는 합이 1이되는 양을 생성하는 데 도움이되므로 유용 할 수 있습니다. Dirichlet 분포 랜덤 변수는 베타 분포의 다변량 일반화로 볼 수 있습니다.
>>> 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
이 문제를 보는 또 다른 방법은 너비와 높이 치수 모두에 대한 분리 선을 고려하는 것입니다. 모자이크 이미지를 만들 때 목표는 4 개의 이미지를 하나의 이미지로 결합하는 것입니다. 우리는 각 차원에서 중간 점 (분리 점 표시)을 무작위로 샘플링하여이를 달성 할 수 있습니다. 이것은 4 개의 숫자를 1로 합산하는 다소 복잡한 요구 사항을 제거합니다. 대신 이제 목표는 균일 한 분포에서 2 개의 독립적 인 값을 샘플링하는 것입니다. 훨씬 간단하고 직관적 인 대안입니다.
따라서 기본적으로 두 가지 값을 샘플링합니다.
w = np.random.uniform(0, 1)
h = np.random.uniform(0, 1)
각 이미지의 기여도가 눈에 띄는 사실적인 모자이크를 생성하려면 [0, 1]이 아닌 [0.25 0.75]에서 값을 샘플링 할 수 있습니다.
이 두 값은 모자이크 문제를 매개 변수화하는 데 충분합니다. 모자이크의 각 이미지는 다음 좌표로 확장 된 영역을 차지합니다. 모자이크 이미지의 크기는 WxH 이고 각 차원의 중간 점은 각각 w 및 h로 표시 됩니다.
- 왼쪽 상단-(0, 0) ~ (w, h)
- 오른쪽 상단-(w, 0) ~ (W, h)
- 왼쪽 하단-(0, h) ~ (w, H)
- 오른쪽 하단-(w, h) ~ (W, H)
샘플링 된 중간 점은 클래스 레이블 계산에도 도움이됩니다. 각 이미지가 모자이크 내에서 차지하는 영역을 전체 클래스 레이블에 대한 해당 기여도로 사용하기로 결정했다고 가정 해 보겠습니다. 예를 들어 4 개의 클래스 {0, 1, 2, 3}에 속하는 4 개의 이미지를 고려하십시오. 이제 '0'이미지가 왼쪽 상단, '1'오른쪽 상단, '2'왼쪽 하단, '3'오른쪽 하단을 차지한다고 가정합니다. 다음과 같이 클래스 레이블 'L'을 만들 수 있습니다.
이 링크에서 방정식을 볼 수 있습니다.