Annotation data efficient learning

Annotation data efficient learning


✅ Data augmentation

1️⃣ Learning representation of dataset

image.png

우리가 얻어지는 Dataset은 거의 대부분 편향된 데이터이다.
왜냐하면 우리가 얻는 이미지는 카메라로 찍은 이미지가 될 것이고 이것은 사람들이 이쁘게 찍기위한 구도로 거의 비슷한 각도로 많이 존재하기 때문이다. 따라서 traing datareal data와는 차이가 존재한다.


📌 훈련 데이터 세트는 실제 데이터의 일부만 포함한다.

image.png

우리는 이러한 차이를 메워서 모델의 정확도를 높일수 있다.


2️⃣ Data augmentation

image.png

  • 데이터 셋에 다야한 이미지 변환을 적용한다.
    • Crop, Shear, Brightness, Perspctive, Rotate ...
  • OpenCV 및 NumPy에 data augmentation의 다양한 방법들이 존재한다.
  • 목표는 실제 데이터의 분포와 유사한 학습용 데이터를 만드는 것이다.


3️⃣ Various data augmentation methods

코드 한줄로 이미지 데이터 augmentation 얻기

📌 Brightness adjustment

image.png

  • 데이터 셋의 밝기를 조정한다.
In [1]:
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

image_pil = Image.open('./data/Angkko.png')
In [2]:
image_pil
Out[2]:


🔎 이미지 numpy array로 받는 방법

In [3]:
# 방법 1
arr = np.array(image_pil)
arr.shape, arr.dtype
Out[3]:
((267, 200, 4), dtype('uint8'))
  • 여기서 arr의 값은 0 ~ 255값의 RGB값이 가진다.
In [4]:
plt.title('Origin')
plt.xticks([]) # x축 눈금 안보이게
plt.yticks([]) # y축 눈금 안보이게
plt.imshow(arr)
Out[4]:
<matplotlib.image.AxesImage at 0x2e9db576508>
In [5]:
def brightness_augmentation(img_origin,val):
    # 원본 보존
    img = img_origin.copy()
    # numpy array img has RGB value(0~255) for each pixel
    img[:,:,0] += val # R 값에 val 추가
    img[:,:,1] += val # R 값에 val 추가
    img[:,:,2] += val # R 값에 val 추가
    
    # 255가 넘는 값에 대한 처리
    img[:,:,0][img[:,:,0]>255] = 255
    img[:,:,1][img[:,:,1]>255] = 255
    img[:,:,2][img[:,:,2]>255] = 255
    return img
In [6]:
new_arr=brightness_augmentation(arr,50)
plt.title('Origin')
plt.xticks([]) # x축 눈금 안보이게
plt.yticks([]) # y축 눈금 안보이게
plt.imshow(new_arr)
Out[6]:
<matplotlib.image.AxesImage at 0x2e9df06e808>
  • 위 코드대로 돌리게 되면 명암이 조정 되지 않는다.
In [7]:
def brightness_augmentation2(img_origin,val):
    # 원본 보존
    img = img_origin.copy()
    # numpy array img has RGB value(0~255) for each pixel
    img[:,:,3] += val # R 값에 val 추가
    
    # 255가 넘는 값에 대한 처리
    img[:,:,3][img[:,:,0]>255] = 255
    return img
In [8]:
new_arr=brightness_augmentation2(arr,50)
plt.title('Origin')
plt.xticks([]) # x축 눈금 안보이게
plt.yticks([]) # y축 눈금 안보이게
plt.imshow(new_arr)
Out[8]:
<matplotlib.image.AxesImage at 0x2e9df0abac8>
  • 위 코드는 투명도를 조절하여 augmentation을 진행하였다.
In [9]:
import numpy as np
import cv2
import matplotlib.pyplot as plt
In [10]:
def brightness_augment(img_origin, factor=0.5):
    img=img_origin.copy()
    hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) #convert to hsv
    hsv = np.array(hsv, dtype=np.float64)
    hsv[:, :, 2] = hsv[:, :, 2] * (factor) #scale channel V uniformly
    hsv[:, :, 2][hsv[:, :, 2] > 255] = 255 #reset out of range values
    rgb = cv2.cvtColor(np.array(hsv, dtype=np.uint8), cv2.COLOR_HSV2RGB)
    return rgb
In [11]:
img=cv2.imread('./data/Angkko.png',-1)
# 이 부분은 밑에서 설명
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
In [12]:
new_img=brightness_augment(img,0.5)
In [13]:
plt.figure(figsize=(8,8))

plt.subplot(121)
plt.xticks([]) # x축 눈금 안보이게
plt.yticks([]) # y축 눈금 안보이게
plt.title('Origin')
plt.imshow(img)

