최종 결과

  • 세상에나… 무려 우승!!!
  • 수상하기 직전까지만 해도 팀원들이랑 ‘트로피 나와!!’ 하면서 농담 따먹기하고 있었는데 진짜 우승하고나니, 다들 벙찐 게 꽤 웃음 포인트였다.
  • 기업 자체 심사인 만큼, 우리 팀이 정확히 각 metric에서 어떤 점수를 받았는지는 알 수는 없지만 자체 평가한 지표에 대해선 아래와 같다.
평가기준BaselineOurs
WER (↓)0.06340.0770
SPIDEr (↑)0.20290.3304
Memory Usage (↓)9.3242 GB4.0500 GB
Latency (↓)1272 ms845.8 ms

프로젝트 소개

  • 오디오 언어모델을 가볍고, 빠르게 만들면서도 여러 가지 Task에 대해서도 다 잘하는 능력을 갖추도록 만드는 것이 이번 프로젝트의 핵심이다.
  • 때문에 여러가지의 평가지표가 사용되는데, 구체적으로는 ASR(Automatic Speech Recognition)를 위한 WER(Word-Error Rate), AAC(Automated Audio Captioning)를 위한 SPIDEr, 효율성을 평가하기 위한 메모리 사용량, TTFT(Time to First Token)와 TPOT(Time per Output Token)의 산술평균, 그리고 과적합 방지를 위해 알려지지 않은 하나의 hidden task가 존재한다.
    • hidden task는 프로젝트가 끝나고 밝혀지길, audioQA라고 한다.
  • 각 지표로 팀별 순위를 매긴 후, 순위의 가중평균이 제일 낮은 팀이 우승하는 대회 형식의 프로젝트였다.
    • 경량 모델링이라는 취지에 맞게, 메모리 사용량과 지연시간에 대한 가중치가 2고 나머지는 1로, 메모리 사용량과 지연시간을 줄이는 것에 초점을 두어야 할 것으로 보였다.

프로젝트 진행 과정

01/10 ~ 01/13

타운홀 미팅

  • 처음 든 생각은 ‘아. 또 리더보드네?‘였다.
    • 리더보드를 보고 점수가 오르고 내리고 하는 걸 보며 ‘도대체 뭐임??’하는 경우가 나한테는 일상다반사였기 때문에… 승부욕에 앞서 성장을 잘 하지 못하게 되는 슬픈 경우가 많았다.
    • 근데 끝난 시점에서 회고하자면, 리더보드가 그렇게 큰 의미가 없었다. 메모리 사용량이나 지연속도를 줄이는 것이 가장 중요한 Task 였다고 생각했는데, 그거에 대한 리더보드는 없었기도 했고…
    • 어차피 경량화를 하다보면 원래 퍼포먼스가 점점 깎이는 게 정배라서, 우리 팀 같은 경우는 ASR은 가장 처음 낸 베이스라인 점수가 제일 높아서 고점 갱신을 한번도 못했다.
  • 그리고 가장 난감했던 점은 고용량 데이터였다.
    • 이게 대충 500GB였는데, 이걸 다 다운로드받는 것은 그렇다치고…
    • 이걸 이용해서 학습하는 것 자체가 시간이 너무 오래걸리지 않을까 생각이 들었다.
      • 결과적으로, 이 예상은 들어맞았다. 모든 데이터셋을 이용하여 1 epoch만큼 학습시키려면 3일 정도 걸렸다
    • 그래서 가장 초기 계획은 일단 학습 안시키고 할 수 있는 방법을 알아보는 것 정도였다.

베이스라인 모델 논문 리뷰

  • 그리고 사실 해커톤 시작하자마자 서버를 쓸 수 있는 환경이 아니었다.
    • 기존에 ai stages라는 플랫폼에서 서버를 받아서 썼는데, 그 서버가 100GB로 용량이 적은 편이라 용량이 더 큰 NCP 서버로 이전하였다.
      • 이것저것 라이브러리 까는데도 큰 어려움 없고 편리했지만… 절대적인 GPU 개수가 4개에서 2개로 줄다보니 확실히 GPU가 부족한 게 많이 체감이 되었다.
  • 그래서 할 수 있는 게 사실 논문 리서치 정도 말고는 딱히 없었던 것 같다.
    • 일단 우리가 멀티모달 LLM에 대해서 완벽히 알고 있는 상태는 아니었고…
    • 그래도 기본적인 경량화를 하려면, 경량화를 하려는 모델 구조는 좀 알고 있어야 하지 않을까 하는 팀적인 합의가 있었다.
  • 멀티모달 LLM 논문을 읽는 건 처음이었지만, 사전에 멘토님께서 LLaVA 관련해서 간단히 알려주신 지식이 있어서 이를 힌트 삼아 읽으니 큰 무리는 없었던 것 같다.

