체계적인 실험 관리 #1. AI 모델의 성능을 높이는 첫걸음
![](https://makinarocks.shoplic.cloud/wp-content/uploads/2024/05/systematic-experiment-management-ai-model-performance-1024x576.jpg)
체계적인 실험 관리 #1. AI 모델의 성능을 높이는 첫걸음
안녕하세요. 마키나락스의 AI 엔지니어 김석기, 장종하입니다! 마키나락스는 여러 산업 현장에서 AI로 해결하고 싶은 문제를 파악하고, 문제를 정의한 뒤에 AI 모델을 학습하여 산업 현장을 지능화하고 있습니다. 여러 AI 프로젝트를 수행하면서 실험 관리의 중요성을 느꼈고, 에너지 기업과 성분 예측 AI 프로젝트를 수행하며 실험 관리 방식을 체계화했는데요. 이런 경험을 기반으로 마키나락스 AI 플랫폼 Runway에도 실험 관리 기능을 구현할 수 있었습니다. 체계적인 실험 관리를 위해 마키나락스가 경험한 일련의 과정을 '체계적인 실험관리' 시리즈로 준비했습니다. 이번 포스팅에서는 AI 프로젝트를 진행하면서 체계화한 실험 관리 방식을 소개합니다.
실험 관리가 필요한 이유
AI 프로젝트를 진행하면서 모델을 개발하게 되는데, 프로젝트의 핵심은 모델의 성능이라고 할 수 있어요. 프로젝트를 진행하면서 모델의 성능을 개선해 나가려면, 모델과 모델의 성능을 쉽게 비교할 수 있는 형태로 실험을 할 수 있어야 해요. 특히 저희는 모델 개발을 할 때 여러 팀원이 각자 다양한 방법들을 시도해 보면서 실험을 진행하는데, 같은 조건에서 방법론을 다르게해 실험을 진행한 것인지 분명해야 방법론의 성능을 비교할 수 있을 거예요.
만약 A 방법론을 가지고 실험한 팀원이 많은 데이터를 가지고 개발한 모델이 B 방법론을 가지고 실험한 팀원이 적은 데이터를 가지고 개발한 모델보다 성능이 높게 나온 경우, A 방법론이 B 방법론보다 좋아서 성능이 높게 나왔다고 말하기 어려울 것이에요.
서로 다른 팀원 사이뿐 아니라, 본인이 한 실험 중에서도 혼동의 가능성은 존재해요. 프로젝트를 진행하면서 고객사와 협업을 하다 보면, 학습 데이터의 교체가 불가피한 상황이 발생하는데 이에 따라 서로 다른 두 실험의 모델 성능을 제대로 비교하기 어려운 경우가 생기게 돼요. 예를 들면, 1개월 전에 했던 실험이 있는데 갑작스러운 고객사의 요청으로 학습 데이터가 바뀌는 경우, 1개월 전에 했던 실험과 성능을 비교하려면 예전 데이터가 어떤 데이터인지, 어떻게 가공되었는지에 대한 기록이 어떤 형태로든 남아 있어야 합니다. 기록이 되어 있지 않거나 재현이 너무 어려운 경우에는 새로운 학습 데이터에 대해 여러 방법론의 실험들을 다시 한다고 했을 때 예전 실험들과의 성능 비교는 어려워지겠죠.
이처럼 AI 프로젝트를 잘하기 위해서는 실험 관리 체계가 필수적이라고 할 수 있어요. 실험 관리가 필요한 핵심적인 이유를 요약해 보면 다음과 같아요.
- 고객사에 좋은 성능의 모델을 제공하기 위해 다수의 모델 간 성능 비교가 가능해야 해요.
- 시나리오 또는 테스트셋 구성 방법에 따라 성능이 좋은 모델이 다를 수 있어요.
- 좋은 성능의 모델이 개발되었을 때 해당 모델의 학습과 성능 평가를 재현할 수 있어야 해요.
- 서로 다른 팀원이 같은 방법으로 실험을 진행했을 때 같은 결과가 나타나야 해요.
이러한 필요성을 해결하기 위해 프로젝트를 수행하면서 실험 관리에 대한 원칙을 세우고 효율적으로 실험들을 관리하는 방법을 체계화했어요. 지금부터 저희가 어떤 방법으로 실험 관리 체계를 만들었는지 소개해 드릴게요.
실험 관리 체계화
모델을 개발하는 AI 프로젝트를 진행하는 데 있어 효율적인 방식으로 실험 관리를 하기 위해 저희는 실험 관리 체계를 크게 3가지 영역으로 구성하였습니다.
- Data Version 관리
- Data Version을 관리하면 모델 성능을 비교할 수 있는 실험들끼리만 모아서 모델 성능을 비교할 수 있어요.
- Source Code Version 관리
- Source Code Version을 관리하면 각 실험이 어떤 방법론을 사용해서 수행된 실험들인지 코드를 통해 구분하기 쉬워요.
- 재현하고자 하는 실험이 있을 때 해당 버전으로 이동하여 실행해 보면 되므로 재현성 측면에서도 좋아요.
- MLflow Logging 관리
- 수행된 실험들의 결과를 기록하는 tool로 MLflow를 활용했어요.
- 실험의 결과들을 통해 모델의 성능을 개선하기 위한 인사이트를 발굴할 가능성을 높이기 위해 각 실험들을 비교하기 좋은 형태로 관리할 방안을 찾고자 했어요.
이러한 데이터 버전 업데이트 정책 아래에 실험에 사용된 데이터 버전이 각각 v0.X.Y 와 v0.X.Z 인 경우, 두 실험의 성능을 비교할 수 있음을 쉽게 파악할 수 있어요. Test Set이 동일하기 때문이에요.
Source Code Version 관리
모델을 개발하는 프로젝트의 경우에, 모델 성능을 높이기 위해 했던 여러 시도들을 기록해야 할 필요가 있고, 시행착오를 겪으면서 프로젝트의 방향성이 바뀌기도 해요. 이러한 과정에서 소스 코드가 계속 변경되는데, 소스 코드를 제대로 관리하지 않으면 실험을 재현하지 못한다거나 내가 시도했던 방법론을 다른 팀원이 시도하려 할 때 다시 코드를 짜야 하는 비효율이 발생하기도 하겠죠.
저희는 실험과 소스 코드를 일대일로 대응하는 일에 초점을 두었어요. 소스 코드 버전은 Git Tag를 이용해서 관리하고요. 자세한 방법은 다음과 같아요.
1.Pull Request Merge
새로운 형태의 실험을 하기 위해 팀원이 해당 실험을 수행할 수 있는 코드를 짜서 Pull Request를 날리면, 나머지 팀원들의 review 후에 해당 PR을 merge해요.
2.Git Tag Release
Merge하는 브랜치에서 새로운 release를 생성합니다. 이때, 새로운 Git Tag를 만들어서 release를 생성해요. Release Note에는 이전 소스 코드 버전과 비교해서 어떤 실험을 추가로 수행할 수 있도록 업데이트되었는지, 또는 실험 결과를 더 잘 볼 수 있도록 새롭게 추가된 기능은 무엇인지 등을 간단하게 적어요.
3.실험 수행 시 Git Tag를 함께 logging
실험을 수행할 때 Git Tag를 MLflow에 함께 logging 하도록 했어요. 이를 통해 각 실험이 어떤 소스 코드 버전을 통해 수행된 것인지 쉽게 알 수 있겠죠. 저희 프로젝트에서는 각 실험의 소스 코드 버전을 MLflow Run에서
src_version
이라는 MLflow Tag로 logging 했어요.각 소스 코드 버전은 다음과 같이 Git Tag로 생성되어 Release됩니다.
![소스 코드 버전 v0.5.1 Release Note](http://makinarocks.shoplic.cloud/wp-content/uploads/2024/05/1.-소스-코드-버전-v0.5.1-Release-Note.jpg)
소스 코드 버전 v0.5.1 Release Note
MLflow 화면에서는 소스 코드 버전을 MLflow Tag로 남겨놓았기 때문에 Columns에서 체크하면 각 실험이 어떤 소스 코드 버전으로 수행된 실험인지 한눈에 확인할 수 있어요.
![TAME-Data-v0.4.0 Experiment 화면의 일부](http://makinarocks.shoplic.cloud/wp-content/uploads/2024/05/2.-TAME-Data-v0.4.0-Experiment-화면의-일부.jpg)
TAME-Data-v0.4.0 Experiment 화면의 일부
MLflow를 활용해서 실험을 관리하는 경우, MLflow에 실험을 로깅할 때 자동으로 Git Commit ID가 남아요. 그럼에도 Git Tag를 이용해서 소스 코드 버전을 지정하고 로깅하면 다음과 같은 장점들이 있어요.
1. 실험 목록에서 여러 실험들을 확인할 때 같은 소스 코드 버전으로 수행된 실험들을 한눈에 알 수 있어요.
2. 여러 실험들의 시간적 순서를 파악하기 용이해요.
Git Commit ID의 경우 hash 값으로 알아보기 어려운 random한 문자열 형태이기 때문에 두 개의 실험을 비교하는 경우에 어떤 실험이 먼저 수행된 것인지 알기가 어려워요. 물론 직접 커밋으로 이동해서 코드를 비교해 보면 알 수도 있지만, 쉽게 알기는 어려울 거예요. Git Tag를 사용하면 버전의 숫자를 통해 여러 실험의 선후관계를 쉽게 알 수 있겠죠. 모델 개발이 끝난 후에 같은 형태의 실험만을 계속 수행하는 프로젝트의 경우에는 실험의 시간적 순서가 의미 없을 수 있지만, 모델을 개발하는 프로젝트의 경우에는 실험의 시간적 순서가 중요하게 작용할 수 있으므로 장점이라고 할 수 있어요.
3. Release Note를 활용하면 각 소스 코드 버전에 대한 설명이 자연스럽게 기록될 수 있어요.
프로젝트를 하면서 여러 실험을 하게 되면 코드 버전이 매우 많아지게 되는데, 코드 관점에서 해당 실험이 어떤 방법론에 대한 것인지 알 수 있어요. 또한 프로젝트의 추적성 측면에서 보면, 해당 버전이 프로젝트의 어느 정도 진척도에 와 있는 버전인지를 간접적으로 유추할 수 있는 효과가 있어요.
MLflow Logging 관리
앞서 저희는 MLflow라는 오픈소스를 이용하고 있다고 말씀드렸는데요. 적게는 수십번에서 많게는 수만 번의 실험이 이뤄지는 AI 프로젝트에서 저희가 MLflow를 활용해서 어떻게 실험 관리를 하는지 말씀드릴게요.
MLflow에 실험들을 기록하는 데 있어 가장 중요하게 생각했던 것은 Description을 잘 기록하는 것이에요. 예시를 통해 살펴볼게요.
먼저 성능을 비교하기 쉽도록 데이터 버전별로 MLflow Experiments를 만들었어요. 각 데이터 버전에 대한 MLflow Experiment의 Description 부분에 데이터 버전과 관련된 설명을 간략하게 작성해요.
다음은 하나의 MLflow Experiment 화면 예시입니다.
![Data Version v0.4.0의 MLflow 화면 예시](http://makinarocks.shoplic.cloud/wp-content/uploads/2024/05/3.-Data-Version-v0.4.0의-MLflow-화면-예시-2.jpg)
Data Version v0.4.0의 MLflow 화면 예시
Data Version v0.4.0의 MLflow 화면 Description 부분에는 실험 개요, 데이터 개요, 호환 가능한 소스 코드 버전을 작성하도록 했어요.
- 실험 개요
- 해당 데이터 버전의 특이 사항을 간략하게 요약하여 작성해요.
- Notion Page 링크를 함께 작성하여 해당 데이터 버전이 왜 정의되었고 어떤 실험을 진행하려고 한 것인지 등을 쉽게 파악할 수 있도록 해요.
- 데이터 개요
- 데이터 샘플 수 정보와 해당 데이터 버전의 Train/Test/Val Split에 대한 정보를 작성해요.
- 호환 가능한 소스 코드 버전
- 프로젝트가 진행되면서 필요한 기능들을 추가하거나 제거하기 때문에 각 데이터 버전마다 호환 가능한 소스 코드 버전이 다르게 되고, 따라서 실험의 재현성을 위해 호환 가능한 소스 코드 버전을 나열하여 빠르게 파악할 수 있도록 했어요.
이렇게 Description을 잘 적기만 한다면 실험 관리가 완벽하게 될까요? 모델을 개발하면서 소스 코드는 계속해서 버전 업데이트가 될 것이고, 데이터 버전도 여러 개가 되면 내가 찾고 싶은 실험을 찾기 위해 많은 시간이 들 수도 있습니다. 이를 해결하려고 고민을 하다 보니, 애초에 실험을 기록할 때 실험의 목적별로 공간을 달리하여 기록하면 나중에 찾기 쉽지 않을까라는 생각을 하게 됐어요.
다음과 같이 실험의 목적에 따라 실험 공간을 만들어 관리했어요.
실험의 목적에 따른 실험 공간 분리
[Type 1] 프로젝트의 진행 상황 리더보드
프로젝트의 추적성을 위한 기록용 공간으로 프로젝트의 진행 과정을 보여줄 수 있는 실험들을 기록하는 공간이에요. 프로젝트가 진행되면서 데이터 버전이 바뀜에 따라 각 버전에 대해 성능이 높다고 판단되거나 유의미한 실험이라고 생각되는 실험들을 기록하여 프로젝트 전체를 한눈에 파악할 수 있어요.
[Type 2] 데이터 버전 실험 공간
주 실험 공간으로, 데이터 버전에 따라 모든 실험을 기록하는 공간이에요. 데이터 버전 업데이트 정책을 세울 때 실험 간 모델 성능을 비교하는 것에 초점을 맞췄기 때문에 데이터 버전별로 실험 공간을 만들었어요. 모델 학습에 사용된 데이터 정보, 모델 파라미터값 등을 함께 기록하여 실험의 재현성을 확보했어요.
[Type 3] 테스트 로깅을 위한 실험 공간
테스트 로깅을 위한 실험 공간은 일종의 메모장 같은 공간이에요. 소스 코드를 개발하면서 실험 기록이 의도대로 잘 되는지, 재현성이 확보되는지 확인하는 용도로 사용했습니다. 메모장과 같은 공간이기 때문에 임시로 알아볼 수 있는 네이밍(개발 중인 브랜치 이름 등)으로 자유롭게 기록합니다. 이 공간에서 테스트 로깅을 한 후에 해당 실험에 대해 잘 동작하는 것을 확인한 후에는 주 실험 공간인 ‘[Type 2] 데이터 버전 실험 공간’에 다시 기록해야 합니다.
[Type 4] 하이퍼파라미터 튜닝 실험 공간
이 공간에는 주 실험 공간에 기록되는 실험들에 대해 수행한 하이퍼파라미터 튜닝 실험들을 전부 기록했어요. 주 실험 공간과 분리한 이유는 주 실험 공간에서는 서로 다른 방법론 또는 서로 다른 모델이 적용된 실험들의 성능을 비교하는 것이 목적이기 때문이에요. 하이퍼파라미터를 튜닝하는 실험들이 주 실험 공간에 함께 기록되어 로그가 쌓이게 되면 서로 다른 방법론끼리의 성능 비교가 어려워지겠죠. 테스트 로깅 공간과 마찬가지로 하이퍼파라미터 튜닝 실험 공간에서도 한 방법론에 대해 하이퍼파라미터 튜닝이 어느 정도 된 것 같으면 주 실험 공간에 해당 하이퍼파라미터를 적용해서 다시 기록했어요. 하이퍼파라미터 탐색 기록을 굳이 기록하는 이유는 무엇일까요? 최적의 하이퍼파라미터 조합이 나오면 그 조합만 테스트하면 되지 않을까라고 생각할 수도 있어요. 하지만 하이퍼파라미터를 탐색한 기록들이 쌓이게 되면 하이퍼파라미터들의 경향성을 분석할 수 있고, 이를 통해 필요한 search space를 좁혀나갈 수 있어 더욱 좋은 성능을 낼 수 있는 하이퍼파라미터를 찾을 수 있는 가능성을 높일 수 있어요. 예시를 통해 볼게요. 다음은 Catboost 모델의 하이퍼파라미터 중 하나인 depth
의 경향을 분석한 그래프예요.
![Catboost 모델의 depth 하이퍼파라미터의 경향 분석 그래프](http://makinarocks.shoplic.cloud/wp-content/uploads/2024/05/5.-Catboost-모델의-depth-하이퍼파라미터의-경향-분석-그래프.jpg)
Catboost 모델의 depth 하이퍼파라미터의 경향 분석 그래프
depth
의 search space를 2~12로 설정하여 탐색을 진행했을 때 위와 같은 결과가 나타났는데요. 결과를 보면 depth
와 validation set의 pearson r이 양의 상관관계를 보이는 것을 확인할 수 있어요. 작은 depth
값보다는 큰 값 쪽에서 탐색하면 더 좋은 성능을 기대할 수 있을 것이라는 분석을 할 수 있겠죠. 이에 따라 search space를 8~11에서 다시 탐색해 본다는 전략을 세울 수 있게 돼요.
이처럼 실험 목적에 따라 실험 공간을 분리하면 찾고자 하는 실험이 생겼을 때 추적하기가 쉬워져요. 하이퍼파라미터 튜닝 실험 공간의 경우 모델 성능을 끌어올리기 위한 인사이트를 발견하는 데 도움도 되고요.
실험 관리 체계화 후기
AI 프로젝트를 하면서 실험 관리의 필요성을 느껴 실험 관리를 체계화하는 작업을 해보았는데요. 저희가 실험 관리를 체계화하면서, 그리고 이를 사용하여 프로젝트를 진행하면서 느꼈던 점을 정리해 볼게요.
좋았던 점: 원활한 협업과 효율적인 실험 방법론 비교
실험 관리에 대한 체계가 잡히니 전반적으로 협업이 잘 되는 느낌을 받았어요. 예를 들면, 다른 팀원이 제게 “A 방법론으로 실험해 봤는데 성능이 이렇게 나왔어요”라고 한 뒤에 해당 실험의 MLflow 링크를 전달해 준 상황이에요. 링크를 들어가 보면 A 방법론에 대한 설명과 실험에 사용된 데이터 버전, 소스 코드 버전이 적혀 있어요. 이런 상황에서 제가 A 방법론에서 약간의 다른 방법을 덧붙여서 실험을 하기 위해 설명을 읽어 보고, 해당 소스 코드 버전에서 코드를 수정한 뒤 실험을 진행할 수 있겠죠. 만약 이런 실험 관리가 되어 있지 않았다면, A 방법론을 다시 구현하려고 할 때 비효율이 발생할 수 있고, 구현하더라도 디테일 측면에서 약간 다르게 구현할 수도 있을 거예요. 새롭게 개발한 모델과 성능을 비교하는 것도 어려움을 겪을 수 있겠죠.
협업 측면 이외에도, 모델 성능을 개선하기 위한 방향성을 찾는 데도 도움이 될 수 있어요. 여러 실험들을 단순히 한 곳에 모아놓는 것이 아니라, 성능 비교가 가능한 실험들끼리만 모아서 볼 수 있기 때문에 이 과정에서 방법론 간의 평균적인 성능을 비교할 수 있었어요.
보완할 점: 비효율과 human error 줄이기
실험 관리를 체계화한 만큼, 프로젝트에서 수행하는 모든 실험에 대해 소스 코드 버전을 관리하려고 노력했어요. 이를 관리하려면 모델을 개발하는 단계에서는 '방법론 구상 → 해당 방법론을 코드로 구현한 후 Pull Request → Pull Request Review → 실험 진행'의 과정을 반복하게 돼요. 성능이 높은 모델을 개발하기 위해서 여러 방법론을 구상하고 시도해 보는 단계에서는 빠르게 시도해 보고 버릴 수 있는 방법론들이 있을 수 있음에도 이 과정을 반복하느라 실험 자체가 딜레이되는 경우가 생기기도 했어요. 실험 관리를 체계화한 것이 효율적인 모델 개발을 위해서인데, 역으로 비효율을 발생시키게 된 것이죠. 이처럼 빠르게 시도해 보는 것이 좋은 경우에는 명확한 기준을 세워 불필요한 과정을 거치지 않도록 예외 케이스를 두도록 보완하는 과정이 필요할 것 같아요.
추가로, 저희는 MLflow에 소스 코드 버전을 로깅하기 위해 config 파일에 src_version
key를 만들어서 MLflow Tag로 로깅했는데, 실험을 할 때 config를 수동으로 수정하는 방식으로 했더니 human error가 발생하는 경우가 있었어요. 이렇게 수동으로 하기보다는 최대한 자동화할 방안을 찾아 보완하는 것이 필요할 것 같습니다.
글을 마치며
지금까지 실험 관리의 중요성을 살펴보고 실험 관리 체계를 만들어서 프로젝트를 성공적으로 마무리한 과정을 소개했습니다. AI 프로젝트라는 점은 동일하더라도, 프로젝트마다 그 목적이 약간씩 다를 수 있으니 프로젝트에 맞는 방향으로 실험 관리 체계를 세워 보면 좋을 것 같아요. 다음 포스팅에서는 마키나락스의 실험 관리 노하우가 어떻게 AI 플랫폼 Runway에 적용되어 반복 작업을 제거하고, 실험의 효율을 높이고 있는지 자세히 소개할 예정입니다.
![](https://makinarocks.shoplic.cloud/wp-content/uploads/2024/06/김석기-251x300.png)
![](https://makinarocks.shoplic.cloud/wp-content/uploads/2024/06/장종하-269x300.jpg)