AI(DeepLearning)

처음해본 kaggle 도전기

크레이지제이 2019. 11. 27. 09:14
반응형
crazyj_kaggle_first

Kaggle first time

crazyj7@gmail.com

동기

처음에 이 사이트를 보고 단순히 무료로 데이터 파일들을 다운받을 수 있는 사이트 인줄 알았다. 거의 방문을 안하다가 가끔 데이터 파일 쓸모있는게 있나 찾다가 여러가지 다른 기능들이 많은 것을 발견했다.
학습에 도움이 많이 될 거라는 생각에 모니터링 중 Competition이 있는 것을 알게 되고 국내에서 주최한 대회가 있다는 것에 흥미를 느끼고 장난삼아 도전해 보려고 했다.
그간 AI쪽을 제대로 공부한 적은 없지만 나름대로 독을 좀 했. 다만 혼자서 하려니 어디 물어볼 데도 없고, 이해가 안가서 막히는 것들이 많아 진행 속도가 더디었다.

캐글 사용기

커널을 대체 어떻게 사용해야 되는지 어렵다.
느리고, 자꾸 끊기고, 에러나고, 아웃풋을 못찾겠고, 이어서 되는 건지 아닌지 모르겠고. 커밋은 git 처럼 소스 커밋을 말하는 건지…

  • 커널을 여러 개 동시에 돌릴 수 있다고 한다. 최대 5개 던가? 아직 해 보지는 않았다.
    • 3개 4개 돌려보니 잘 된다. 계속 하다 보면 익숙해짐.
  • 커널 이용 최대시간은 9시간 이라고 하는 것 같다. 학습이 이 시간을 넘어가면 짤린다는 것이겠다. 중간 저장이 필수겠다.
  • 가공 생성한 파일들은 대체 어디에 있는 것일까?
    • 현재 디렉터리에 생성된다. /kaggle/working 인 듯. 디렉터리 탐색도 커맨드 실행으로 할 수 있다. 커널버전 보기에서 Output 메뉴에 생성한 파일들 목록이 보여서 다운로드는 할 수 있다.
    • 그런데 이어서 작업할 때는 왜 output 파일이 다 없어지는 것일까? 디렉터리 탐색시 다 사라진다. 작업 디렉터리인 working 디렉터리는 세션 실행시 초기화된다. output이 다 없어진다. 주의! 이전 커밋은 버전을 찾아 들어가면 output을 받을 수 있다.
  • 소스는 여러 개를 올릴 수 있는 것일까?
    • 안되는 것 같다.
    • 한 파일만 되는 듯. ipynb (노트북)와 py(스크립트) 변환을 지원하고 업로드기능이 있으니 잘 활용하면 된다. 스크립트는 올릴필요없이 복붙하면 쉽다.
  • 대체 커밋이 뭐지?
    • 커밋은 소스 전체를 실행하는 것이다. 에러없이 모두 성공해야지만 output 파일이 생성되고, 다운 받을 수 있다. 중간에 실패하면 날라간다. ㅜ.ㅜ
  • 생성한 output을 유지할 수는 없나?
    • 시행착오 끝에 output을 다운 받아서 dataset에 추가하고 커널에서 dataset을 추가해서 불러서 사용하면 된다.
  • 데이터셋 업데이트는?
    • 안된다. 올라간 데이터셋을 삭제하고, 새로운 데이터셋을 동일한 이름으로 올리는 식으로 업데이트 할 수 있다. 불편함. 해당 데이터셋을 참조하는 커널에서는 링크깨진 데이터셋을 삭제하고 다시 만든 것을 추가해 주어야 한다.

