COCO Dataset
-일반적으로 객체 구분과 검출에 자주 사용되는 데이터 셋
-이미지에 대한 box, segment 위치를 포함한다.
-Info 에는 데이터셋에 대한 high-level의 정보가 포함된다.
-licenses 에는 이미지의 라이센스 목록이 포함된다.
-images 에는 데이터 셋의 전체 이미지 목록 및 각각의 width, height, 파일명을 포함한다.
-categories 에는 class에 해당하는 id, name 및 supercategory가 포함된다.
-annotations 에는 해당 이미지의 자세한 라벨 정보들이 포함된다.
mAP (mean average precision)
-AP (Average Precision)은 x를 recall, y를 predicsion으로 둔 그래프의 면적의 넓이이다.
-mAP는 AP의 평균.
mIOU
-합집합 대비 교집합 (Segmentation에서 사용)
-타겟과 예측의 합집합에 교집합을 나누고 이를 평균을 낸 지표
세그멘테이션
-Semantic의 경우 같은 종류의 객체는 하나로 취급하고, Instance Segmantation의 경우 같은 종류라도 다른 객체이면
다른 클래스로 취급한다.
-Segmentation은 객체 탐지 및 이미지 분할 등에 사용되어, 자율주행이나 의료 분야에서 자주 활용된다.
FCN(Fully Convolution Networks)
-VGG 네트워크를 백본으로 사용하되, VGG 네트워크의 FC 레이어 3개를 Convolution으로 대체했다.
-Transposed Convolution을 활용해 Pixel Wise Prediction을 수행했다.
Fully Connected Layer vs Convolution Layer
-FC 레이어의 경우 Flatten을 수행해야 한다.
-이러한 방식은 위치가 아닌 특징만 추출하는 task에서는 잘 작동하는 방식이었다.
-하지만 Segmentation 분야에서는 각 픽셀이 어느 class에 속하는지를 분류해야 했고, 이로 인해 FC 레이어를
Convolution으로 대체했다.
-또한 Filly Convolution Layer 사용 시 input 이미지의 사이즈에 관계 없이 파라미터의 수정이 필요가 없어진다.
-즉, 어느 이미지든 resize 없이 바로 입력이 가능한데, 이는 이전 채널의 데이터의 파라미터 수를 반드시 입력해야 하는
Linear 레이어가 없어졌기 때문.
-그에 반해 Convolution 레이어는 커널의 파라미터에 영향을 받지만, 이미지 혹은 레이어의 크기에는 전혀 영향을
받지 않는다.
Transposed Convolution
-기존 CNN은 컨볼루션과 풀링 과정을 거치며 이미지의 사이즈가 점점 줄어드는데, 이를 다운 샘플링이라 부른다.
-하지만 Object Detection이나 Segmentation을 위해 이미지 사이즈를 다시 늘려야 하는데, 이를 업샘플링이라 부른다.
-FCN에서는 업샘플링을 위해 Transposed Convolution을 활용한다.
-Transposed Convolution도 학습을 통해 좋은 weight의 kernel의 파라미터를 찾아가며 이미지를 복원한다.
-즉, Convolution에서 사용한 커널과 똑같은 커널을 사용하는 것이 아니라, 또다른 학습 가능한 커널을 활용하여
복원한다. (같은 커널 사용시 다른 값으로 복원됨)
-이러한 이미지 복원 작업을 Upsampling, Deconvolution, Tranposed Convolution이라고 한다.
-엄밀히 말해서는 Transposed Convolution이 가장 제대로 된 의미.
-Deconvolution이 가장 제대로 된 의미가 아닌 이유는 같은 커널을 사용하여 다운샘플링, 업샘플링을 하는 것이
아니기 때문.
FCN의 상세한 구조
-VGG를 사용했기에 5개의 Conv 블록을 사용한다.
-커널 수(채널 수)는 64 - 128 - 256 - 512 - 512 이다.
-FC6, 7는 CBR을 사용하여 4096개의 특징으로 바꾸고, Dropout을 적용한다.
-Score에서는 1*1 conv를 활용해 스코어맵을 만들면서, num_class만큼의 채널을 세팅함으로써 채널 단위로
분류를 수행한다.
-그리고 이를 UpSampling 하여 이미지를 복원한다.
def CBR(in_channels, out_channels, kernel_size = 3, stride = 1, padding=1) :
return nn.Sequential(nn.Conv2d( in_channels = in_channels,
out_channels = out_channels,
kernel_size = kernel_size,
stride = stride,
padding = padding),
nn.ReLU(inplace = True)
)
#conv1
self.conv1_1 = CBR(3, 64, 3, 1, 1)
self.conv1_2 = CBR(64, 64, 3, 1, 1)
self.pool1 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv2
self.conv2_1 = CBR(64, 128, 3, 1, 1)
self.conv2_2 = CBR(128, 128, 3, 1, 1)
self.pool2 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv3
self.conv3_1 = CBR(128, 256, 3, 1, 1)
self.conv3_2 = CBR(256, 256, 3, 1, 1)
self.conv3_2 = CBR(256, 256, 3, 1, 1)
self.pool3 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv4
self.conv4_1 = CBR(256, 512, 3, 1, 1)
self.conv4_2 = CBR(512, 512, 3, 1, 1)
self.conv4_2 = CBR(512, 512, 3, 1, 1)
self.pool4 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv5
self.conv5_1 = CBR(512, 512, 3, 1, 1)
self.conv5_2 = CBR(512, 512, 3, 1, 1)
self.conv5_2 = CBR(512, 512, 3, 1, 1)
self.pool5 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#FC6
slef.fc6 = CBR(512, 4096, 1, 1, 0)
slef.drop6 = nn.Dropout2d()
#FC7
slef.fc7 = CBR(4096, 4096, 1, 1, 0)
slef.drop7 = nn.Dropout2d()
#Score
self.score_fr = nn.Conv2d(4096, num_classes, 1, 1, 0)
#UPScore using deconv
self.upscore32 = nn.ConvTransposed2d(num_classes, num_classes, kernel_size = 64, stride = 32, padding = 16)
FCN의 성능 향상
1) FCN-16s
-기존의 CNN의 과정을 거치며 FCN은 디테일한 위치 정보를 소실하게 된다.
-그저 대략적인 정보만을 유추하고, 확실한 경계를 볼 수는 없다.
-이를 방지하기 위해 Stride 사이즈를 줄이며 이전의 Output Featuremap을 불러오는 Skip-connection을 활용한다.
-이전의 알고리즘은 하나의 Deconv를 사용해 32배로 키웠다면, 진화한 알고리즘은 하나의 Deconv로 2배로 키우고,
풀링 이전의 특징맵을 가져와 결합하여 16배로 키우는 Deconv2 레이어가 있다.
-이러한 방식은 풀링에 의해 잃어버린 정보를 복원해주는 작업을 진행한다.
-또 Upsampled Size를 줄여주기에 (한 번에 32배로 키우는 게 아니라 보다 천천히 복원하기에) 좀 더 효율적인
이미지 복원이 가능하다.
def CBR(in_channels, out_channels, kernel_size = 3, stride = 1, padding=1) :
return nn.Sequential(nn.Conv2d( in_channels = in_channels,
out_channels = out_channels,
kernel_size = kernel_size,
stride = stride,
padding = padding),
nn.ReLU(inplace = True)
)
#conv1
self.conv1_1 = CBR(3, 64, 3, 1, 1)
self.conv1_2 = CBR(64, 64, 3, 1, 1)
self.pool1 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv2
self.conv2_1 = CBR(64, 128, 3, 1, 1)
self.conv2_2 = CBR(128, 128, 3, 1, 1)
self.pool2 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv3
self.conv3_1 = CBR(128, 256, 3, 1, 1)
self.conv3_2 = CBR(256, 256, 3, 1, 1)
self.conv3_2 = CBR(256, 256, 3, 1, 1)
self.pool3 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#conv4
self.conv4_1 = CBR(256, 512, 3, 1, 1)
self.conv4_2 = CBR(512, 512, 3, 1, 1)
self.conv4_2 = CBR(512, 512, 3, 1, 1)
self.pool4 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#Score pool4 /변경
self.score_pool4_fr = nn.Conv2d(512, num_classes, kernel_size = 1, stride = 1, padding = 0)
#conv5
self.conv5_1 = CBR(512, 512, 3, 1, 1)
self.conv5_2 = CBR(512, 512, 3, 1, 1)
self.conv5_2 = CBR(512, 512, 3, 1, 1)
self.pool5 = nn.MaxPool2d(2, stride = 2, cell_mode = True) #1/2
#FC6
slef.fc6 = CBR(512, 4096, 1, 1, 0)
slef.drop6 = nn.Dropout2d()
#FC7
slef.fc7 = CBR(4096, 4096, 1, 1, 0)
slef.drop7 = nn.Dropout2d()
#Score
self.score_fr = nn.Conv2d(4096, num_classes, 1, 1, 0)
#UPScore using deconv /변경
self.upscore2 = nn.ConvTransposed2d(num_classes, num_classes, kernel_size = 4, stride = 2, padding = 1)
#이제 forward에서
#h = upscore2의 결과값 + score_pool4_fr의 결과값을 한 후
self.upscore16 = nn.ConvTransposed2d(num_classes, num_classes, kernel_size = 32, stride = 16, padding = 8)
2) FCN-8s
-풀링 4의 결과 뿐 아니라 풀링 3의 결과도 가져와 컨볼루션한다.
FCN의 한계점
-객체의 크기가 크거나 작은 경우 예측을 잘 수행하지 못했다.
-큰 객체의 경우 지역적인 정보만으로 예측하는데, 버스의 유리창에 비친 자전거를 보고
버스를 자전거로 인식하기도 함. 이로 인해 큰 객체의 경우 같은 객체여도 다른 라벨링이 일어날 수 있음.
-반대로 객체의 크기가 작으면 무시하는 경우도 있음.
-Deconvolution의 절차가 너무 간단하여 객체의 디테일한 모습이 사라지는 문제도 있음.
Decoder를 개선한 모델
-FCN의 문제를 개선하기 위해 인코더-디코더 구조로 바꾸어 연구를 진행
1) DeconvNet
-디코더를 인코더와 대칭으로 만들었다.
-컨볼루션 네트워크는 VGG16을 만들었다.
-디컨볼루션 네트워크는 업샘플링, 디컨볼루션, ReLU로 이루어져있다.
-Unpooling은 아래와 같이 풀링한 결과를 복원하는 과정
-풀링은 노이즈를 제거하지만 그 과정에서 정보가 손실된다.
-언풀링을 통해 풀링 시 지워진 경계에 정보를 기록했다가 복원.
-학습이 필요없기에 속도가 빠르나, sparse한 activation map이 생성되기에 이를 채워줘야 하고, 이를 위해 Transposed
Convolution을 수행해야 한다.
-Deconvolution Network의 Activation map을 보면 층과 풀링 방법에 따른 특징이 있다. 낮은 층은 전반적인 특징,
깊은 층은 복잡한 패턴을 잡아낸다.
-그래서 Unpooling의 경우 example-specific한 구조, 즉 자세한 구조를 잡아낸다.
-그리고 Transposed Conv의 경우 "class-specific"한 구조를 잡아낸다. 즉, 빈 부분을 채워넣는다.
-둘을 병행할 경우 활성화 맵이 더 디테일해진다.
2) SegNet
-Road Scene Understanding applications라는 분야에서 Semantic Segmentation을 수행하기 위해 모델이 필요한
능력에 대한 고민
-자율 주행에 있어 중요한 것은 클래스들을 빠르고 정확하게 분류하는 작업이었다.
-VGG16의 13개 층을 인코더로 사용하고, 뒤집어서 디코더로 사용했다.
-FC 레이어를 모두 제거했고, 디코더 파트에서 Convolution을 사용했다.
-인코더는 Pretrained된 네트워크 사용.
Skip Connection을 적용한 모델
-Skip Connection은 ResNet에서 나온 개념으로, input과 output을 연결하여 더하는 테크닉.
-이전 레이어의 output을 입력으로 제공함으로써 깊은 레이어에서 성능을 좋게 만들어줌.
-DenseNet은 같은 DenseBlock 내에서 이전의 모든 레이어의 output을 가져온다.
1) FC DenseNet
-FC DenseNet은 이러한 DenseNet의 Skip Connection을 빌려왔다.
-Block 내부에서는 DenseNet의 Skip Connection을 수행하고, Block 사이에서는 ResNet의 Skip Connection을 수행한다.
2) Unet
-가장 큰 특징은 인코더를 통과하는 특징맵의 결과를 같은 레벨 층의 디코더의 output과 concat (총 4회)
Receptive Field를 확장시킨 모델
-Receptive Field란 뉴런이 얼마만큼을 바라보고 있는지, 즉 얼마만큼의 영역을 바라보고 있는지를 의미한다.
-Receptive Field가 객체에 대한 정보를 다 포함하지 못하면 예측 정확도가 낮아질 수 있다.
-즉, Receptive Field는 객체의 일부가 아닌 전체를 보고있어야 한다. (위의 경우 B < C)
-Conv → Max pooling → Conv 반복하면, 효율적으로 receptive field를 넓힐 수 있음
-그러나, Resolution 측면에서는 low feature resolution 을 가지는 문제점 발생
-그래서 이미지의 크기 자체를 너무 줄이지 않고, 파라미터의 수도 변함이 없는 채로 Receptive Field만 넓게 하는 방식이
필요해짐.
1) DeepLab V1
-위의 테크닉이 바로 Dialated Convolution이다.
-이미지의 크기를 적게 줄이면서도 효율적인 receptive field를 넓히는 방법.
-Dilated Convolution & downsampling 시 파라미터를 줄이며 Receptive Field를 넓힐 수 있다.
-커널이 적용되는 넓이를 넓히며, 나머지에는 0을 채운다.
-이러한 개념을 처음으로 도입한 것이 DeepLab V1
-2*2가 아닌 3*3 Max풀링 사용, 마지막 풀링은 평균풀링 사용.
-마지막 UpSampling은 Bilinear Upsampling인데, 이웃 좌표들의 값을 각 좌표에서 거리를 기반으로 채워넣는 방법
2) DialatedNet
-DeepLab v1과 비슷한 구조이나 보다 Dialated Convolution을 효율적으로 사용하는 방식.
-DialatedNet은 2*2 맥스 풀링 사용, 두 개의 맥스풀링(평균풀링) 제외로 맥스풀링으로 인한 정보 손실 방지.
그리고 rate을 4로 주고, Deconv 사용
3) DeepLab v2
-DeepLab v1의 앞부분은 동일하나 FC 레이어를 변경함.
-브랜치를 뻗어 네 갈래로 만들었는데, 이를 ASPP라고 명명함.
-이렇게 네 개의 각자 다른 dilate rate를 다르게 주어 1*1 conv를 거친 후 합쳐 BiLinear Interpolation 수행
4) PSPNet
-Receptive Field를 넓히는 데 이전과 다른 방법 사용
-도입 배경은
1) Mismatched Relationship : 모델이 외관만 보고 물체를 판단
2) Confusion Categories : 비슷한 카테고리를 헷갈려함
3) Inconspicuous Classes : 크기가 작아 잘 보이지 않는 객체를 헷갈려함
-이러한 문제점들은 주변의 특징들을 동시에 파악하면 충분히 제대로 된 예측이 가능해진다.
-또 다른 도입 배경은 왜 FCN은 MaxPool에 의해 줄였는데 Receptive Field가 넓혀지지 않을까?
-이러한 점은 2014년에 나온 논문에서 파악할 수 있는데, 이론적인 Receptive Field와 실제는 다르기 때문.
-PSPNet은 이러한 문제를 해결하기 위해 Dialated Conv가 아닌 Global Average Pooling을 도입했다.
-Global Average Pooling은 주변 정보를 토대로 객체를 인식할 때 활용되는 방식이다.
5) DeepLab v3
-Global Average Pooling을 사용한 버전
-ASPP 부분에서 Global Average Pooling이 추가되었다.
U-Net
-바이오, 의료 쪽에 포커싱이 맞춰진 모델이나, 성능이 좋아 여러 Segmentation 분야에서 사용되었다.
-의료 쪽의 데이터의 문제점은, 데이터의 수가 부족한 것이다. 라벨링을 일반인이 하는 것이 불가능하기 때문.
-또한 데이터들에 개인 정보가 포함되어 있어 데이터 수가 부족할 수 밖에 없다.
-두 번째 문제는 데이터의 인스턴스의 경계를 테두리로 만들어야하는 작업이 필요했다.
-U-Net은 U자 형태의 네트워크를 구성하고 있다.
-왼쪽의 인코더는 Contracting Path라 부르며, 입력 이미지의 전반적인 특징을 추출하며 다운샘플링 한다.
-오른쪽의 디코더는 Expanding Path라고 하며, 업샘플링을 수행하여 Segmentation을 수행한다.
-제로 패딩을 사용하지 않아 특징맵의 크기가 계속해서 감소한다.
-채널이 인코더에서는 두 배씩 감소, 디코더에서는 두 배씩 증가하며, 같은 레벨의 인코더 층의 출력을
디코더에서 Concat 하는 Skip connection을 활용함으로써 이전 레이어의 정보를 효과적으로 활용.
-인코더에서는 3*3 conv + BN + ReLU 작업을 두 번 수행 => 2*2 맥스풀링 (절반 감소)
-디코더에서는 2*2 업컨벌루션 => Concat => 3*3 conv + BN + ReLU 두 번 수행
-마지막에는 1*1 conv로 output channels 수 설정
-유넷은 인코더가 확장함에 따라 채널의 수를 1024까지 증가시켜 좀 더 고차원에서 정보를 매핑한다.
-각기 다른 계층의 인코더의 출력을 디코더와 결합시켜 이전 레이어의 정보를 효율적으로 활용한다.
U-Net의 테크닉
1) Data Augmentation
-데이터 부족 현상을 해결
1-1) Random Elastic Deformations를 통해 증강 수행
-RED는 데이터에 외부적인 압력을 가하여 변형시키는 방법.
-바이오, 의료에서는 같은 종류의 세포라도 사람에 따라 다를 수 있음. 그렇기에 세포의 모양에 관계 없이
같은 세포임을 파악할 수 있도록 하기 위해 사용했다.
-용어로 설명하면 모델이 invariance와 robustness를 학습할 수 있도록 하는 방법
1-2) Sliding Window
-윈도우가 이미지를 훑으며 이미지의 부분을 사용.
-쉽게 하나의 이미지를 여러 이미지로 늘릴 수 있으나, 몇몇 이미지에는 배경만 존재하고, 전체가 아닌 부분적인
정보만 가지고 모델을 학습할 수 있고, 특정 이미지에서 이전의 이미지와 겹치는 영역이 존재한다는 문제가 있다.
-유넷에서는 이미지가 겹치지 않도록 slice 수행.
2) Weight map
-두 번째 단점인 데이터의 인스턴스의 경계를 구분하기 위한 테크닉
-즉 인접 셀을 구분하기 위한 테크닉
-Pixel-wise loss weight을 계산하기 위한 Weight map 생성
U-Net의 한계
-기본적으로 깊이가 4로 고정되는데, 데이터셋마다 최고의 성능을 보장하지 못한다.
-Skip Connection이 너무 단순하다.
-이러한 한계 극복을 위해 U-Net++가 등장했다.
U-Net++
-U-Net의 한계 극복을 위해 새로운 형태의 구조를 제시했다.
-인코더를 공유하는 다양한 깊이(1~4)의 U-Net을 생성하고, Skip Connection을 동일한 깊이에서의 특징맵이
모두 결합되도록 유연한 특징맵을 생성했다.
-U-Net의 최종 결과는 depth 1~4를 모두 앙상블하는 효과가 있다.
-또한 Loss를 Pixel wise Cross Entropy와 Soft Dice Coefficient를 앙상블한 로스를 사용한다.
-이러한 Loss를 X(0,1)에 1*1 conv를 한 후 softmax를 통해 probablity를 계산하고, x(0,2)에서도 계산하는 식으로
이어나간다. 그리고 이 Loss들을 평균을 내서 사용하는데, 이를 Deep Supervision 이라고 부른다.
-U-Net++의 한계는 너무 복잡한 커넥션으로 파라미터가 증가하고, 메모리가 증가했다는 점이다.
또한 인코더-디코더 사이에서 Connection이 동일한 크기를 갖는 특징맵에서만 진행되어
Full Scale에서 충분한 정보를 탐색하지 못해 위치와 경계를 명시적으로 학습하지 못한다.
-이러한 단점 극복을 위해 U-Net3+가 등장했다.
U-Net 3+
-디코더에서 특징맵을 결합하는 방법을 조금 복잡하게 변경했다.
-인코더 레이어로부터 같은 스케일의 인코더 레이어로부터 직접 특징맵을 받고,
더 작은 스케일의 low-level 특징맵도 받아 풍부한 공간 정보를 통해 경계를 강조한다.
더 큰 스케일의 high-level 특징맵도 받아 위치 정보를 구현한다.
-이를 Full-scale Skip Connection이라고 한다.
U-Net 3+의 Techniques
1) Classification-guided Module (CGM)
-낮은 레벨의 레이어에 있는 배경의 노이즈가 발생하여 false-positive 문제가 발생
-그래서 정확도 향상을 위해 extra classificaion task 수행
-높은 레벨의 특징맵을 사용.
-Dropout => 1*1 conv => AdaptiveMaxPool => Sigmoid 를 통과한 결과에
argmax를 통해 Organ이 있으면 1, 없으면 0을 출력하여 나온 결과와 각 low-layer마다 나온 결과를 곱셈.
-즉 출력값을 디코더의 값에 곱해줌으로써 loss term 계산
2) Full-scale Deep Supervision (Loss Function)
-순서대로 Focal Loss : 클래스의 불균형 해소
-ms-simm Loss : 경계 인식 강화
-IoU : 픽셀의 분류 정확도 상승
U-Net의 버전들
1) Residual U-Net
-Encoder 및 Decoder 부분의 block마다 residual unit with identity mapping 적용
2) Mobile-U-Net
-어플리케이션의 속도 강화를 위한 MobileNet을 백본으로 사용.
3) Eff-U-Net
-EfficientNet을 백본으로 사용.
DataLoader
-dataset : 로드할 데이터셋
-batch_size : 배치 사이즈
-shuffle : 모든 Epoch의 데이터를 섞을 지
-num_workers : 로드에 사용할 프로세스 수 => 0은 기본 프로세스 => 윈도우는 0, 리눅스는 크게 맞추는 게 좋음
-collate_fn : sample의 list를 merge하여 텐서의 minibatch 구성
Segmeantation_models_pytorch
-다양한 segmentation 모델 불러오기가 가능하고, 백본 교체도 쉬움
-smp.readthedocs.io/en/latest/index.html
Validation
Validation이 중요한 이유
1) 제출을 하지 않더라도 모델의 성능을 평가할 수 있다.
2) Public 리더보드의 성능에 오버피팅 되지 않도록 돕는다.
Hold Out
-고정된 비율로 데이터 셋을 Train-Valid로 나누는 방법.
-빠른 속도로 모델이 검증하다는 장점이 있으나, 20%의 데이터를 사용할 수가 없다.
K-Fold
-기본적으로 고정된 비율로 데이터 셋을 나누는 방법은 홀드 아웃과 같으나, 모든 데이터를 학습에 활용할
수 있다.
-K가 5라면 다섯 개의 모델을 만들고, 이 모델들을 앙상블하여 최종 결과를 출력한다.
-장점으로는 모든 데이터 셋을 학습에 참여시킬 수 있고, 전체 데이터셋에 대해 검증을 진행하여
신뢰성 있는 검증 결과를 만들 수 있다.
-또한 앙상블 효과로 인해 대부분의 경우 모델의 성능이 향상된다.
-하지만 홀드아웃 방식에 비해 K배의 시간이 소요되고, k의 선택에 대한 문제도 존재한다.
K의 선택에 따라 성능과 시간이 달라질 수 있기 때문.
-또한 데이터셋이 나누어지는 것이 랜덤성에 의존하기 때문에 편향된 데이터 셋으로 학습이 진행될 수 있다.
Stratified K-Fold
-Class 분포를 고려하지 못하는 k-fold 방식을 개선한 방법.
-폴드마다 클래스 분포를 동일하게 하여 split 하는 방식으로, 클래스가 불균형한 상황에 좋다.
Group K-Fold
-아예 특정 클래스만 검증 셋으로 만들어버리는 방법.
Augmentation
-데이터 수의 증가, 일반화 성능 강화, 성능 향상, 클래스 분균형 해소 등을 위해 사용된다.
-Torchvision.transforms에 다양한 Augmentation이 있고,
Albumentation에서도 가능한데, Albumentation에는 분류, 객체 검출, 시멘틱 세그멘테이션 등 다양한
분야에 적용이 가능하다. 또한 다양한 라이브러리를 기반으로 최적화 하여 속도가 빠르다.
Kaggle에서 자주 사용되는 Augmentation
1) Cutout
-Cutout의 경우 렌덤하게 박스를 생성하기에 사진마다 성능의 편차가 존재한다.
-즉, 객체를 전부 가려버릴 수도 있고, 배경만 가려 성능에 별로 도움이 되지 않을 수 있다.
-이러한 문제의 해결을 위해 Gridmask 기법이 등장했다.
2) Gridmask
-규칙성 있는 박스를 통해 Cutout하는 방안을 제시했다.
3) Cutmix
-여러 가지 이미지를 합성시킨 것.
-굳이 밑에 처럼 구현할 필요는 없고,
from cutmix.cutmix import CutMix
from cutmix.utils import CutMixCrossEntropyLoss
를 불러와 사용해도 좋음.
def rand_bbox(size, lam) :
# 1. 랜덤하게 잘릴 박스 추출
H = size[2]
W = size[3]
cut_rat = np.sqrt(1, -lam)
cut_w = np.int(W * cut_rat)
cut_h = np.int(H * cut_rat)
# 2. 박스의 위치 결정
cx = np.random.randint(W)
cy = np.random.randint(H)
bbx1 = np.clip(cx - cut_w // 2, 0, W)
bby1 = np.clip(cy - cut_h // 2, 0, H)
bbx2 = np.clip(cx + cut_w // 2, 0, W)
bby2 = np.clip(cy + cut_h // 2, 0, H)
return bbx1, bby1, bbx2, bby2
# 3. Input 이미지들의 순서를 섞고 박스의 크기를 결정할 람다 추출
lam = np.random.bera(beta, beta)
rand_index = torch.randperm(input.size()[0]).cuda()
target_a = target
target_b = target[rand_index]
bbx1, bby1, bbx2, bby2 = rand_bbox(input.size(), lam)
input[:, :, bbx1:bbx2, bby1:bby2] = input[rand_index, : , bbx1:bbx2, bby1:bby2]
lab = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (input.size()[-1] * input.size()[-2]))
output = model(input)
loss = criterion(output, target_a) * lam + criterion(output, target_b)
4) SnapMix
-CAM(Class Activation Map)을 이용해 이미지 및 라벨을 합치는 방법
-영역 크기만을 고려해 라벨을 생성했던 cutmix와 달리 영역의 의미적 중요도를 고려해 라벨을 생성한다.
HRModel
LR_Scheduler
-lr이 고정되었을 때, lr이 너무 작으면 학습 시간이 오래 걸리고 Local Optima에 빠질 위험이 있다.
-하지만 너무 크다면 loss가 발산할 수 있다.
-그렇기 때문에 lr을 확정하지 못한 상황에서는, 하나의 lr을 사용하는 것보다 좀 다양하게 사용할 필요가 있다.
-다양하게 사용하면 빠른 속도로 수렴이 가능하고, 높은 정확도를 가지게 된다.
1) CosineAnnealingLR
-lr의 최대값과 최소값을 정해 그 범위의 학습률을 코사인 함수의 형태로 스케줄링하는 방법.
-lr이 급격하게 증가되었다 감소되기 때문에 saddle point, 정체 구간을 빠르게 탈출할 수 있다.
2) ReduceLROnPlateau
-metric의 성능이 향상되지 않을 때 learning rate를 조절하는 방법.
-local minima에 빠졌을 때 lr을 조절하여 효과적으로 빠져나올 수 있다.
3) Gradual Warmup
-학습을 시작할 때 마우 작은 lr로 출발해서 특정 값에 도달할 때까지 lr을 서서히 증가시킨다.
-이 방식을 사용하면 weight이 불안정한 초반에도 비교적 안정적으로 학습 수행이 가능하다.
-백본 네트워크 사용 시 weight가 망가지는 것을 방지할 수 있다.
Batch_size
-배치 사이즈가 크면 더 빠른 학습이 가능하고, 다양한 데이터를 한 번에 학습할 수 있어
일반화 성능이 좋아진다.
1) Gradient Accumulation
-모델의 weight를 배치마다 업데이트하지 않고, 일정 step만큼 gradient를 누적한 다음 누적된 gradient를
사용해 weight를 업데이트
-이 방법은 배치 사이즈를 키울 수 있는 장점이 있다.
2) Mixed-Precision Training of Deep Neural Networks
-웨이트의 소수점 자리를 32에서 16으로 대체하여 배치를 키우는 방법
Optimizer
-보통 Adam을 많이 사용하지만 조금이라도 성능 향상을 위해서라면 보다 최신 최적화기를 사용하는 것이 좋음.
-AdamW, AdamP, Radam 등
1) Lookahead optimizer
-Adam이나 SGD를 통해 K 번 업데이트 후 처음 시작했던 방향으로 1 step back 후 그 지점에서 다시 k번 업데이트
-Adam이나 SGD로 빠져나오기 힘든 Local minima를 빠져나올 수 있다.
Ensemble
1) Epoch Ensemble : epoch마다 모델을 저장한 후 마지막부터 N개의 모델을 이용해 앙상블
2) SWA : 각 step마다 weight를 업데이트 시키는 SGD와 달리 일정 주기마다 weight를 평균내는 방법.
3) Seed Ensemble : 랜덤 요소를 결정하는 시드를 바꿔가며 여러 모델을 학습시킨 후 앙상블 하는 방법
4) Resize Ensemble : 입력 이미지의 크기를 다르게 학습해 앙상블하는 방법
출력 이미지에 대해서도 가능하다.
5) TTA (Test time augmentation) : 테스트 셋으로 성능 테스트 시 augmentation을 수행하는 방법.
Pseudo Labeling
-라벨이 없는 데이터에 라벨을 붙여 학습에 활용하는 방법
1) 모델을 학습시킨다.
2) 성능이 가장 좋은 모델에 대해 Test 데이터셋에 대한 예측을 진행한다.
*이 때 Softmax를 취한 확률값이나, Softmax 이전의 값, torch.max를 취하기 전의 값을 예측해야 한다.
*Test 데이터셋은 Model1의 예측값이 threshold(예 : 0.9) 인 것을 사용한다.
3) 2단계에서 예측한 test 데이터셋을 활용해 재학습 진행.
4) 3단계를 학습한 모델로 test 데이터셋을 예측
'BOOSTCAMP AI TECH > PStage' 카테고리의 다른 글
03-03. Object Detection (0) | 2021.05.10 |
---|---|
03-02. MRC (Machine Reading Comprehension, 기계독해) (0) | 2021.04.26 |
02-02. Tabular (0) | 2021.04.24 |
02-01. KLUE (0) | 2021.04.24 |
01. Computer Vision (0) | 2021.04.24 |