Paper review

[Review] How to avoid machine learning pitfalls: a guide for academic researchers

Jonghyuk Baek 2023. 3. 12. 23:19

paper link: https://arxiv.org/pdf/2108.02497.pdf

 

Introduction

이 페이퍼는 머신러닝을 이용해 문제를 풀 때 흔하게 저지를 수 있는 실수와 어떻게 하면 그것을 피할 수 있을 지에 대해 소개하고 있다. 머신 러닝 프로세스를 크게 다섯 가지의 단계로 나누어 각 단계별로 설명하게 되는데, 각 단계를 미리 소개하자면 다음과 같다.

 

  • 모델 빌드 전에 해야 할 것
  • 모델을 안정적으로 빌드하는 방법
  • 모델을 안정적으로 평가하는 방법
  • 모델을 공평하게 비교하는 방법
  • 결과를 리포트하는 방법

 

본 글에서는 제시된 내용 전부를 훑기보다는, 개인적으로 몇 가지만 골라 간단하게 소개하고자 한다. 아카데믹 관점보다는 머신러닝 프로젝트를 성공적으로 이끌기 위한 방법 위주로 내용을 선정하고 해석을 덧붙였다.

 


 

0. 모델 빌드 전에 해야 할 것

데이터를 수집하자마자 곧바로 모델을 학습 시키려 들기 보다는, 프로젝트가 어떤 목적을 가지고 있으며 데이터는 해당 목적을 위해 적합한지, 필드에서 기존에 어떤 문제가 이미 해결되어 있는지 파악하는 것이 중요하다.

 

데이터를 이해하는 시간을 가지자

데이터가 믿을 만한 출처를 가지고 있는지, 적절한 방법론을 통해 수집되었는지, 좋은 품질을 가지고 있는 지 사전에 확인해야 좋은 결과를 얻을 수 있다. 만약 어떤 페이퍼를 통해 공개된 데이터라면, 해당 페이퍼가 믿을 만한 곳에 퍼블리시 되었는지, 저자들이 언급한 한계점이나 주의사항이 있는 지 확인하는 것도 좋다.

단순히 많은 횟수 인용되었다고 해서 좋은 데이터일 것이라 단언할 수도 없다. 단지 접근성이 좋은 데이터셋이였을 수도 있으며, 널리 사용된 데이터셋이라 해서 단점이 없는 것은 아니다.

데이터가 좋지 않으면 학습된 모델 또한 좋은 성능을 보이지는 못 하기 때문에 (garbage in garbage out), 모델을 학습 시키기 전에 반드시 데이터가 하려는 일에 적합한지, 어떤 특성을 가지고 있는 지 미리 시간을 들여야 한다.

 

모든 데이터를 면밀히 보지 말자

데이터를 보다 보면 어떠한 패턴을 발견하거나 어떤 직관을 가지게 되고, 이것을 모델 설계에 반영하는 경우가 많다. 괜찮은 접근이지만, 만약 테스트 데이터를 보고 뭔가를 떠올려 이를 모델에 반영하기 시작하면 문제가 생긴다.

학습 셋이 아닌 테스트 셋에서 발견한 정보를 통한 가정은 추후 검증이 불가능하며 (untestable), 결과적으로는 모델의 일반성을 떨어트릴 수 있다.

 

도메인 전문가와 이야기하자

도메인 전문가는 어떤 문제가 실제로 중요한 문제인지, 어떤 피처가 문제를 푸는 데 유의미한지 알고 있다. 프로젝트 시작 단계에서 도메인 전문가의 도움을 받아 데이터를 이해하고, 추론에 도움이 될 만한 피처를 미리 골라내는 것이 도움이 될 수 있다.

 

모델이 어떻게 배포될 지 생각하자

머신러닝 모델의 최종적인 목표는 실제 세계의 문제를 풀기 위해 배포되는 것일 것이다. 그렇다면, 모델을 만들기 전에 모델을 어떻게 배포할 지에 대해서 한 번쯤은 생각해 봐야 한다.

만약 센서 블록이나 로봇처럼 엣지 컴퓨팅을 해야 하는 상황이라면 애초에 모델의 복잡도를 크게 가져갈 수 없을 것이다. 혹은 데이터가 수집되는 속도가 빨라 데이터 인스턴스 추론 한 번에 허용되는 시간이 수 밀리세컨드 정도 수준일 수도 있다.

 

1. 모델을 안정적으로 빌드하는 방법

이 단락에서는 모델을 설계, 학습할 때 고려해야 할 만한 사항들을 보여준다.

 

테스트 셋이 학습 프로세스에 영향을 주지 않도록 하자

 

 

