본문 바로가기

Machine Learning/about ML

kaggle 입문 -Digit Recognizer

구글 부트캠프 팀원들과 kaggle 입문을 하기위해 Getting Started Prediction Competition인 Digit Recognizer[Learn computer vision fundamentals with the famous MNIST data]을 각자 풀어보고 리뷰하기로 하였다. 

 

 

intro

이미지 분류 문제임을 확인 할 수 있다.

대회 소개:

이 대회는 컴퓨터 비전(Computer Vision)에 적용되는 기술에 대한 소개를 위한 이상적인 대회로, R 또는 Python 및 기계 학습 기초에 어느 정도 경험이 있지만 컴퓨터 비전에는 새로운 분야인 개발자를 위한 것입니다. 이 대회는 사전 추출된 특징을 포함한 고전적인 데이터셋을 사용하여 신경망(Neural Networks)과 같은 기술을 소개하는 완벽한 기회를 제공합니다.

대회 설명:

MNIST("Modified National Institute of Standards and Technology")는 컴퓨터 비전의 "안녕, 세계!" 데이터셋으로 알려져 있습니다. 이 데이터셋은 1999년에 처음 출시된 이래로 필기체 이미지의 고전적인 데이터셋으로서 분류 알고리즘의 벤치마킹을 위한 기초로 사용되어 왔습니다. 새로운 기계 학습 기술이 등장하더라도, MNIST는 연구원과 학습자 모두에게 신뢰할 수 있는 자원으로 남아있습니다.

이 대회에서 여러분의 목표는 수만 개의 필기체 이미지 데이터셋에서 숫자를 올바르게 식별하는 것입니다. 튜토리얼 스타일의 커널을 제공하여 회귀부터 신경망까지 모든 것을 다루고 있으며, 여러 가지 알고리즘을 실험해보고 어떤 기법이 잘 동작하며 기술 비교를 직접 학습하는 것을 장려합니다.

연습할 수 있는 기술:

간단한 신경망을 포함한 컴퓨터 비전 기초

SVM 및 K-최근접 이웃(K-nearest neighbors)과 같은 분류 방법

 

EDA

1.데이터셋 구성 파악:


- 'train.csv'와 'test.csv' 데이터 파일: 0부터 9까지의 손으로 그린 그레이스케일 이미지
- 각 이미지는 높이 28 픽셀과 너비 28 픽셀로, 총 784개의 픽셀

-각 픽셀은 해당 픽셀의 밝기 또는 어둠을 나타내는 단일 픽셀 값과 연결되어 있으며,  이 픽셀 값은 0에서 255 사이의 정수

-훈련 데이터 세트인 'train.csv'는 총 785개의 열로 구성되어 있음.
-첫 번째 열은 "label"이라고 불리며 사용자가 그린 숫자를 나타냄. 나머지 열은 해당 이미지의 픽셀 값들을 포함.


2.데이터 csv 구조 확인

데이터 레이블 확인

3.데이터 시각화

4.데이터 불균형 확인

불균형 없음.

 

 

hyperparameter tuning

 

-train data augmentation 

    #훈련 데이터 전처리 - 데이터 증강
    '1': transform.Compose([
                           transform.ToPILImage(),
                           transform.Resize(94),
                           transform.Grayscale(num_output_channels=3),
                           #밝기(brightness), 대조(contrast), 채도(saturation) 등의 색상 조정을 무작위로 적용
                           transform.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),
                           # 최대 11도까지 무작위로 회전, 이동, 크기 조정
                           transform.RandomAffine(degrees=11, translate=(0.1,0.1), scale=(0.8,0.8)),
                           transform.ToTensor(),
                           transform.Normalize(
                                    [0.13097111880779266, 0.13097111880779266, 0.13097111880779266],
                                    [0.30848443508148193, 0.30848443508148193, 0.30848443508148193])
]),

 

 

(1)transform.Grayscale(num_output_channels=3)

:1채널 흑백 이미지를 3채널(RGB) 이미지로 변환

- torchvision.models 의 pretrained =True로 사전학습 모델 imageNet를 사용하기위해 mnist datasets을 3채널로 변환

(imageNet은 3채널 이미지를 입력으로 받는 신경망 아키텍처로 학습됨.)

 

(2)transform.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2): 밝기, 대조, 채도와 같은 이미지의 색상 속성을 랜덤 변경.


(3)transform.RandomAffine(degrees=11, translate=(0.1,0.1), scale=(0.8,0.8))

-이미지에 최대 11도까지 무작위로 회전

- 이미지의 너비와 높이의 10% 범위 내에서 무작위 이동

-이미지의 너비와 높이는 80%에서 100% 사이의 크기로 조정

 

 

증강 시각화

=>Non-augmented data  + aug datasets 둘다 모델에 입력

 

train 전략

 

1.Non-augmented data  + aug datasets 둘다 모델에 입력