캐글 사용 정리

  1. 로컬 환경에서 먼저 자료 분석을 한다.
    데이터 셋을 받은 다음 jupyter notebook이나 lab으로 자료 관찰하고, 데이터 전처리를 하는 것을 만든다.
  2. 데이터 전처리된 파일들을 데이터셋으로 만들어 업로드한다.
  3. 가급적 경로를 로컬환경과 캐글환경을 일치시키면 올릴때 경로 수정이나 환경플래그값을 변경하지 않아도 되어 편하다.
    따라서 …/input/dataset이름/파일명 이나 …/input/dataset이름/압축파일명/내부파일명 으로 접근.
  4. 커널을 만들고 데이터셋을 추가하여 테스트해 본다
  5. 로컬 환경에서 디버그 모드를 만들어 적은 데이터로 빠르게 학습할 수 있도록 준비한다. 잘 되면 릴리즈모드로 만들고 커널에 임포트하여 커밋해 본다.
  6. 기본이 되는 커널을 잘 만든다. 여러가지 테크닉을 집어 넣기 전에 기본이 되는 커널이 잘 작동하고 성능도 좋게 만들 방안을 찾는다.
  7. 데이터가 크면 메모리 부족 에러를 아주 많이 볼 것이다. 이미지의 경우 numpy로 만들어 로딩하여 쓰다 보면 그리고 data type을 float로 변환하면 엄청나게 증가한다. 미리 메모리에 로딩하지 말고 필요한 만큼. 일정 크기만큼 불러서 처리하고 결과 저장하고를 반복하여 메모리 부족을 방지해야 한다. 전처리 후 이미지 크기도 크게 영향을 받는다. 이미지가 너무 작으면 성능이 떨어질 것 같고, 너무 크면 학습도 어렵고 메모리도 부족할 것 같다.
  8. EarlyStopping을 사용하여 멈출 때를 정한다. metric을 평가 방식에 맞게 설정한다. (loss, acc, f1_score 등)
  9. Checkpoint 저장. 중간 중간 best를 계속 저장하도록 한다.
  10. 테크닉?
  • 이미지 전처리를 바꿔본다. 크기, Margin추가, 색상, color scale, … cut-out (이미지 일부를 삭제), normalize, …
  • Image Augument Generator로 학습 데이터를 늘린다. zoom, shift, rotation, shear, flip, brightness, …
  • Pre-Trained Model 변경 : xception, efficientnet, resnet, …
  • Dropout 추가
  • Train/Validation 비율 변경 / 샘플링 기법 변경 : oversampling, straitifiedKFold, …
  • ReduceLROnPlateau 적용
  • Cross Validation : 결국 모든 학습데이터를(validation 포함) 훈련하게 되는 방식으로 학습데이터가 많아서 결과도 더 좋아진다.
  • 앙상블 : 여러 네트웍의 결과를 보고 판단. (5% 정도 올랐음)
  • TTA : 시험시에 시험 이미지에 Augument를 가해서도 측정해 보고 그 결과를 반영해 본다. (0.2% 올랐음)
  1. 몇 개의 폴드로 나눠서 폴드 번호를 지정하고 학습할 수 있는 스크립트를 만들고, 커널에 올려 돌린다. 이 커널을 Fork하여 폴드 번호를 바꿔가면서 계속 커널을 만들어 commit한다. 동시에 4개까지 model을 만들 수 있을 것이다.
  2. model들을 다운 받아 모델 데이터셋을 만든다.
  3. 모델들을 합쳐 앙상블 결과를 내는 스크립트를 만들어 돌린다.
  4. 마지막에 TTA를 추가해 본다.
  5. pseudo labeling 적용 테스트. (효과가 있을지는 모르겠다.)

용어

  • val ; validation. 검증용 데이터. 모델 학습시에는 모델은 검증 데이터를 전혀 본적없는 데이터이다.
  • k fold ; train, val 셋을 분리하는데, k개의 다른 방식으로 데이터를 나눈다. 따라서 fold별로 하나씩 모델을 만들 수 있다.(k개의 모델 생성 가능). 나중에 생성된 모델들을 합친다(? 앙상블한다는 의미인가?)
  • stratifiedkfold ; kfold를 할 때, 원본 데이터의 클래스 비율을 유지하여 분리한다.
  • oversampling / undersampling ; stratified하는 것 대신, 샘플 수를 고르게 맞추는 방식이다. over는 많은 개수 기준. under는 부족한 개수 기준.
  • tta ; 학습시가 아닌 테스트시에 augmentation을 하여 앙상블 결과를 내놓는다.
  • cross validation ; 학습이 다 끝나면 나중에 validation data도 학습한다.
  • 앙상블 ; 여러 다른 모델의 결과를 합친다. (? 합치는 방식이 여러가지 일 듯. average, max count)
  • pseudo label ; 어느정도 성능이 나온 훈련모델로 test셋의 결과를 예측하여 99% 가량 강하게 맞다고 한 데이터의 라벨을 가상으로 붙여 훈련셋에 추가한다. 훈련데이터 개수 확장 효과.
  • cut-out image ; 이미지에서 랜덤하여 자름. 랜덤한 영역의 블록을 잘라버림. (노이즈)
    -했다면 했다고 할 수 있다.