테스트 셋의 정보가 모델의 선정, 학습 과정, 혹은 학습 환경 설정에 관여하게 되면 모델의 일반성을 떨어트릴 수 있다. 실제 문제를 풀기 위해 배포되는 순간 모델 성능의 저하를 느끼게 될 것이다.

사실 테스트 셋을 모델 빌드 과정에서 쓰지 않아야 한다는 것은 당연하게 받아들여지지만, 의외로 쉽게 테스트 셋이 빌드 과정에 영향을 미칠 수도 있다.

 

 

예를 들어 데이터 정규화 (normalization) 에 쓰일 평균, 분산 값을 학습 셋이 아닌 데이터셋 전체에 대해서 구한다던가, 학습 /  테스트 셋을 분리하기 이전에 피처 선정을 한다던지 (PCA 등을 통한 dimensionality reduction 또한 포함한다), 혹은 데이터 augmentation 을 테스트 데이터 분리 이전에 수행한다던지.. 실수를 범할 만한 구석은 도처에 널려 있다.

이를 피하기 위해서는 데이터를 처음 수집하자 마자 곧바로 테스트 셋을 분리하고 (처음부터 나누어져 있지 않다면), 이를 모델 성능 측정 이외에는 절대로 쓰지 않도록 해야 한다.

 

딥러닝이 최선의 접근일 것이라 단언하지 말자

딥러닝 네트워크를 이용한 모델이 모든 문제에 대한 최선의 해답은 아닐 수 있다. 문제에 따라서 꽤 옛날 방식의 머신러닝 기법인 랜덤 포레스트, SVM, 클러스터링 등이 더 나을 때도 있다. 특히 캐글 등에서는 decision tree 를 기반으로 한 부스팅 기법인 Extereme gradient boosting (XGB) 이 한참 강세를 보이기도 했었다 (참고). 

만약 도메인 지식을 이용해 문제를 풀기 위한 규칙이 사실은 꽤 간단하다는 것을 직접 파악할 수 있거나, 모델이 설명 가능한 방향으로 추론을 내려야 하는 상황이라면 고전 머신러닝 기반의 접근도 나쁘지 않다.

개인적으로는 딥러닝 모델을 더 이상 추가하기 곤란한 상황이거나, 문제가 그렇게 복잡해 보이지 않는 경우엔 학습이 필요하지 않은 고전 비전 기법 또는 간단한 고전 머신러닝 기법을 시도해 보는 것이 꽤 도움이 되었다. 

 

가짜 상관관계 학습을 피하자

가짜 상관관계 (Spurious correlations) 는 어떤 피처가 타겟 변수와의 correlation은 가지고 있지만, 사실은 아무런 의미적 의미를 가지고 있지는 않은 경우를 뜻한다.

예를 들어 이미지 내에 자동차가 존재하는 지 구분해 내야 하는 태스크에서, 자동차 사진들이 다른 자동차가 없는 사진들에 비해 유난히 다양한 날씨 환경에서 촬영이 되었다면 모델은 자동차의 존재가 아닌 사진 상단의 날씨 관련 이미지 피처를 이용해 결정을 내리기 시작할 것이다.

모델이 복잡해질 수록 이러한 가짜 상관관계를 캐치해 오버핏 되어 버리는 경우를 쉽게 목격할 수 있을 것이다. 본인은 이런 현상을 모델이 잔머리 굴린다 라고 부르고 있다...

이러한 문제를 방지하기 위해선 데이터 augmentation을 잘 사용하거나, 데이터 처리 과정에서 모델이 정답 구분에 사용할 만한 의도치 않은 추가적인 정보가 제공되고 있지 않은 지 (이미지 크롭 양상이나 정규화 양상 등) 면밀하게 파악해야 한다. 모델이 이상하게 성능이 좋아진다면 후자의 상황을 의심해 볼 수 있다.

 

2. 모델을 안정적으로 평가하는 방법

이 단락에서는 모델을 공정하고 정확하게 평가해, 유의미한 결론을 도출해 내기 위한 방법론들을 소개한다.

 

적절한 테스트 셋을 사용하자

ML 모델의 성능을 측정하기 위해서는 항상 테스트 셋이 필요하다. 모델이 학습 셋에 대해 잘 작동하는지는, 모델 capacity가 충분하다면 아무런 의미를 가지지 못 한다. 사실상 학습 셋을 전부 외워 버렸을 수도 있으며 학습 셋에 대한 평가로는 모델의 일반화 성능이 전혀 드러나지 않는다.