def create_dataloaders(seed, test_size=0.1, df=train_pd, batch_size=50):
   
    #  훈련 데이터와 검증 데이터로 분리
    train_data, valid_data = train_test_split(df,
                                              test_size=test_size,
                                              random_state=seed)
   
    # Create Datasets
    train_dataset_0 = GetDf(train_data, Transform=transformer['0'])
    train_dataset_1 = GetDf(train_data, Transform=transformer['1'])
    #두 개의 데이터셋을 하나로 결합
    train_dataset = ConcatDataset([train_dataset_0, train_dataset_1])

    valid_dataset = GetDf(valid_data, Transform=transformer['val'])
   
    # Create Dataloaders
    train_loader = DataLoader(train_dataset, batch_size=batch_size, num_workers=0, shuffle=True)
    valid_loader = DataLoader(valid_dataset, batch_size=batch_size, num_workers=0)

    train_size = len(train_dataset)
    val_size = len(valid_dataset)

    return train_loader, valid_loader, train_size, val_size

2.train 방법

 
densenet121= torchvision.models.densenet121(pretrained=True)
#모델의 모든 파라미터 동결 
for param in densenet121.parameters():
  param.requires_grad=False
#모델의 출력 레이어를 변경->뒷부분 레이어만 학습
densenet121.classifier = nn.Linear(in_features=densenet121_0.classifier.in_features, out_features=10, bias=True)

-fine tuning 

전이 학습(transfer learning)에서 일반적으로 사용는 방법으로 , 

먼저 출력 레이어를 작은 학습률로 훈련하고,

작은 학습률로 전체 네트워크를 fine-tuning하여 전체 모델을 업데이트하는 방식을 사용.

 

모델은 총 두번의 훈련을 하게됨.

  optimizer = torch.optim.Adam(model.fc.parameters(), lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
  # 학습률 스케줄러 설정 (스텝 스케줄러)
  scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 4, gamma=0.1)

 

  1. Fine-Tuning 및 스케줄러 설정: Fine-Tuning하기위해 model.fc.parameters() 파라미터를  설정하고, 학습률 스케줄러(torch.optim.lr_scheduler.StepLR)를 설정합니다.  Fine-Tuning : model.fc모델의 출력 레이어를 나타내며,존의 사전 훈련된 모델 아키텍처의 일부인 출력 레이어의 가중치와 편향만을 업데이트하고 나머지 모델 파라미터는 고정.
  2. 훈련 루프 - 첫 번째 단계 : 첫 번째 단계에서는 모델의 일부 파라미터만 업데이트됩니다. 
  3. 훈련 루프 - 두 번째 단계 : 두 번째 단계에서는 모든 모델 파라미터를 최적화합니다. 이 과정에서 모든 파라미터가 업데이트됩니다.

해제

  for param in model.parameters():
        param.requires_grad=True

장점

: 적은 계산 비용으로 빠른 수렴과 나은 초기 성능을 얻을 수 있음.

빠른 수렴: 먼저 상위 레이어(분류기)를 작은 학습률로 훈련하면 초기에 모델은 이미지넷과 같은 대규모 데이터셋에서 학습한 특징을 유지한 채로 특정 작업에 대한 예측을 수행할 수 있습니다. 이로 인해 초기 훈련 단계에서 빠른 수렴이 가능하며, 상위 레이어의 가중치는 상대적으로 빨리 업데이트됩니다.

더 나은 성능: 작은 학습률로 훈련된 상위 레이어는 초기 예측을 더 정확하게 수행할 수 있으므로 초기 예측의 품질이 향상됩니다. 이로 인해 높은 초기 성능을 얻을 수 있습니다.

적은 계산 비용: 초기 훈련에서는 상위 레이어만 업데이트하므로 계산 비용이 낮습니다. 따라서 초기 훈련은 비교적 저렴하게 수행할 수 있습니다.

적은 데이터 필요: 상위 레이어를 작은 학습률로 훈련하기 때문에 상대적으로 적은 양의 작업 데이터로도 좋은 결과를 얻을 수 있습니다. 이는 특히 작은 규모의 작업 데이터셋에서 유용합니다.

 

 

단일 모델 훈련 결과

 

model public score
mobilenet_v2 0.99521
vgg19_b 0.99642
resnet101 0.99646
densenet121 0.99657
googlenet 0.99667

 

ensemble model 훈련 결과

앙상블 2개

densenet121,googlenet = 0.99632  

 

 

앙상블 3개

googlenet,densenet121,resnet101 = 0.99732

densenet121,googlenet,vgg19_b  = 0.99742

densenet121,,resnet101,vgg19_b =0.99728

 

앙상블 4개

densenet121,googlenet,resnet101,vgg19_b  0.99703

 

 

 

앙상블 5개

mobilenet_v2,densenet121,googlenet,resnet101,vgg19_b  0.99728

 

 

 

결론

 

앙상블 3개 모델의 성능이 가장 좋았음. densenet121,googlenet,vgg19_b  = 0.99742 

 

더 시도해볼 방법

 

1. l2 변경

 

2. 손실함수 변경