01/14 ~ 01/16

데이터셋 다운로드

  • 14일 오후에 서버를 사용할 수 있는 환경이 되었다.
  • 그때부터 본격적으로 데이터를 다운로드 받으려고 보니까… 이게 작은 데이터셋은 그래도 1~2시간이면 받는데, 100GB가 넘는 압축파일을 다운받으려고 하니 거기서부터 줌도 마비되고 난리가 아니었다.
  • 이러고나서 또 데이터를 로컬에서 서버로 또 옮겨야 하니까… 거의 이번 주 내내 이러고 있겠다는 생각에 눈 앞이 아찔해졌다.
  • 그래서 selenium을 이용해서 드라이브 링크를 타고 들어가 email을 입력한 후, OTP도 입력하게 하여 버튼을 눌러 파일을 다운로드하도록 코드를 구현했다.

베이스라인 코드 분석

  • 논문 리뷰로 어느 정도의 이론은 알고 있는 상태니 코드 레벨로 보면서 어떻게 경량화를 하면 좋을지 전략을 세워보기로 했다.
  • 거기에 더해서 실제로 학습이나 추론 과정이 어떻게 일어나는지 이해해보는 것 또한 목표로 잡았다.
  • 난 주로 Q-Former 부분이 궁금해서 그에 관한 코드를 좀 살펴보았다: Discussion

01/17 ~ 01/22

앞으로의 방향성

  • 데이터를 거의 다 다운로드 받은 시점에서 모델 구조를 파악하면서 실제로 어떤 부분이 제일 모델에서 용량을 많이 차지하는지를 알아보았다.
  • LLaMA 3B를 이용한 베이스라인 모델 기준으로도 LLM 부분이 거의 80%로 엄청나게 많이 차지하고 있다는 걸 알고 있었다.
  • 그래서 일단 LLaMA 3B를 1B로 바꾸어서 끼면 그래도 꽤 많이 경량화를 해볼 수 있지 않을까 생각이 들었다.
  • 다만 그 경우 새로 학습이 필요해서 그 방법은 후순위로 두기로 했고, LLaMA 3B를 기반으로 만들어진 가중치를 그대로 활용할만한 Post-Training Quantization/Pruning 방법을 위주로 조사해보기 시작했다.

vllm을 이용한 가속화

  • 위에서 말한 것처럼 여러가지 방법론을 찾고 각 팀원이 하나씩 맡아 진행했는데, 나는 vllm 라이브러리를 이용한 추론 가속화에 도전해보았다.
  • 문제 상황은 vllm을 이용하여 추론을 하기 위해서는 query가 string이나 token ids로 주어져야 하는데, 베이스라인 모델은 Q-Former를 이용한 hidden state가 LLM으로 바로 넘겨지는 것이었다: Discussion
  • 그래서 이를 강제로 token으로 바꾸고, 해당 token이 똑같은 hidden state를 가질 수 있도록 LLM의 embedding layer를 조작하는 작업을 해주었다.
  • 근데 생각보다 안 빨라졌다…. 아니 오히려 느려진 것 같기도 하다….
    • 아마 전체 latency에서 LLM이 출력을 생성하는 시간은 그리 크지 않고, Whisper나 BEATs 같은 Feature extractor에 걸리는 시간이 병목이라 그런 것 같다고 회고한다.
  • 그래서 아쉬웠지만 일단 이 방법은 포기하기로 했다.

01/23 ~ 01/27

프로젝트 기가차드

  • 그래서 결국 뭘 할지 좀 애매해졌는데… 그때 마침 이 모 캠퍼님께서 훌륭한 아이디어를 제안해주셨다: Discussion
  • 그래서 이 아이디어를 보조하기로 했다.
    • 주로 이 레포에서 어떤 부분을 훔쳐와야 할지 함께 보면서 의논을 나누었다.
  • 말고는 대부분의 구현을 1저자(예정)인 이 모 캠퍼님께서 맡아주셨다. 난 그냥 옆에서 거드는 정도….
    • 하지만 마지막에 기가차드(새로운 모델 이름) 학습시킬 때 OOM 이슈로 batch size를 크게 가져가지 못하는 문제가 있었는데, 그걸 gradient checkpoint 기법을 이용해 batch size를 2에서 8로 늘리면서 학습이 3일 걸리던 것을 2일 걸리도록 줄이는데 성공했다 ㅎㅎ.