테스트 셋은 학습 셋과 절대 겹치지 말아야 하며, 큰 데이터 모집단을 잘 표현할 수 있어야 한다. 테스트 셋에 특정 경향의 데이터가 유난히 몰려 있다면, 다른 특성을 가지는 실제 데이터에 대해서는 어떻게 작동할 지 테스트 과정에서 전혀 드러나지 않게 된다.

 

데이터 분리 이전에 augmentation 을 하지 말자

데이터 augmentation 기법은 테스트 데이터가 아닌, 학습 데이터에 대해서만 가해져야 한다. 모델의 성능이 원본 데이터셋이 아닌, augment 된 데이터셋에 대해 오버핏이 된 경우, 테스트 셋에 대해서도 augment가 가해져 있는 경우 테스트 과정에서 해당 문제가 드러나지 않을 수 있다.

또한, 만약 데이터셋을 augmentation 을 통해 크게 불려 놓은 상태에서 데이터 split을 진행하게 된다면, 테스트 데이터의 대부분이 이미 학습 셋에 존재하는 데이터의 다른 augment 버전으로 이루어질 가능성이 있다. 이렇게 되면 학습 셋과 테스트 셋이 상당히 많은 정보를 공유하게 되며 테스트 셋은 그 기능을 상실하게 된다.

앞서 테스트 셋이 학습 프로세스에 영향을 주지 않도록 하자 에서 언급했듯이, 데이터를 처음 얻게 되면 곧바로 데이터 split 부터 진행하는 것이 좋다.

 

Validation 셋을 사용하자

 

 

모델 성능을 측정하고 그 성능을 바탕으로 다음 모델 개선을 반복하는 경우, 테스트 셋을 이 과정에 직접 사용하게 되면 모델 설계 자체가 테스트 셋에 오버핏 되어버릴 수 있다.

Validation 셋을 학습 데이터셋에서 따로 나누어 이를 학습 과정을 세세하게 tweak 하는 데에 사용하고, 테스트 셋은 최종 성능을 리포트 하는 데에 사용해야 한다. 학습 시 early stopping 시점을 결정할 때에도 마찬가지로 별도의 validation 셋을 사용해야 한다.

 

클래스가 불균형한 경우 accuracy 를 쓰지 말자

Accuracy (정확도) 는 사용하기 간편하고 직관적이지만, 데이터셋 내에 분류 클래스가 균일하게 존재하지 않는 경우엔 잘못된 측정 결과를 보여줄 수 있다. 예를 들어, 90%의 데이터 라벨이 한 가지의 클래스에 몰려 있다면, 모델은 단순히 모든 데이터 입력에 대해 해당 클래스 출력을 내는 식으로 0.9의 꽤 높은 accuracy를 얻어낼 수 있다. 하지만 이런 모델은 아무런 쓸모가 없을 것이다.

클래스 비중이 불균형하다면, F1-Score, Balanced accuracy 와 같이 클래스 불균형 문제를 해결한 다른 메트릭을 고려해 봐야 한다.

 

3. 모델을 공평하게 비교하는 방법

서로 다른 모델의 성능을 비교하기 위해서는 각 모델을 동일한 맥락에서, 다양한 관점으로 적절한 통계 테스트를 사용해 조심스럽게 비교해야 한다.

 

더 높은 숫자가 더 나은 모델을 의미 하지는 않는다

단순히 정확도 수치가 기존에 리포트 된 수치인 0.94에서 0.95로 증가했다고 두 번째 모델이 더 낫다고 단언할 수는 없다. 예를 들어, 학습과 테스트에 사용된 데이터셋 구성에 조금이라도 차이가 있었다면, 해당 성능 차이는 이 사소한 데이터셋 차이에 의해 발생했을 가능성이 있다.

이외에도, 특정 모델에 대해서만 유난히 더 많은 하이퍼파라미터 서치를 수행했다던가, 혹은 인퍼런스 시 더 많은 정보를 제공해 주고 있다던가 하는 식으로 모델의 성능을 불공정하게 평가하기 쉽다. 중요한 것은, 100% 완벽할 수는 없겠지만 각각의 모델을 같은 출발선에서, 같은 조건 하에서 평가해 그 성능을 비교해야 한다는 것이다.

 

커뮤니티 벤치마크 결과를 항상 믿지는 말자

대다수의 태스크에 대해선 어떤 잘 알려진 벤치마크 데이터셋이 존재하기 마련이고, 해당 데이터셋에 대한 다양한 모델의 벤치마크 결과가 잘 리포트 되어 있을 것이다 (예시). 모두가 동일한 학습, 테스트 데이터셋을 사용해 성능을 평가하기 때문에 공개적인 벤치마크 결과는 모델의 성능을 굉장히 투명하게 알려주는 지표라고 볼 수 있지만, 문제는 벤치마크 셋의 테스트 셋은 언제든 열어볼 수 있게 공개되어 있는 상태라는 것이다.

