프로젝트 1 - 데이터
- 데이터 전처리
- 데이터셋과 데이터로더
바닐라 데이터를 모델에 적합한 형태의 데이터셋으로 가공하는 과정
캐글 등의 경진대회에서 주어지는 데이터는 대부분 이상이나 노이즈가 없는 아름다운 데이터다. 하지만 실제로 데이터를 수집한다면 이상한 값이 들어있거나 null값이 들어 있는 경우가 꽤 있다.
이상이 있는 데이터를 골라내거나 데이터가 모델에 잘 맞도록 가공하기 위해 전처리 과정을 거친다. 전처리가 마스터 키는 아니지만 task에 따라 적절한 전처리를 해 주면 성능을 끌어올리는 데 큰 도움이 되는 경우도 있다.
Bounding box
이미지가 필요 이상으로 많은 정보를 가지고 있을 때도 있다. 필요한 부분만 잘라서 학습에 사용한다면 원하는 정보에 집중할 수 있어서 더 나은 성능을 기대할 수 있을 것이다. 단, bounding box를 찾고 크롭하는 과정에는 알고리즘(과거의 방법) 또는 bounding box 탐색 모델이 필요하다.
Data augmentation
데이터를 일반화하기 위해서 사용하는 방법이다. 밝기를 조절하거나 회전시키거나 뒤집거나 기울이거나 노이즈를 주는 등 데이터가 가질 수 있는 상태를 다양하게 해서 데이터셋의 수를 늘리는 기법이다. 성능을 올리는 데 도움이 되는 방법이지만, 문제가 만들어진 배경과 모델의 쓰임새, 데이터가 가질 수 있는 상태를 잘 파악하고 사용해야 한다. EDA!!!
데이터에 따라서 하면 안 되는 변형도 있다! (MNIST 데이터 중 숫자 6과 9, 2와 5 등)torchvision.transforms
모듈 안에 augmentation에 사용할 수 있는 다양한 함수들이 있다. 외부 라이브러리인 Albumentations
를 쓰면 torchvision.transform
보다 더 빠르고 다양한 augmentation 기법을 적용할 수도 있다.
torch.utils.data
모듈의 Dataset
클래스를 상속받아 자신만의 커스텀 데이터셋 클래스를 만들 수 있다. Dataset
은 바닐라 데이터를 원하는 형태로 출력할 수 있는 클래스다.
class MyDataset(Dataset):
def __init__(self, img_paths, transform):
self.img_paths = img_paths
self.transform = transform
def __getitem__(self, index):
image = Image.open(self.img_paths[index])
if self.transform:
image = self.transform(image)
return image
def __len__(self):
return len(self.img_paths)
커스텀 데이터셋 클래스를 만들어 사용할 때 DataLoader
와 연계해서 사용하면 편하다. 데이터로더는 데이터셋을 잘 쓸 수 있게 해 주는 유틸리티로, torch.utils.data.DataLoader
에 포함되어 있다. 데이터로더를 쓰면 아주 편리하게 배치 사이즈만큼 데이터를 묶을 수 있는데, num_worker
옵션을 설정하면 스레드를 여러 개 사용할 수도 있다. drop_last
옵션을 통해 배치를 이루지 못하고 남은 데이터를 버릴지 말 지 설정할 수도 있다. 데이터로더는 여러 개의 Dataset
을 만들어 두고 각각에 다른 처리를 하고 싶은 경우에 특히 유용하다. 데이터로더에 들어갈 Dataset
을 바꿔 가면서 각각 처리하면 된다!
transform = transforms.Compose([
ToTensor(),
Normalize(mean=(0.5, 0.5, 0.5), std=(0.2, 0.2, 0.2)),
# 그 밖의 augmentation들
])
trainSet = MyDataset(imgPaths, transform) # 위에서 만든 MyDataset에서 imgPaths를 요구한다
trainLoader = DataLoader(trainSet, shuffle=False, num_workers=2, drop_last=True)
피어 세션 시간에 앞으로 프로젝트에 적용해 보면 좋을 것 같은 방법에 대한 이야기를 나눴다. 생각 못 해 봤던 아이디어도 있고 성능을 끌어올리기 좋을 것 같은 아이디어도 몇 개 떠올릴 수 있었다.
모든 데이터에 동일한 augmentation을 적용하지 말고 데이터를 몇 묶음으로 나눠서 묶음별로 다른 augmentation을 랜덤하게 적용하기
Albumentation 모듈은 정말 진짜 엄청 빠르다
데이터 중에서 이상한 것이 몇 가지 있음! 마스크를 눈에 쓴 사람이나 손수건을 두른 사람 등
얼굴 부분만 데이터를 크롭해서 사용한다면 어떨까? 얼굴이 영역 안에 다 안 들어오고 조금 잘려도 큰 문제 없을 것 같은데.
학습 데이터 안에서 클래스별 데이터 수가 굉장히 불균형한데, 검증셋을 구성할 때 클래스별 분포가 균등하게 만들어서 검증 정확도를 측정하면 더 정확한 측정이 가능할 것
학습 데이터 비율이 불균형하니까 수가 많은 마스크 정상 착용
데이터는 augmentation 하지 말고 부족한 데이터에만 적용해서 수를 불리면 어떨까?
한 번에 하나(성별만 구분, 마스크만 구분, 연령대만 구분)만 하는 모델 여러 개를 만들어서 앙상블하면 어떨까?
모델 만들고 나서 학습 데이터를 분류시켜 본 다음 모델이 생각한 레이블과 실제 레이블을 각각 scatter plot으로 나타내 본다면 모델이 어떤 것을 헷갈리는지 알 수 있을 것이다. 그러면 augmentation 등으로 그쪽 데이터를 더 만들어 주면 해결될지도!