plt.subplot(122)
plt.xticks([]) # x축 눈금 안보이게
plt.yticks([]) # y축 눈금 안보이게
plt.title('Brightness')
plt.imshow(new_img)
Out[13]:
<matplotlib.image.AxesImage at 0x2e9df21f2c8>


📌 Rotate, Flip

image.png

  • 데이터 셋의 각도 조절한다.
In [14]:
import numpy as np
import cv2
import matplotlib.pyplot as plt
In [15]:
img=cv2.imread('./data/Angkko.png',-1)
In [16]:
img.shape
Out[16]:
(267, 200, 4)
In [17]:
# 사진 띄우기
# matplotlib에서 rgb 채널 순서가 다르다
# RGB -> red / green /blue
# opencv -> blue / red /green
plt.imshow(img)
Out[17]:
<matplotlib.image.AxesImage at 0x2e9df2738c8>
In [18]:
fix_img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(fix_img)
Out[18]:
<matplotlib.image.AxesImage at 0x2e9df2eb948>
In [19]:
img_rotated=cv2.rotate(fix_img,cv2.ROTATE_90_CLOCKWISE)
img_flipped=cv2.rotate(fix_img,cv2.ROTATE_180)
In [20]:
plt.figure(figsize=(8,8))

plt.subplot(121)
plt.title('Rotated')
plt.imshow(img_rotated)

plt.subplot(122)
plt.title('Flipped')
plt.imshow(img_flipped)
Out[20]:
<matplotlib.image.AxesImage at 0x2e9df394208>


📌 Crop

image.png

  • 데이터 셋의 학습하고 싶은 부분만 자르기
In [21]:
import numpy as np
import cv2
import matplotlib.pyplot as plt
In [22]:
img=cv2.imread('./data/Angkko.png',-1)
# plt으로 그리기 위해서
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
In [23]:
y_start=60
crop_y_size=80
x_start=50
crop_x_size=80
img_cropped=img[y_start:y_start+crop_y_size,x_start:x_start+crop_x_size,:]
In [24]:
plt.figure(figsize=(8,8))

plt.subplot(121)
plt.xticks([])
plt.yticks([])
plt.title('Origin')
plt.imshow(img)

plt.subplot(122)
plt.title('Cropped')
plt.imshow(img_cropped)
Out[24]:
<matplotlib.image.AxesImage at 0x2e9df454dc8>


📌 Affine transformation

image.png

In [25]:
import numpy as np
import cv2
import matplotlib.pyplot as plt
In [26]:
img=cv2.imread('./data/Angkko.png',-1)
# plt으로 그리기 위해서
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

rows,cols,ch=img.shape
# 각각의 대응쌍을 지정해 준다.
pts1=np.float32([[50,200],[50,50],[150,200]])
pts2=np.float32([[100,180],[50,50],[170,180]])
# 변환 행렬을 생성
M=cv2.getAffineTransform(pts1,pts2)
shear_img=cv2.warpAffine(img,M,(cols,rows))
In [27]:
plt.figure(figsize=(8,8))

plt.subplot(121)
plt.title('Origin')
plt.imshow(img)

plt.subplot(122)
plt.title('AffineTransform')
plt.imshow(shear_img)
Out[27]:
<matplotlib.image.AxesImage at 0x2e9df4fcc48>


📌 CutMix

image.png

  • 자르고 합치기를 통해서 새로운 데이터 셋을 만든다.
  • 이때, 결과의 label도 합쳐진 비율만큼 주게 된다.
  • 이렇게 하면 물체의 위치를 더 정교하게 캐치하게 된다.



✅ Leveraging pre-trained information

1️⃣ Transfer learning

  • Transfer learning의 이점은 사전 훈련 된 지식 (기능)을 활용하여 새로운 작업에 쉽게 적응하게 할 수 있다.
  • 비슷한 데이터 셋은 비슷한 공통의 정보를 가지고 있다라는 생각
  • 하나의 데이터 셋에서 배운 지식을 다른 데이터 셋에 적용 할 수 있다.

📌 접근 1: 사전 훈련 된 작업에서 새 작업으로 지식 이전

image.png

  • 기존의 10개의 class로 분류하는 pre-trained model이 있다.
  • 사전 훈련 된 모델의 최종 계층을 잘라 내고 새 FC layer을 추가하고 다시 학습을 진행
  • 추출 된 기능은 사전의 모든 지식을 보존


📌 접근 2: 전체 모델에 Fine-tuning을 한다.

