Full Stack Deep Learning — Training and Debugging

김희규
11 min readSep 7, 2020

이 글은 Full Stack Deep Learning의 다섯번째 코스인 Training and Debugging를 보고 내용을 정리한 글입니다. 내용의 사진은 모두 발표 슬라이드를 가져왔습니다. 잘못 이해했거나, 의역이나 오타가 있을 수 있습니다. 제보해주시면 감사하겠습니다 🙏

Overview

왜 딥러닝 문제해결은 어려울까? 실무진들이 보통 느끼기론 80–90%의 시간을 디버깅과 튜닝에 사용하고 오직 10–20%의 시간을 수학 공식을 유도하고 모델을 구현하는데 사용한다. 논문 등지에 나온 결과물을 재구현하기가 어려운 이유에는 다양한 요인이 있다.

왼쪽은 논문, 하지만 우리가하면 오른족처럼 됨
  • 구현 버그
  • 모델 하이퍼파라미터가 다름
  • 데이터와 모델이 안맞음
  • 좋은 데이터가 아님
박사땐 모델과 알고리즘에 대부분의 시간을 쏟았지만 실무에서는 데이터셋에 많은 시간을 투자

DL 문제해결에 필요한 마인드셋은 바로 비관주의, 문제의 원인을 명확하게 알기 어렵기 때문에, 우선은 간단하게 시작하고(Start Simple), 점차 복잡도를 올려가야한다.

시작하기 앞서

  1. 테스트 셋이 존재하고
  2. 향상시킬 간단한 metric이 있고
  3. human-level 성능이나 출간된 결과물이나,이전의 베이스라인 등 목표 성능이 있다고 가정한다

Start Simple

딥러닝 모델을 간단하게 시작하는 방법은?

아키텍처는 이미지면 우선은 LeNet, 이후에 ResNet, 이런식으로 시도를 해보면 된다. 하지만 실제 문제들이 이렇게 간단한 경우는 잘 없다.

예를 들어 이미지 2장과 텍스트가 입력으로 들어온다면, 정말 간단하게 CNN과 LSTM으로 결과를 만들어내고 이를 합친다음 FC레이어로 판별해내는 것처럼 간단한 모델을 만든다.

Use Sensible Defaults

활성화함수, 옵티마이저 등은 일반적으로 추천되는 것을 사용한다. Regularization과 Data Normalization은 최종 성능을 끌어올릴 때 쓰고, 버그를 유발할 수 있으니 처음에 사용하지 않는다. Data의 scale을 조정하는 Data Normalization은 중요한 작업이고, 이후에 시도해볼만 하다.

이후에는 문제를 최대한 간단하게 만들어본다. 트레이닝 셋을 적게 시작해보거나, 분류문제라면 맞출 class 숫자나 이미지 크기를 고정한다. 모델이 별론지 문제가 어려운지 모르니까 우선 문제를 최대한 간단하게 하고 시작하자

Debug

딥러닝 모델을 어떻게 구현하고 디버깅할까?

버그가 없는 모델을 만들기 위한 프로세스를 살펴보자. 일반적으로는 가볍게 구현하고, 검증된 라이브러리를 쓰고(keras 등), 복잡한 데이터 파이프라인은 나중에 하는 것이다(Data Augmentation 같은?).

Get your model to run

먼저 동작하는 모델을 만들어야한다. 그 과정에서 주로 발생하는 이슈는 위와 같다

  • 레이어간의 shape 이 안맞거나, 타입이 안맞는 문제
  • OOM 문제: 가장 메모리를 많이 쓰는 부분을 찾아서 조절해야 한다.
  • Other: StackOverflow에 물어보거나 디버거로 디버깅해야한다. pytorch는 ipdb, Tensorflow는 trickier 등이 있다.

각 방법에 대한 세세한 내용은 설명하지 않고 넘어가고 나중에 슬라이드를 보라고 한다

Overfit a single batch

