top of page

세상에 없는 것을 정의하다. 1편


 

넷츠프레소 개발 과정은 일사천리로 진행되지 않았습니다. 개발을 시작하고 넷츠프레소 1.0의 개념이 나오기까지 우리는 긴 시간에 걸쳐 고민과 시도와 실패를 거듭했습니다. 그러나 전체 과정을 알지 못하고 결과물만 보면 연구 개발의 과정을 쉽고 간단한 것으로 오해할 수 있습니다. 그래서 저는 넷츠프레소의 시작부터 1.0 버전의 출시까지 우리가 어떤 과정을 거쳤는지 정리하였습니다. 이 글을 읽는 분들이 연구 개발 과정에 대해 이해하고 앞으로 넷츠프레소가 어떻게 발전해야 할지에 대한 통찰을 얻기를 바랍니다.



첫 단추 - 모델 압축의 절차를 정립한다.

제가 처음 노타에 합류한 2020년 1월 무렵, 노타에는 AutoML for Model Compression(이하 AMC) 라는 것을 만들어야 한다는 공감대가 형성되고 있었습니다. 이 개념은 AMC: AutoML for Model Compression and Acceleration on Mobile Devices라는 2019년 논문에서 시작되었습니다. 우리도 이 논문의 내용과 유사하게 AI 모델 경량화를 하는 플랫폼을 개발해야 한다는 생각이 싹트고 있었던 것이죠. AMC 가 무엇인지 물어보면 사람마다 조금씩 다른 대답이 나왔는데 대체로는 네 가지의 하위 분류에 대해 언급했습니다.


  • Pruning

  • Filter Decomposition

  • Knowledge Distillation

  • Quantization


사람들은 임의의 AI 모델에 대해 위 네 가지 기술을 적용하여 작은 디바이스 위에서도 원활히 구동될 수 있게 경량화해주는 도구를 AMC라고 생각하는 듯했습니다. 어떤 사람은 이 도구를 간단히 만들 수 있을 거라고 했고 어떤 사람은 어려울 거라고 했습니다. 어쨌든 어떤 모델을 인풋으로 넣어주면 성능은 그대로이면서 경량화된 모델을 아웃풋으로 내어놓는 end-to-end 도구라는 것은 누구나 동의하는 부분이었습니다.


AMC의 개념에서 시작된 오늘날의 넷츠프레소 모듈 세 가지
AMC의 개념에서 시작된 오늘날의 넷츠프레소 모듈 세 가지

그렇게 ‘AI 모델을 경량화하는 플랫폼을 만들어보자!’라는 아이디어에서 넷츠프레소가 시작되었습니다. 그래서 위 내용을 토대로 코드의 구조를 잡아 AMC의 첫 번째 코드를 작성했습니다. 그리고 얼마 후부터 여러 사람이 코드에 참여하기 시작했습니다.


🤔 초기의 코드를 보면 지금은 여러 다른 팀에서 수고하시는 분들의 이름이 나옵니다. 당시 노타는 팀의 개념이 없고 한 사람이 여러 프로젝트에 참여하는 구조였기 때문에 당시에 노타에 있었던 사람이라면 꽤 높은 비율로 해당 프로젝트에 (어떤 방식으로든) 참여했습니다.

우리는 이 프로덕트에 네트워크를 ‘압축’한다는 의미로 넷츠프레소(NetsPresso)라는 이름을 붙였습니다. 임의의 모델이 인풋으로 들어오면 Pruning을 하고, Filter Decomposition을 하여 모델을 압축했고 재학습을 해서 원래의 성능을 복원하는 단계를 만들었습니다. 그리고 디바이스에 맞게 모델을 변환하는 과정을 거치면서 Quantization을 적용한 후, 마지막으로 실제 디바이스에서 모델의 성능을 측정하여 기존에 비해 얼마나 모델이 가벼워졌는지 확인합니다. 이 당시에 생각했던 절차는 현재 서비스 중인 넷츠프레소 1.0과 놀라울 정도로 비슷합니다.


