본문 바로가기
TIL/Boostcamp AI tech

[Image Classification] Week 4 Daily Report :: seofware

by seowit 2021. 8. 25.

<< 마스크 착용 상태 분류 >>

: 카메라로 촬영한 사람 얼굴 이미지의 마스크 착용 여부를 판단하는 Task

 

🔴앞으로 더 고민해봐야 할 것은 빨간색 🟢고민해서 결론을 내린 것은 초록색

 

🌼 Day15. EDA

  • EDA는 무엇을 해야할지 고민
    • 피어세션 전에는 각 클래스 별로 어떤 데이터가 있는지 확인하려고 함
    • 피어세션에서 다른 캠퍼님의 EDA를 보고 조금 더 데이터를 뜯어볼 필요를 느낌
      • 데이터의 분포를 확인했는데, 성별은 'female' 비율이 높았고 연령대는 '60세 이상'이 확연히 적었으며, '30-60세' 범위의 사람들은 너무 골고루 펼쳐 있었다.
      • 위를 보고 데이터 불균형으로 인한 문제가 발생할 것을 예상할 수 있었고 해결방법에 대해 고민해봤음.
    • data visualization의 seaborn 강의 수강
  • 서버 생성
    • AI stages 플랫폼 이용
    • jupyter notebook를 이용했는데, 다음주에는 python으로 사용해 볼 예정
  • 코드 이해
    • import, test dataset, inference 부분의 코드가 기본으로 있음
    • torch, torchvision 등의 필요한 라이브러리 살펴봄
    • test dataset의 구조를 보고 train dataset은 어떻게 짜야할지 대략적인 코드와 주석 작성
    • train dataset을 위해 class를 어떻게 분류해야할지 고민
      • age, gender, mask 세 가지 요소를 어떻게 input 이미지에서 찾을지 방법 고민
    • inference에서 dataset과 dataloader 부분 확인

🌼 Day16. Dataset

  • 💥Mission : 모든 이미지를 18개의 클래스(target)로 분류하고 Dataset 클래스(Class)를 완성하라!
  • 바닐라 데이터 구조
    • "train/images/" 아래에 2700명의 폴더가 존재. 폴더명은 'id_gender_race_age'로 명명. 예를 들면 '0001_female_Asian_22', '0002_male_Asian_14' 등의 폴더가 있음
    • 각 폴더 아래에는 7장의 사진이 있는데, 마스크 쓴 사진 5장, 잘못 착용한 사진 1장, 마스크 미착용 사진 1장으로 구성.
  • 목표 데이터 구조로 변경 : 각 이미지(2700*7=18900)을 path와 class(0~17)를 칼럼으로 하는 dataframe에 정리.
    •   
      정리 결과 - train_df
  • TrainDataset(Dataset) 구현
    • __init__ 
      • transform 부분은 TestDataset과 동일
      • TestDataset에서는 image path만 필요하지만, TrainDataset에서는 target(y)도 필요하기 때문에 위에서 정리한 데이터프레임(train_df)을 불러옴.
    • __getitem__
      • index를 통해 image와 target 반환하는 함수.
    • __len__ 
      • TrainDataset의 개수 구하는 함수. 여기서는 18900개
    • class TrainDataset(Dataset):
          def __init__(self, img_labels, transform):
              self.df = img_labels
              self.transform = transform
              
          def __getitem__(self, index):
              train_img_dir = os.path.join(train_dir, 'images/')
              image_path = train_img_dir + self.df.iloc[index]['path']
              image = Image.open(image_path)
              target = self.df.iloc[index]['class']
      
              if self.transform:
                  image = self.transform(image)
                  
              return image, target
      
          def __len__(self):
              return len(self.df)

🌼 Day17. Model

💥Mission: 아래의 스펙을 보고 모델 구현, pretrained model 불러와서 fine_tuning 시도, feature_extration(Backbone freeze) 시도 

  • resNet 모델을 불러와서 Fine tuning 시도
    • 호출방법 : model = torchvision.models.resnet18(pretrained=True)
    • 마지막 fully connected layer의 in, out features 확인 후 class 개수에 맞춰서 바꾸기
      • #in_features : resnet18은 512, resnet152는 2028
      • 변경방법 : model.fc = nn.Linear(512, 18) # 512는 resnet18 fc의 in_features, 18은 class num
🙄 다른 조건은 모두 같게 하고 모델만 resnet18과 resnet152 두 개로 다르게 해서 학습을 해봤는데, accuracy가 resnet18은 68%, resnet152는 51%가 나왔다. 당연히 152가 더 좋게 나올 거라고 기대했는데, 예상과 달라서 놀랐다. 내가 임의로 설정한 learrning_rate, transforms, optimizer가 resnet18에 더 잘 맞아서 그런 것 같다. 하이퍼파라미터 튜닝이 중요하다고 배웠는데, 모델에 따라서도 좋은 하이퍼파라미터가 다른 것 같다. 각 모델에 적합한 파라미터를 찾는 과정이 필요할 듯 하다.
  • 미션에서 제시한 모델 스펙을 구현해보려고 했는데, 표에 나타난 표시들이 의미하는 것도 모르고 Residual을 어떻게 구현해야 할지 모르겠다. 우선 질문을 적어놓고 내일 코드가 공개되면 답변을 작성해야겠다
    • ❓ Residual은 어떻게 구현할까?
    • ❓ Block마다 옆에 1x, 2x, 8x 등이 적혀 있는데, 이것이 의미하는 것은 무엇일까?
    • ❓ Convolutional kernel size에 3 x 3 / 2 라고 적혀있는데, /2가 의미하는 것은 무엇일까?
    • ❓ Conv2d의 파라미터는 #input channel, #output_channel, #kernel_size 인데 스펙에는 왜 output size도 제공할까? 어디에 사용되나?
  • wandb 회원가입하고 jupyter notebook과 연동해봄

 

🌼 Day18. Train

Train 결과가 잘 나오지 않는데, 클래스를 한 번에 18개를 분류하는 것보다 마스크, 성별, 나이대를 나눠서 학습하는게 낫지 않을까 싶다. 그래서 알아보다가 Multi-label classification과 Mutli-class classifiacation에 대해 알게되었다.

위의 사이트를 보고, 구현 방법에 대한 방향을 잡았다. 

한 여성의 사진을 가지고 위 세가지 방법으로 분류를 할 수 있다. 그 중에서도 내가 해결해야 할 문제와 적합한 방식은 multi-output classification 이라고 생각했다. 왜냐하면 우리도 사진이 주어지면 [wear, not wear, incorrect], [female, male] [30세 아래, 30~59세, 60 이상] 으로 분류하기 때문이다. 

 

댓글