Car model classify

문제는 자동차 모델명을 분류하기.
학습 이미지 데이터와 라벨이 있고 더구나 Bounding box도 있어서 도전해 볼만 했다. 근데 클래스가 상당히 많았다. 정확도가 높게 나오지 않을 것 같은데…라는 생각이 들었다. 그러나 나중에 보니 다른 참가팀들의 정확도에 놀랐을 뿐이다.

Try1 ; 70%

  • mobilenetv2

전에 한 번 구글이미지 검색으로 동물들 데이터셋을 만들어 이미지 분류 테스트를 해봤었는데 단순한 몇 개 클래스 구분하는 것도 만만한 일이 아니란 걸 알았다.
나름대로 CNN을 활용하여 Sequential 모델로 만들어봤지만 쉽사리 정확도가 높아지지 않았다는 기억이 났다.
그 때 데이터량의 부족, 학습이 안되는 현상, 과적합 현상 등 어려움이 많았다.
나중에 이미지 분류에 미리 학습된 모델들을 활용한 전이학습이 있다는 것을 보고 적용해 보니 손쉽게 정확도가 높아지는 것을 보았다.

  • 데이터 전처리
    • 이미지 crop 하고 resize, RGB 3 channel로 보정
  • mobilenetv2 사용
    • 뒤에 Dense1개, Softmax1개 사용

Test 데이터셋으로 accuracy가 70% 정도??

  • 나중에 알고보니 image color를 rescale하지 않았었다. 수정 완료. rescale=1/255로 color값을 [0,1] 범위로 함.

Try2 ; 80%

  • ImageAugumentation 으로 학습 데이터 확장. 좌우반전. 사이즈. 뒤틀림 등.
    mobilenetv2에 Dense 2개, Softmax1개 사용
    정확도 80%로 향상됨.

Try3.v1 ; 80%

training set의 정확도가 99%가 넘는데, validation은 80%였다.

  • Cross Validation?
    훈련 데이터셋 부족으로 데이터셋 재분배하여 test set, validation set으로 나누어 이어서 학습.
    training , validation set 모두 90% 이상 나옴. 그러나 학습이 계속되면 train은 99% val은 79정도로 떨어짐. test set은 80%로 여전함.
  • OOM이 자주 발생해서 고생함. batch_size 줄임. 네트웍 사이즈 줄임. 더 이상 필요없는 변수들 삭제.

Try4.v2 ; 81%

이미지의 일부를 지워서 학습??
Image part Random Remove ; resnet에 있다는 모듈을 적용시도.
ImageAugment ; shift 추가.
성능이 약간 좋아졌으나 별차이 없는 정도. 이론상 좋은 듯 한데.
lb acc 81%

Try5.v3 ; More Deep ; 83%

  • xception

원래는 Resnext50을 사용하고 싶었으나, keras 버전이 오래된 거라서 그런지 지원이 안된다.

  • 학습전이 모델 변경. mobilenetv2에서 xception으로. 파라미터수가 5배는 차이난다. 400만개 vs 2천2백만개.
  • 처음부터 다시 학습. 시간이 오래 걸림.
  • 모델은 처음부터 freezing하지 않고, 어느 정도 학습 한 후에 전이 모델만 freezing한다. 처음부터 freezing하니 정확도가 잘 안올라갔다. freezing을 풀고 학습하니 빠르게 상승하였다. 20~30에폭만에 train 80%, val 70%가 나온다. 어떤 경우는 전이모델의 상단 일부만 freezing하기도 한다.
  • train 93%, val 82% 정도까지 나옴.
  • 위 모델 2개를 만들고 병합하니 lb 83% 정도 나옴.
  • 더 학습 시킬 필요가 있어서 모델3을 생성 중. EarlyStopping 조건을 변경하여 더 오래학습되도록 patience를 증가. delta는 더 작게.