이렇게 탄생한 넷츠프레소의 첫 트라이얼 버전을 개발하던 저는 ‘무식해서 용감한` 상태였던 것 같습니다. 앞으로 어떤 문제를 만날지 전혀 예상하지 못하고 그저 의욕에 넘쳐서 코딩했습니다.



문제점 - 압축해야 할 모델이 고객으로부터 온다.

우리는 첫 트라이얼 버전에서 몇 가지 문제를 맞닥뜨렸습니다. 이 문제들은 모두 하나의 근원을 갖고 있었습니다. 바로 ‘압축해야 할 모델이 고객으로부터 온다'라는 것이었습니다. 다르게 표현하자면, 우리는 넷츠프레소에 어떤 모델이 인풋으로 들어올지 알 수 없었습니다. 그것이 어떤 구조를 가진 모델인지도 알 수 없었고 어떤 목적(이미지 분류, 객체 탐지 등)을 가진 모델인지도 알 수 없었습니다.


당시 우리의 모델 압축 기술은 기본적인 모델을 압축하는 데는 문제가 없었지만, 조금이라도 특이한 구조를 가진 모델이 들어와도 압축을 할 수 없었습니다. 그리고 더 큰 문제는 압축 후 손실을 보완하는 ‘재학습’이 쉽지 않다는 점이었습니다. 재학습을 하는 방법은 모델의 종류와 목적에 따라 천차만별인데 어떤 모델이 인풋으로 들어올지 모르는 상황이었으니 어려운 것이 당연했습니다.


우리는 인풋 모델을 간단한 구조를 가진 몇 가지로 제한하고 이미지 분류 모델만 압축할 수 있게끔 세팅을 한 채로 넷츠프레소를 출시했습니다. 그러나 제약이 많고 한정적인 우리의 제품은 고객의 좋은 반응을 끌어내기 어려웠습니다.


초기 버전 넷츠프레소의 모습
초기 버전 넷츠프레소의 모습

첫 트라이얼 버전의 넷츠프레소는 개선할 부분이 많아 보였습니다. 한 번에 모든 것을 해결하려는 생각으로 과욕을 부렸던 것이 가장 큰 문제였습니다. 우리는 모든 종류의 모델에 대해 압축과 재학습을 한 번에 가능하게 만들겠다는 큰 목표를 달성하려고 했습니다. 이 꿈은 웅장했으나 우리의 당시 기술적 수준으로는 좌절을 느낄 수밖에 없었습니다.


그 후, 우리가 너무 크고 어려운 문제를 한 번에 해결하려고 했다면, 이제는 큰 덩어리를 쪼개서 부분별로 문제를 해결해야 한다고 생각했습니다. 엔지니어링의 기본은 문제의 범위를 제한하고 단순화하여 해결하기 가능한 문제부터 시작하는 것이니까요. 그렇게 된다면 다듬어진 조각들이 어딘가에서 만나게 되리라 믿었습니다. 그렇게 시작된 것이 넷츠프레소의 모듈(module)화입니다.


분리된 모듈의 기능을 통합하여 하나의 큰 플랫폼을 만든다.
분리된 모듈의 기능을 통합하여 하나의 큰 플랫폼을 만든다.

이후, 넷츠프레소는 세 가지로 모듈로 나누어졌습니다. 처음에는 모델의 압축을 담당하는 모델 컴프레서(Model Compressor)와 모델을 생성하고 학습하는 모델 서쳐(Model Searcher)로 분리되었고 나중에는 모델 서쳐에서 모델을 변환하고 패키징하는 모듈이 분리되어 모델 런쳐(Model Launcher)라는 모듈도 생성되었습니다.


두 번째 단추 - 고객의 모델을 직접 설계하여 제공한다.

모델 경량화의 목적은 경량 모델을 만드는 것입니다. 첫 트라이얼 버전에서는 고객이 이미 가지고 있는 모델을 받아서 경량화하는 것에 집중했습니다. 그러다 보니 어떤 모델이 들어올지 알 수 없었고 여기서부터 많은 문제가 생겨났습니다. 그러나 모델을 압축하는 것이 경량 모델을 만드는 유일한 방법은 아닙니다. 애초에 작은 모델을 설계하여 고객에게 제공하는 것도 방법이 될 수 있습니다. 그래서 넷츠프레소의 두 번째 트라이얼은 Neural Architecture Search(이하 NAS)라는 작고 좋은 성능을 가진 모델을 찾아내는 방법을 적용하였습니다.


NAS를 활용한 두 번째 트라이얼은 첫 번째 트라이얼과는 달리 유저로부터 모델을 받지 않습니다. 대신 유저의 데이터셋을 받고, 받은 데이터에서 가장 좋은 성능을 내는 경량 모델을 NAS를 이용해 찾아냅니다. 이 방법을 사용하면 비교적 안정적으로 경량 모델을 만들어낼 수 있으나 시간적, 금전적 비용이 많이 발생한다는 문제가 있었습니다.


🤔 AI 모델을 학습하는 데는 생각보다 큰 비용이 들어갑니다. 그중 많은 부분을 차지하는 것이 학습하기 위해 GPU를 탑재한 서버를 임대하는 비용입니다. 특히 NAS는 여러 번의 시도를 통해 성능이 좋고 작은 모델을 찾아내는 방법이기 때문에 일반적으로 비해 학습을 더 많이 돌려야 하고 당연히 더 큰 비용이 들어가게 됩니다. 만약 모델을 하나 찾아내는데 고객이 낼 수 있는 금액보다 더 큰 비용이 들어간다면 이 서비스는 정상적으로 유지될 수 없을 것입니다.

많은 시도를 하면 좋은 모델을 찾아낼 확률은 높아지지만 큰 비용이 들어갑니다. 반대로 적은 시도를 하면 좋은 모델을 찾아낼 확률은 낮아지지만 적은 비용이 들어갑니다. 하지만 우리는 좋은 모델과 적은 비용이라는 두 마리 토끼를 모두 잡아내야 했습니다. 적은 비용으로 좋은 모델을 찾아내기 위해서는 AI에 대한 사전지식을 이용하여 모델 탐색이 이루어지는 경우의 수를 줄여야 한다고 판단했습니다. 우리는 좋은 모델들을 미리 찾아서 각 모델이 디바이스의 종류에 따라 어느 정도의 초당 프레임 처리 속도를 내는지 데이터베이스화하는 방식으로 경우의 수를 줄였습니다. 이 방법은 추후 넷츠프레소 1.0의 핵심적인 기능에 영향을 미치게 됩니다.


넷츠프레소 정식 배포 버전에 해당 아이디어의 영향을 받아 제작된 퀵서치(Quick Search) 기능
넷츠프레소 정식 배포 버전에 해당 아이디어의 영향을 받아 제작된 퀵서치(Quick Search) 기능

실패 - 넷츠프레소 1.0 버전을 위한 두 개의 밑거름

우여곡절 끝에 NAS를 활용한 두 번째 트라이얼을 공개했습니다. 유저들의 반응은 첫 번째 버전에 비해서는 나은 편이었지만 만족할 만한 수준은 아니었습니다. 학습 비용을 낮추기 위해 여러 가지 노력을 시도했지만 우리가 생각했던 수준까지 낮추지 못했고 모델의 성능도 유저가 원하는 수준에 다다르지 못했습니다.

하지만 모델 서쳐의 개발은 넷츠프레소의 발전에 지대한 기여를 했습니다. 우리는 넷츠프레소의 첫 번째 트라이얼을 개발할 때까지 당연히 압축할 모델을 유저로부터 받아야 한다고 생각했고 여기에서 수많은 문제가 파생되었습니다. 그러나 모델 서쳐는 '압축할 모델을 유저에게서 받아야 한다'라는 우리의 고정관념을 깨고 '압축해야 할 모델을 우리가 만들어서 고객에게 제공한다'라는 새로운 방향을 제시했습니다. 이것은 넷츠프레소의 첫 번째 트라이얼 버전이 갖고 있었던 근원적인 문제를 해결할 실마리가 되었습니다.


.

.


이번 편에서는 넷츠프레소 1.0 버전이 나오기 전까지 우리가 시도했던 방법들에 대해 적어보았습니다. 첫 번째 시도는 모델을 압축하는 직관적인 절차를 제시하였고 두 번째 시도는 모델을 압축하는 것뿐만 아니라 애초에 작은 모델을 설계하여 제공하는 방법도 있음을 제시했습니다. 넷츠프레소 1.0 버전은 첫 번째 트라이얼 버전에서 정립된 모델 압축 절차에 두 번째 트라이얼 버전의 모델 설계를 통합한 결과물입니다. 두 번의 실패가 새로운 프로덕트가 태어나는 밑거름이 된 것입니다. 다음 편에서는 두 개의 트라이얼 버전이 통합되어 넷츠프레소 1.0 버전이 만들어진 과정에 관해 이야기하겠습니다.




 

Nota Inc. NetsPresso 팀 Application 파트 | 백종원

"넷츠프레소, I'm your father."


 

bottom of page