01/28 ~ 02/02

  • 설 연휴 + 새로고침 데이 + 주말 콤보가 있던 날

사전 Feature Extraction을 통한 학습 가속화

  • 사실 1월 24일에 오프라인으로 팀원들과 만나 프로젝트를 진행했었는데, 그때 계시던 당직 멘토님이 조언을 하나 주신 게 있었다.
  • Whisper랑 BEATs로부터 Feature를 뽑아내는 과정이 병목이므로 이를 미리 뽑아둔다면 학습 시간을 단축시킬 수 있을 것이라는 이야기였다.
  • 그래서 이를 한번 시도해보려고 용량을 계산해보니 그렇게 Feature를 뽑게 되면 중간 결과값을 저장하는데 거의 1200GB 정도 나온다는 결과를 얻게 되었다.
  • 계속 고민을 하다가 중간 결과값 자체를 average pooling한 걸 사용하면 어떨까 싶었다. 일단은 그렇게 한다면 용량은 파격적으로 줄어서 거의 100GB 정도만 써도 될 것이라는 계산이 나왔었다.
  • 그렇게 구현이 다 끝나고 직접 중간 결과값을 저장하면서 계산해보는데 내가 계산을 잘못했는지 예상되는 중간 결과값 크기가 무슨 1000GB 정도로 잡혔다. (average pooling을 한 결과다….)
  • 그래서 이것도 아쉽게 적용을 못해본 방법론 중 하나다….

02/03 ~ 02/10

실패담

  • 사실 이 기간은 개인적으로는 지혜롭게 활용하지 못하지 않았나 싶다.
  • 변명 아닌 변명을 하자면, 이미 의미있는 실험은 몇 번 밖에 못돌리는 상황이었고 나름 어떻게 하면 좋을지 로드맵이 잡힌 상태라서 오히려 좀 더 쉬엄쉬엄하지 않았나 싶다.
  • 내가 시도해본 방법론들은 모두 잘 안됐어서… 다른 팀원들이 준비하고 있는 실험에 미래를 맡기고 나는 랩업 레포트나 발표 자료 위주로 준비했던 것 같다.
  • 이어서 나오는 이야기들은 그냥 하루 정도 박았는데 잘 안됐던 것들에 대한 이야기이다.

기가차드 디버깅

  • 사실 기가차드를 학습시키다가 우연한 계기로 학습이 끊기게 되어서 지금까지 된 결과물로 효율성 테스트를 해보았다.
  • 근데 메모리 사용량과 지연시간이 베이스라인에 비해 너무 안좋게 나와서… 디버깅을 열심히 해보았다.
  • 진짜 코드 단위로 시간 찍어가면서 열심히 디버깅 해보니까 무슨 텐서 하나를 VRAM으로 올리는데 시간이 졸라 오래 걸리더라….
  • 전혀 오래 걸릴 작업이 아닌데 왜 이렇게 오래 걸리는 걸까 싶어서 확인해보니 아마 GPU Utilization에 의한 병목인 것으로 보였다.
  • 그래서 아마 더 좋은 GPU 환경에서는 이 병목이 해결될 것 같았지만, 메모리 사용량에서 이미 지고 들어가서 이것 또한 작별하게 되었다.

멀티모달 vllm

  • vllm이 멀티모달을 지원하게 하는 좀 더 젠틀한 방법이 있다는 걸 마지막 멘토링 때 알아버렸다…!
  • 그래서 LLaVA가 vllm에서 어떻게 작동하는지 확인하고 그걸 모방하려고 했는데… 결과적으로는 잘 안됐다.
  • 베이스라인 모델 중 BEATs 부분이 model executor로 구현되지 않아서 이걸 따로 만들어주었어야 했는데… 이걸 만든다고 해도 가중치를 그대로 옮겨올 수 있을까 싶기도 했고… 구현량 자체가 BEATs는 700줄짜리 코드라서 이걸 만들다가는 발표자료도 잘 못 만들 것 같아서 그냥 포기했다.
  • 이건 개인적으로 시간이 좀 더 있었으면 해볼만 했을 것 같아서 좀 아쉬웠다.