하나의 배치에 오버피팅시켜보기 — 쉬울 것 같지만 막상 해보면 잘 안된다. 자신있으면 스킵해도 된다. 학습이 잘 안된다면 보통 아래 4가지 이슈가 발생한다.

  • Error가 계속 올라간다: loss function이나 gradient가 부호가 반대로 되어있을것이다.
  • Error explodes: 보통은 NaN, Inf, div/0 같은 수치문제다. Learning Rate가 높을 때도 발생한다.
  • Error oscillates: Learning Rate를 낮추고 데이터 라벨이 섞였는지, Data Augmentation이 잘못됬는지 본다
  • Error plateaus: Learning Rate를 늘리거나 Regulation을 없앤다. loss function이나 데이터 파이프라인을 조사해본다.

Compare to a known result

이제 내 결과물을 다른 결과물과 비교해본다. 유용한 비교방법 순서대로 써보면

  1. 유사한 데이터셋의 공식 모델 구현체의 성능과 비교한다 — 한줄씩 보면서 같은 output을 내는지 본다.
  2. MNIST같은 벤치마크 데이터셋에서 공식 모델 구현체의 성능
  3. 비공식 모델 구현 — GitHub같은곳의 소스들은 보통 버그가 있으니 unofficial은 조심해야한다. (내 생각에는 Star가 많다면 신뢰도 상승할듯)
  4. 논문에 나온 결과(코드 없을 경우)
  5. MNIST같은 벤치마크 데이터셋에서 내 모델의 성능 — 내 모델이 간단한 세팅으로도 좋은 성능을 내는지 본다
  6. 유사한 데이터셋의 유사한 모델의 성능 — 보통 어느정도 성능이 나오는지 본다
  7. 정말 간단한 베이스라인(평균 출력이나 선형회귀 등…) — 내 모델이 무엇이든 학습이 되는지 본다

추가로 QnA

  • Batch Norm은 트레이닝 모드를 꺼놓는걸 잊는 경우가 많으니 조심

Evaluate

내 모델을 어떻게 평가할까?

모델을 학습할 때 보통은 위처럼 학습 그래프가 만들어지고

테스트 에러는 아래 값들의 합이다

  • Irreducible Error: Human-performance baseline 같은 더 줄일 수 없는 최소한의 에러
  • bias: Irreducible error와 training error의 차이 — 클 수록 underfitting
  • variance: validation error와 training error의 차이- 만약 underfitting이더라도 validation과의 차이가 클 경우 overfitting됬다고 할 수 있음.
  • val overfitting: validation error와 training error의 차이, 또 validation data의 error를 줄이는 과정에서 validation에 오버피팅될 수 있음

이런 식은 test dataset과 train dataset이 같은 분포를 가질때만 유효하다.

위 사진처럼 test data에는 train data에 없는 야간 사진 등이 포함되어있다면 다른 분포를 갖게된다. 이를 해결하는 방법은 test set에도 validation data를 추가하는 것이다.

그러면 위 사진처럼 test validation overfitting이 추가되고, 이들의 에러를 합쳐서 bias(underfitting)과 variance(overfitting)을 함께 고려할 수 있게된다.

Improve

모델을 어떻게 개선시킬까? 크게 4가지 방법에 대해서 소개한다.

Address under-fitting(reducing bias)

  1. 먼저 모델을 더 크게 만들어보고(레이어 추가/레이어 유닛 추가)
  2. regularization을 줄여보고
  3. 에러 분석을 해본다
  4. SOTA수준의 다른 아키텍처를 써본다
  5. 하이퍼파라미터 튜닝
  6. feature를 더 추가

Addressing over-fitting(reducing variance)

  1. 트레이닝 데이터 추가
  2. normalization
  3. data agumentation
  4. regularization(Dropout, L2, Weight Decay)
  5. 에러 분석
  6. 다른 아키텍처 쓰기
  7. 하이퍼파라미터 튜닝

그 아래 방법들은 추천하지 않는다고 한다.

