본문 바로가기
Project/Image Classification Pipeline Project

3. (2) Pytorch 데이터 클래스 정의 & albumentations 활용하기(이미지 수집부터 분류 모델까지)

by inhovation97 2021. 6. 18.

이 포스팅은 아래 흐름대로 진행되는 포스팅입니다.

데이터 수집 - 전처리 - 모델링 - 성능 개선 

 

이번 포스팅은 바로 전 포스팅과 똑같이 모델에 넣을 데이터를 준비하는 과정이지만, 다른 방법으로 진행합니다.

Pytorch 데이터 클래스를 직접 정의하여 커스터마이징합니다.

전처리 과정에서 albumentations 라이브러리를 사용해봅니다.

https://inhovation97.tistory.com/37 << 이전 포스팅 [3. (1) 이미지 전처리 - augmentation, normalization]을 읽고 오시는 것을 권장드립니다:)

 

포스팅 순서

<data pipeline을 설계하고, albumentations로 Image augmentation하기>
1. 데이터 클래스 정의하기

2. 이미지 resize하기
3. albumentations을 활용해 augmentation & normalization

티스토리 코드 가독성 때문에 먼저 코드 파일을 공유합니다. (주석도 잘 달아놓음)

코랩으로 열기를 권장합니다.

https://github.com/inhovation97/personal_project/blob/main/pytorch/pytorch_project_Image_preprocessing.ipynb

 

inhovation97/personal_project

개인 프로젝트. Contribute to inhovation97/personal_project development by creating an account on GitHub.

github.com

 

지금이야 연습이지만, 나중에는 별의별 데이터를 만날 수 있습니다.

매번 다른 데이터들을 마주해 클래스를 정의할 줄 알아야하기 때문에 이 글을 포스팅합니다.

 

 

<data pipeline을 설계하고, albumentations로 Image augmentation하기>

 

1. 데이터 클래스 정의하기

파이토치는 모델에 들어갈 데이터의 클래스와 loader를 정의해주어야합니다. 

loader는 클래스만 만들어주면 정의가 쉽지만, 직접 수집한 데이터들은 직접 data pipeline을 만들어주어야합니다.

 

길어보이지만 천천히 하면 됩니다.

먼저 from torch.utils.data import Dataset을 임포트해줍니다.

파이토치 dataset이 요구하는 것은 3가지입니다.

매 인덱스의 data, label & 전체 데이터의 길이(len)

 

pipeline은 크게 3가지로 구성돼있습니다. 3가지 특수 메서드들을 잘라서 천천히 설명하겠습니다.

먼저 __init__ 메서드를 봅시다.

 

 

 

인자를 넣어 클래스를 불러오면, 처음으로 반응하는 이 메서드는 클래스 내에서 인자들을 활용하기위해 존재합니다.데이터를 불러오고 최종 데이터를 내뱉는 과정에서 필요한 것들을 init이 생성해줍니다.

여기서 데이터의 경로와 불러올 데이터들에 augmentation을 적용하기위해 transform 인자를 만들어줍니다.

 

 

 

__getitem__메서드에서는 인덱스마다 1개의 데이터와 그 label을 return하는게 목적입니다.

그래서 data경로에 인덱스를 붙여주고, 이를 이미지를 읽어주는 함수인 cv2를 통해 이미지 데이터로 읽어줍니다.

RGB형태로 변환까지 진행합니다.

라벨도 각 데이터에 맞는 라벨을 부여해주고 data와 label을 return해 줍니다.

 

그리고 albumentations 라이브러리를 이용하기 위해서는 이미지를 cv2 라이브러리로 읽어야합니다.

albumentations은 tensor형태의 이미지를 변환해주기 때문에 PIL로 읽으면 변환이 안됩니다.

 

__len__메서드는 별거없습니다. 그냥 길이를 반환해줍니다.

 

 

 

돌고래 귀엽죠 ㅋㅋ

잘 정의해주었다면, 이렇게 클래스에서 이미지가 잘 나올겁니다!

 

 

 

 

 

2. 이미지 resize하기

이제 normalization을 위해 또 이미지를 resize해주고 tensor형태로 바꿔줍시다.

이전 포스팅 https://inhovation97.tistory.com/37에서 만들어두었던 함수로 train/test 각각의 채널별 mean과 std를 구해주었습니다.

대체 왜 이전 포스팅에서 구한 파이토치 transforms의 mean/std 값이 다른지 모르겠습니다 ㅋㅋㅋ 비슷하니 그냥 패쓰

resize 성공!

 

 

 

 

 

3. albumentations을 활용해 augmentation & normalization

albumetations는 이미지 데이터를 transform에 아주 유용한 라이브러리입니다.

torchvision에서 제공하는 transform보다 훨씬 더 빠르고 다양합니다.

특히 객체 탐지 모델에서 이미지 데이터에 그려져있는 b-box도 같이 transform해주기 때문에 albumentations에 익숙해지는 것을 좀 더 권장합니다.

 

이렇게 albumentations 라이브러리가 훨씬 더 다양한 data augmentation을 제공합니다. 특히 OneOf는 함수 안에 있는 것들 중 랜덤으로 진행해줍니다.

이렇게 data_loader까지 정의해서 끝나면 좋겠지만, 한가지 문제가 생겼습니다...

 

data augmentation은 normalize하려면 totensor로 (0~1) 범위로 스케일링한 뒤에 해주어야합니다.

근데 albumentations.Normalize 이 친구가 tensor형태의 데이터를 못알아먹습니다...

albumentations 공식 documentation 다 뒤졌는데, 해결할 수가 없었습니다.

깔끔하게 라이브러리 내부에 뭔가 다른 방법이 있을텐데 저는 사실 통계학과라 코딩 실력이...

 

결국 데이터셋 클래스에 인자를 추가해서 normalize는 trochvision라이브러리를 이용하려했는데, 그것도 쉽지 않더군요.

https://inhovation97.tistory.com/23
train 셋과 test 셋을 전 처리할 때에는 동일한 mean을 이용하여 zero-mean을 해준다고 합니다.
여기서 mean값을 이미지의 전체 데이터로 할지, 아니면 각각 독립된 채널마다의 mean으로 이용할지 선택할 수 있는데, 이는 큰 차이는 나지 않는다고 합니다.
 
VGGNet은 알렉스 넷보다 후에 나온 것인데, 각각의 채널별로 mean값을 두어 zero-mean을 했다고 합니다.

cs231n의 내용을 위안삼으면서 normalization은 건너뛰려합니다.

 

 

 

albumentations을 적용한 상어가 왼쪽처럼 바뀌었네요. (멸치아님...)

다음 포스팅은 모델링에 관한 포스팅입니다!

 

댓글