Try6. v3 ; metrics ; 91.5%

EarlyStopping 조건이 중요하다. f1_score를 조건으로 주고, 이어서 학습하되. 전이모델은 weight freezing시켰음.

  • 평균 80에폭정도 학습.
  • train 97%, val 85% 정도 나옴.
  • 데이터셋 구간을 달리하여 (cross validation) 모델 3개를 생성.
  • 개별 최대는 lb 86.8% 로 올라감.
  • 세 모델을 앙상블했더니 무려 5%나 상승하여 LB 91.58%. 드디어 90대 진입.
  • 그런데 개별로도 그 정도 나와야 되지 않나?

Try7.v4 ; 92.7%

개선해야 될 점.

  • 모델 세 개를 하나씩 불러 예측하려니 시간이 많이 소요됨. 웨이트만 저장하여 불러쓰는 것으로 하자. (이렇게 해봤는데 속도 차이가 거의 없음???)
  • weight는 best_only로 checkpoint를 저장하는 방식 사용. (monitor에 val_f1_score, mode는 max로 지정해야 함)
  • 3개를 만들어 앙상블 ; 92% (LB)

Try8. v5 ; 93.5%

  • 5개의 fold로 데이터 구분하여 새로 학습하고 5개를 앙상블해 보자.

More or Stop?

  • 일단, 현재까지 버전 commit.
  • 좀 더 올릴 수 없을까?
  • 이미지 전처리에서 crop할 때 margin을 추가할까?
  • 이미지 일부 제거 기능을 끄는 것이 좋을까?
  • 일괄 처리로 모델 5개 생성해서 다시 시도?
  • 전이학습 모델을 다른 것으로 변경해 볼까?

Try v6

  • 이미지 crop시 마진 20픽셀 추가. 이미지 왜곡시에 덜 잘릴 듯.
  • 이미지 일부 삭제 기능(cut-out)은 off 시키니까 acc 2% 감소.
  • 이미지 일부 삭제 기능이 있는 것이 좋다!

Try v7

  • 이미지 일부 삭제 on ; 반드시 사용해야 겠다.
  • 마진도 사용하는 것이 좋을 것 같다.

Try v8

  • xception과 resnet50 모델을 각각 5개씩 만들고 val_f1_score가 높은 순서대로 5개를 골라서 합의.
  • 합의 방식 ; 기존 : np.sum(a,b, axis=0)
  • 최대,최소를 버리고 중간 판정자 점수 합계??? 테스트 필요.
    • minv = np.min(…), maxv = np.max(…), np.sum() - (minv+maxv)
  • xception이 가장 괜찮은 것 같다. resnet50은 느리고 학습이 잘 안됨. mobilenetv2는 되긴 하지만 성능이 좀 떨어진다. efficientnetb2도 학습이 잘 안됨.
  • xception만으로 구성하는 것이 가장 낫다는 결론.
  • xception 모델 5개를 앙상블하면 개별로는 f1_score가 85,86,87 정도인데, 합치면 92 정도로 올라간다. (5%정도 인상)
  • Pseudo Labeling??? xception 모델에서 성능이 가장 좋은 것을 선정하여 test셋을 예측하였고, 예측시 가장 높은 확률의 클래스의 확률값을 히스토그램으로 보니, 0.99 이상이 반 정도 나왔다. 0.99 이상으로 예측한 라벨을 맞다고 가정하여, test 셋에서 라벨을 할 수 있는 부분들을 추출하여 pseudo set을 만들었다.
  • train set에 pseudo set을 추가하여 학습할 데이터를 뻥튀기하여 학습!
  • xception 모델에서 성능이 가장 좋은 것을 선정하지 않고, 앙상블하여 판단한 결과를 사용하였다. (더 확률이 올라감)
  • 90% 이상 정도는 맞출 것이고, 그 중 상위 50% 정도를 추가 학습데이터로 한 것이-라 어느 정도 일리가 있다.
  • 이렇게 훈련셋을 증가하고 기존 개별 모델들은 연속 학습하니, 개별 모델들의 f1 score가 더 올라갔다. 대략 85,86,87에서 94,95,96 정도로.(10%인상?) 이것을 다시 앙상블 한다면?
  • 결론은… 92. TT
  • 마지막에 1epoch만 all set을 대상으로 학습. 약간의 보정???
    -stratifiedkfold 적용. fold 나눌 때 클래스 비율을 유지해준다고 한다.