image.png

  • pre-trained model을 준비한다.
  • 사전 훈련 된 모델의 최종 레이어를 새 레이어로 교체하고 전체 모델을 다시 학습한다.
  • 학습률을 다르게 설정하게 되는데 Convolution Layer는 낮은 learning rate을 주고 새 FC layer는 높은 learning rate를 준다.
  • 조금 더 많은 데이터가 들어가고 성능도 더 좋다.



2️⃣ Knowledge distillation

  • 훈련 된 모델의 지식을 다른 작은 모델로 'Distillate' 한다.
  • 모델 압축에 사용(더 큰 모델이 알고있는 것을 모방)
  • pseudo-labeling에 사용된다. (라벨이없는 데이터 세트에 대한 유사 라벨 생성).

image.png


📌 Teacher-student Network 구조

image.png

  • Student network는 Teacher network가 알고 있는 내용을 배우게 된다.
  • 이때 Student model는 일반적으로 더 작은 network를 쓴다.
  • Student model과 Teacher model의 Output을 KL div. Loss를 통해 측정하고 backporb을 통해 Student model만 학습하게 된다.
  • Student model는 Teacher model의 출력을 모방하게 된다.
  • 레이블이 없는 데이터로만 수행 할 수 있으므로 비지도 학습


📌 Knowledge distillation

image.png

  • 레이블이 지정된 데이터(Ground Truth Y)를 사용할 수 있는 경우 학습을 위해 레이블이 지정된 데이터를 활용할 수 있다. (Student Loss)
  • Teacher model과 유사한 결과를 예측 하기위한 Distillation Loss
  • distillation에서 Semantic information은 고려하지 않는다.
  • 여기서 예측은 Soft Prediction을 사용한다.

🔎 Hard label vs Soft label

image.png

Hard label(One-hot vector)

  • 일반적으로 데이터 셋에서 가져온다.
  • class가 정답인지 여부를 나타낸다.

Soft label

  • 모델의 일반적인 출력 (= 추론 결과)
  • "지식"으로 간주한다. 모델이 어떻게 생각하는지 관찰하는데 유용하다.


📌 Softmax with temperature(T)

image.png

image.png

  • temperature가 있는 Softmax : 작은 입력과 큰 입력 값 사이의 출력 차이 제어
  • 큰 𝑇값은 큰 입력 값 차이를 부드럽게한다.
  • Student & Teacher model의 출력을 동기화하는 데 유용하다.



image.png

Distillation Loss

  • kLdiv(Soft label, Soft prediction)
  • Loss는 Teacher와 Student Network의 추론의 차이를 의미
  • 모방하여 Teacher의 Network가 아는 것을 배움

Student Loss

  • CrossEntropy(Hard label, Soft prediction)
  • Loss는 Student network와 실제 레이블의 차이
  • "정답" 배우기

Distillation lossStudent loss의 가중합을 사용한다.



✅ Leveraging unlabeled dataset for training

1️⃣ Semi-supervised learning

image.png

  1. label이 있는 데이터를 통해 Model을 학습한다.
  2. 그 다음 이 Model을 가지고 Unlabeled dataset에 대해서 Pseudo-labeled dataset을 만든다.
  3. 새롭게 지정된 Pseudo-labeled dataset을 추가하여 그 전의 Model을 다시 학습 시킨다.


2️⃣ Self-training

image.png

  1. 먼저 수집한 데이터 셋을 가지고 Teacher Model을 학습 시킨다.
  2. Teacher Model을 통해서 unlabeled data에 Pseudo-labeled data로 만든다.
  3. 이제 기본 데이터와 Pseudo-labeled data를 합쳐서 Student Model을 학습시킨다. 이때 학습할 때 , RandAugment를 이용하여 더 방대한 데이터를 학습한다.
  4. Studen Model의 학습이 끝나면 이전 Teacher Model를 날리고 최근에 학습한 Student Model를 다시 Teacher Model로 사용한다.
  5. 이렇게 새로 만들어진 Teacher Model로 다시 unlabeld data를 pseudo-labeled data로 만들고 반복한다.



image.png

  • 위 그림은 위에서 설명한 내용을 그림으로 보여준다.
  • 여기서 Model은 점점 더 커지게 된다.

'AI > 이론' 카테고리의 다른 글

torch.autograd  (0) 2021.03.10
Object Detection  (0) 2021.03.10
Semantic segmentation  (0) 2021.03.09
Image classification II  (0) 2021.03.09
Image classification I  (0) 2021.03.08
그래프 신경망이란 무엇일까? (심화)  (0) 2021.02.26
그래프 신경망이란 무엇일까? (기본)  (1) 2021.02.26
그래프를 추천시스템에 어떠게 활용할까? (심화)  (0) 2021.02.25

+ Recent posts