물론 해당 테스트 셋을 학습에 사용했을 가능성은 낮고, 모두가 동일한 학습 셋을 모델을 학습시켰을 것이지만, 모델의 최적화 과정에 테스트 셋에 대한 평가 결과가 얼마나 반영되었을 지는 알 수 가 없다. 즉, 최상의 모델은 단순히 테스트 셋에 대해 오버핏 되어 있는 상태일 가능성이 있다는 말이다.

이 글을 읽는 사람 중 몇몇은 분명 실제 태스크를 풀기 위해 커뮤니티 벤치마크 테이블의 탑 랭크 모델을 적용했지만, 그다지 좋은 성능을 내지 못 했던 경험이 있을 것이다. 이런 현상은 다양한 벤치마크 셋을 가지고 있지 못 한 태스크일 수록 더욱 두드러진다.

 

4. 결과를 리포트하는 방법

ML 모델을 적절하게 활용하기 위해서는 모델이 어떤 것을 할 수 있고, 어떤 것을 할 수 없는 지 명확하게 리포트 해야 한다. 어떤 모델이 다른 모델을 모든 면에서 압도하는 것은 쉽지 않은 일이며, 결국 우리는 여러 선택지를 두고 어떤 상황에서 어떤 모델을 사용해야 할 지 선택해야 하기 때문이다.

 

모델의 성능을 다양한 방법으로 리포트 하자

모델 간의 성능을 더 정확히 비교하기 위해선, 다양한 데이터셋을 이용해 보는 것이 도움이 된다. 이 방법을 통해 모델이 특정 데이터셋에 크게 오버핏 되어있지 않았는지 검증이 가능하며, 해당 태스크에 대한 모델의 성능을 더 명확하게 밝힐 수 있다.

또한 다양한 메트릭을 사용해 다양한 성능 관점에서 모델의 성능을 비교해 볼 수도 있다. 특히, 각각의 도메인 별로 중요하게 여겨지는 메트릭들이 따로 존재하기 때문에 주로 어떤 메트릭 셋이 쓰이는 지 잘 알아보는 것이 중요하다.

 

모델의 성능을 과대평가 하지 말자

모델이 어떤 한 데이터셋에 대해 잘 작동한다고 해서, 유사한 다른 데이터셋에 대해 다같이 잘 작동할 것이라는 보장은 없다. 여러 데이터셋에 대한 검증을 끝마쳤다고 해도, 데이터셋 간의 본질적인 유사성, 데이터 품질의 문제, 실제 데이터와의 차이 (sampling error, bias) 등 모델이 실제 환경에서는 잘 작동하지 않을 여지는 어디에나 있다.

모든 요인들을 배제한 상태에서 모델이 잘 작동할 지 예상하는 것은 불가능에 가까울 테지만, 중요한 것은 모델의 성능을 너무 낙관적으로 보거나 결과를 과대포장 하지 말고, 성능 측정 과정에서 한계점을 발견했다면 이를 명확히 리포트 하는 것일 것이다.

 

당신의 모델을 다시 들여다 보자

단순히 학습된 모델이 좋은 성능을 냈다고 작업을 마무리 하기보단, 모델이 어떤 것을 학습했고 어떤 과정을 통해 최종 결론을 내리고 있는 지 확인해 보자. CAM (Class activation map) 과 같은 XAI (Explainable AI) 테크닉을 사용한다던가, 아니면 convolution layer 직후의 feature map을 들여다 보는 등 모델의 동작을 분석하는 과정에서 의도치 않은 동작을 발견할 가능성도 있다.

예를 들어 모델이 가짜 상관관계를 배우고 있다던지 하는 학습 자체의 문제 혹은 데이터 전처리 과정에서 라벨 정보가 인풋에 유입되고 있다던지 하는 단순하지만 치명적인 버그를 발견할 수도 있다. 모델을 다 선정해 놓고 배포까지 한 이후에 이런 문제를 발견하는 것 보다는, 모델 결과를 리포트 하는 과정에서 당신이 설계한 모델이 의도대로 작동하는 지 확인도 해볼 겸 한번 검토해 보는 편이 좋을 것이다.

 


아래는 참고할 만한 페이지들이다.

 

References

Kaggle tutorial - XGBoost

https://www.kaggle.com/code/dansbecker/xgboost

paperswithcode - State of the Art (벤치마크 결과 제공 사이트)

https://paperswithcode.com/sota

 

 

 

반응형