Addressing Distribution Shift

  1. Test-validation set 에러를 분석해보고 더 많은 학습 데이터를 수집한다
  2. 마찬가지로 에러를 분석해보고 더 많은 데이터를 인위적으로 넣는다.
  3. Domain adaptation techniques를 적용해본다

에러 분석이란, 위 처럼 어떤 데이터를 모델이 틀리는가 확인해보는 것이다. 위의 보행자 예측 모델이 잘못 예측한 예시를 보면 크게 3가지로 나뉜다.

  1. 사람이 잘 안보임
  2. 화면에 반사된 내부가 비침
  3. 야간 사진

1번은 그냥 학습 데이터를 더 모으는 것도 좋지만, 2번에서는 이를 분석해보고 우선순위를 정해서 인위적으로 에러를 줄이기 위한 데이터를 수집하는 것이다. 그마저도 안된다면 domain adaptation techniques를 적용해본다.

Domain Adaptation

쉽게말해 pretraining이다. 라벨링된 데이터를 얻기는 힘들지만 라벨링이 안된 데이터를 많이 모으기는 쉬울때 사용한다.

지도학습에서는 전이학습과 파인튜닝을 쓰면 되고, 비지도학습에서는 Correlation Alignment 등의 방법이 있다.

Rebalancing Dataset

만약 test-validation set과 test set의 차이가 크다면, test validation set에 오버피팅된 것이다. 이는 하이퍼파라미터 튜닝을 너무 많이하거나, validation set이 너무 작을 경우 발생한다. test validation 데이터를 다시 수집해야한다.

튜닝

모델 성능이 어느정도 만족스러워졌다면, 이제 할 것은 튜닝이다. 하지만 하이퍼파라미터가 너무 많다보니 어렵다.

때문에 성능에 영향을 미치는 파라미터를 살펴봐야한다.

이는 모델에 따라 달라지고, 보통은 위 사진에 오른쪽에 정리된 내용과 비슷하다. Learning Rate가 중요하다는 것에 놀람. 이제 튜닝하는 방법들에 대해 알아보자.

하나는 수동 최적화인데, 알고리즘을 잘 이해하는 숙련된 실무자라면, 가장 적은 계산으로 좋은 결과를 얻을 수 있다. 깊은 이해도를 갖기 어려울 수 있고, 시간이 많이 소모된다.

그 다음은 Grid Search다. 구현하기 쉽고 좋은 결과를 얻을 수도 있다. 하지만 많은 계산을 필요로해서 크게 효과적이지는 않다. 좋은 하이퍼파라미터 범위에 대한 지식도 있어야한다.

그 다음은 무작위 검색인데, 구현하기는 쉽고 자주 Grid Search보다 좋은 결과를 낸다. 하지만 결과를 해석하기 어렵고, 마찬가지로 좋은 파라미터값에 대한 사전지식을 갖고 그 범위내에서 무작위 값을 산출해야한다.

Coarse-to-fine은 먼저 무작위 검색을 한 뒤, 결과물이 좋은 범위로 좁혀서 다시 그곳에서 검색을 하고,, 이를 반복하는 검색 방법이다. 실제로 가장 많이 사용되는 방법이다. 가끔은 수동 절차가 필요하다.

그 다음에는 좋은 하이퍼파라미터를 예측하는 확률적 모델을 만드는 방법이다. 보통은 가장 효과적이지만 구현하기가 어렵다고한다. 이 부분에 대한 더 자세한 내용은 infrastructure & tooling 섹션에서 다뤘으니 패스.

Conclusion

  • 많은 에러의 원인들이 DL 디버깅을 어렵게 만든다.
  • 버그없는 모델의 학습을 위해, 우리는 모델구현을 반복적인 프로세스로 대해야 한다.
  • 이런 과정들이 프로세스를 쉽게, 버그를 최대한 빠르게 잡도록 도와줄 것이다.

다시 정리하면

--

--

김희규

나는 최고의 선수다. 나를 최고라고 믿지 않는 사람은 최고가 될 수 없다.