최종 결과물

  • 원래 베이스라인 모델인 SALMONN 구조에 Whisper랑 LLM만 바꾼 구조다.
  • 결과적으로는 우리가 논문 보면서 나름대로는 독창적이지 않나 싶었던 시도들은 결국 딱 하나만 되어서 꽤나 담백한 결과물이 아닌가 싶었다.
  • 그냥 누구나 조금만 생각해보면 나타낼 수 있는 모델 구조로는 끝내고 싶지는 않았는데… 뭐 완전 그런 구조인 건 또 아니지만 아쉬움이 많이 남았다.

자체 평가

좋았던 점

오픈 소스 코드를 깊게 들여다보았다

  • 사실 보는 게 좋다는 것 정도야 너무 많이 들었고 알기도 했지만… 실제로 이렇게 볼 수 있는 기회는 많이 없었던 것 같은데, 이 기회에 강제로라도 볼 수 있게 되어 공부가 좀 된 것 같다.
  • 논문을 바탕으로 구현된 코드를 보면서 생각보다는 복잡하지 않다는 인상을 받았다.

다양한 시도를 해본 것

  • 다양한 시도야 늘 해봤지만 이번 프로젝트에서 특히 가장 많이 다양한 시도를 도전해보지 않았나 하는 생각이 들었다.
  • 일단 주제 자체가 경량화라고 되어있으니까 참고할만한 논문도 많고 자유도가 높아서 해볼 수 있는 것 자체는 엄청 많았던 것 같다.
  • 물론 다 잘 됐으면 더더욱 좋았겠지만… 그래도 심사해주신 멘토님들이 이런 점을 되게 좋게 봐주셨던 것 같아서 기분은 좋다.

나름 활발했던 소통

  • 그래도 이번엔 Zoom을 잘 활용한 것 같다.
  • 실시간 소통으로 무언가 문제가 생기면 즉각적으로 얘기하고 고쳐보고 이런 시간들은 꽤 괜찮았던 것 같다.
  • 일단 다 같이 모여서 뭘 얘기하든 디버깅하든 하면 일단 결론은 나오는 것 같아서

아쉬운 점

무능한 PM

  • 민주적인 절차로 이제 내가 PM이 되었다….
  • 근데 사실 위에 프로젝트 과정만 봐도 알겠지만 내가 딱히 PM으로써 한 게 딱히 없는 느낌이었다. 그냥 최종 결정권자에 불과한 느낌?
  • 사실 근데 이건 내가 생각했던 PM이랑은 거리가 멀어서 좀 힘들었던 것 같다. 이런이런 이유로 이런 실험은 어떻게 하고… 뭐 이런 식으로 되어야 하지 않았을까 싶은데 그냥 ‘잘 모르겠으니 일단 다 해보죠?’ 처럼 되지 않았나….
  • 내가 미움받을 용기가 좀 부족했던 것 같다기엔… 근데 진짜 실험이 유망하고 유망하지 않은 게 확 보일 정도로 내가 능력있지가 않아서… 다 논문 베이스로 실험을 하는 건데 그게 어떻게 근거가 없다고 볼 수 있을까….
  • 그렇다고 내가 막 업무를 잘 배분하고 그런 것 같지도 않아서…

후반 텐션 유지 실패

  • 사실 후반 가서는 나는 그냥 좀 놔버린 경향이 있는 것 같기도 했다.
  • 어차피 내가 시도한 방법론들이 다 잘 안되기도 했고… 이제 더 뭘 할 수도 없겠다는 생각이 들어서 그냥 더 해보겠다는 팀원분 계시면 그 분 실험을 전폭적으로 밀어주고 한 거 말고는 없는 것 같다.
  • 그래도 그 시간에 뭘 더 해보려고 했으면 더 좋아졌을까 이런 아쉬움이 많이 남는다.

프로젝트 후기

  • 사실 우승은 했지만 아쉬움은 많이 남는 프로젝트인 것 같다.
  • 결국 최종 솔루션에 어떤 식으로 기여했냐고 말할 때 딱히 말할 수 있는 게 없어서…
  • 그래도 분명 얻어가는 건 많은 느낌인 것 같다. 좋은 성적을 전혀 기대안하고 있다가 덜컥 우승까지 해버리니까 기분도 좋기도 하고 ㅋㅋ.
  • 언어공방 모두 함께해주셔서 감사하고… 고생 많으셨습니다…!