Try9

  • 이미지 크기 확장. 왜 224x224로 했지?(처음했던 mobilenetv2 기준). 299x299로 확장.(xception기준). 아무래도 이미지가 커야 더 잘 구분하겠다.
  • xception 베이스 모델 사용. : 기존 유지
  • cut out image (일부 손실. 자름. 검은 박스 노이즈 추가) : 기존 유지
  • 마진 20픽셀 유지하고 resize.
  • straitifiedkfold 적용. fold5으로 모델 3개 생성
  • pseudo label 삭제.
  • 진행. 먼저 single model의 성능부터 파악하자. 앙상블은 나중에.
  • 기존은 개별이 85정도 val f1 score 였다.
  • 메모리 사용량 증가로 batch는 16으로 낮춤. 나중에는 4로 낮춤.
  • Augument parameter!
    • rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True, vertical_flip=False, shear_range=0.5, brightness_range=[0.5, 1.5], fill_mode=‘nearest’, preprocessing_function=get_random_eraser(v_l=0, v_h=255)
    • 현재 진행 중인 것은 rotation은 15. 나머지는 0.1. brightness 추가. 이하 상동.
  • 메모리 부족… OOM. 메모리 부족 관련하여 좀 더 분석해야 할 것 같다.
    • 가공한 이미지를 numpy로 저장하여 불러서 다시 나누어 사용했는데, 이게 메모리 부족을 야기시키는 것 같다. 아예 처음부터 가공된 이미지를 디렉터리별 저장하고 kfold시 index로(파일명)으로 폴드에 맞는 이미지들만 로딩하여 사용하는 것이 좋은 것 같다.
    • 전체를 다 로딩하여 나누지 말고, Generator에서 디렉터리 지정하고, from dataframe으로 필요한 파일명 목록을 주는 방식으로 로딩.
    • 미처 다 못해보고 컴피티션이 종료됨.
    • 개발 환경이 좀 아쉽다. 캐글 커널로 좀 더 컴팩트하게 테스트할 수 있도록 준비가 필요할 것 같다.
    • 랜덤 고정 필요. 계속 변경되면 기준이 없어서 모델의 평가가 어렵다.

After… 94.1%

  • 다른 Pretraining Model 적용 비교
  • 이미지 전처리 결과를 numpy로 하지 않고, 이미지 파일로 저장하여 데이터셋 생성 및 로딩 방식으로 함.
  • flow_from_dataframe을 사용.
  • 이미지 크기를 299에서 250으로 줄였더니 메모리 압박에서 벗어났다.
  • Dropout 추가 : 개별로 최고 90%도 찍는다. (val_f1_score) 대략 89,90정도가 나옴.
  • Fold를 6개로 늘림.
  • 6개 네트웍 앙상블 결과 93.9%대가 나옴.
  • TTA 추가 ; 단순하게 좌우 flip만 하였다. 0.2%상승하여 94.1%대가 나옴. (최종적으로 12개의 결과를 합쳐서 평균으로 판단한 결과)

못해본 것 들…
다른 기본 네트웍 사용.
gray scale image 로 학습하는 것은 어떨까?
contour image 로 학습하는 것은 어떨까?

kaggle command

download kaggle api token (account menu)
copy to ~/.kaggle from ~/downloaddir/kaggle.json
chmod 600 ~/.kaggle/kaggle.json

kaggle competitions list -s titanic
kaggle competitions download titanic
데이터 파일 다운로드

kaggle kernels list --user junheeshin
kaggle kernels pull junheeshin/titanic-analyze
커널 소스 파일 가져옴.

Authors: crazyj7@gmail.com