실제로 위 사진처럼 단체 카톡방 대화를 구분하기 위해 "사진 변경" 기능이 있는 것을 알 수 있다. 하지만, 이 경우 내가 가지고 있는 이미지로 사진을 변경하는 것이므로 이에 맞는 이미지 찾기가 귀찮을 수 있다.
즉, 우리 프로젝트 목표는 아래와 같다
단체방의 대화 내용은 계속해서 바뀐다. 따라서, 이 부분을 어떻게 파악할지에 대해 생각해봐야 한다.
최근 대화 내용이 현재 이 단체방이 가장 흥미를 가지고 있는 주제라고 생각했다. 따라서 최근 대화를 활용하여 이를 요약하고, 요약문을 Image로 바꾸는 방식으로 카카오톡 대표 이미지를 형성하면 되지 않을까라고 생각했다.
이번 Project는 시작하기 전부터 많은 우려가 있었다.
멘토님께서도 난이도에 살짝 걱정하셨고, 사실 우리 팀에서도 너무 어려운 주제를 잡은 것이 아닐까 걱정할 정도였다.
특히, Text-to-Image(이하 T2I) 같은 경우 그나마 Multimodal로써 뜨고 있는 Task여서 많은 Pre-trained Model이 존재하였지만, Dialogue Summarization은 너무 생소한 Task였기에 먼저 우리가 프로젝트를 실제로 진행할 수 있을지(즉, 대화 요약을 할 수 있는지) 확인하는 것이 매우 중요했다.
따라서, SAMSum 데이터셋으로 먼저 Feasibility Check를 해보았다.
수행한 내용은 아래와 같다.
수행 이유 : 무조건 내가 짠 Train코드가 결과가 나쁠 것이라는 것은 이해했었다. 하지만, 직접 1부터 구현해봐야 대화 요약 모델의 학습 흐름을 이해할 수 있을 것 같다고 판단하여 직접 구현해보았다.
어디까지나 Feasibility Check이므로, 구현 가능하더라도 "어떻게" 구현이 이루어지는지 이해하는 것이 중요하다고 판단하였다.
결과 : ROUGE 점수상 20~30점 정도의 결과를 도출해보았다. 실제로 결과 문장을 보더라도 어느 정도 학습이 된다는 것을 느낄 수 있어서, 이제는 Huggingface의 여러 메서드를 활용해도 될 것 같다는 생각이 들었다.
수행 이유 : 내가 짠 코드가 구현 되었으니, 내 코드보다 더 High Level로 짜진 Seq2SeqTrainer를 활용하면 성능 향상이 무조건 있을 것이라고 생각하였다.
결과 : ROUGE Score 상 40점 정도가 나왔다. 논문에서 SOTA 점수가 ROUGE 50점 정도였으니, 이정도면 충분히 모델로써 활용 가능하다는 것을 깨달았다. 즉, 대화 요약 Task는 실제로 Project에 활용할 수 있는 모델이였다.
위와 같은 Feasibility Check Test를 진행하고, 이에 대한 흐름을 이해했으며, 마지막으로 짜여져있는 라이브러리를 활용하여 성능을 대폭 올린 이후 팀원에게 "가능한 Task다"라고 말했고, Project가 시작되었다.
실험을 하면 할 수록 ROUGE에 대한 의구심이 강하게 들었고, T5를 포기하여 KoBART로 실험을 하게 되자 팀원에게 실험을 많이 맡기고 Metric 구현에 힘써야겠다는 생각이 들었다.
다른 팀원도 ROUGE가 모델의 성능을 밝히는데 그렇게 좋지 않다는 생각을 하였기 때문에 흔쾌히 받아들여주었고, 따라서 이 부분을 구현해보기로 하였다.
Metric 설명
Sentence-BERT를 활용하여 Input을 {Prediction Summary, Golden Sumamry}로 넣어줘 Cosine Similarity를 구하는 방식으로 Metric을 정했다.
Metric 생각 이유
RDASS라는 논문이 존재한다.
간단히 설명하자면 SBERT의 Cosine Similairty를 활용하여 {Dialogue, Golden Summary} 점수와 {Dialogue, Predictoin Summary} 점수를 구하여 평균을 내는 것이다.
처음엔 RDASS를 우리의 Main Metric으로 활용하기로 했다.
하지만 문제가 발생했다.
애초에 Dialogue Summarization에서는 {Dialogue, Golden Summary}의 Cosine Similarity 점수가 낮았던 것이다.
Prediction은 Golden Summary를 내는 방향으로 학습이 진행될텐데, 애초에 {Dialogue, Golden Summary} 점수가 낮으니 Metric으로써 신뢰성이 조금 떨어지는 느낌이 들었다.
따라서, Dialogue를 제외하고 그냥 Golden Summary와 Prediction Summary만 활용하여 문장 유사도를 측정하는 것이 그나마 괜찮은 Metric이라고 판단하였다.
Cosine Similarity가 Loss의 경향성과 비슷한 경향성을 보이고, 점수 자체도 상당히 괜찮게 나왔다.
즉, 이정도면 이번 Project의 Metric으로 충분하다고 판단하였다.
다른 팀원이 해당 모델로 실험해본 결과 괜찮은 성능인 것 같다고 판단하였고, 이에 따라 우리의 Main Metric으로 활용하기로 하였다.
T2I 모델이 충분히 크기 때문에, 대화 요약 모델마저 Size가 커져버리면 너무 커서 활용하기 어려운 모델이 될 것이라고 판단하였다.
따라서, 대화 요약 모델은 무조건 KoBART에서 추가시켜 Size를 키우지 않고 그대로 활용하기로 하였다.
실험 이유
Loss를 보니깐 3 Epoch으로 실험이 끝났을 때 경향성 자체가 계속해서 감소하다가 끝남을 알 수 있었다.
따라서 Epoch을 매우 증가시킨 이후, Overfitting이 어디서 나는지 확인하고 load_best_model_at_end
와 우리의 Metric을 적극적으로 활용해보기로 하였다.
실험 결과
Loss 값의 감소는 조금 되다가 멈췄지만, Main Metric인 STS가 매우 커졌음을 알 수 있었다.
따라서, 이렇게 학습시킨 모델로 실행시켜보았다.
결과 자체는 더 좋아진 듯 보았으나, 결과가 좋은 이유는 간단했다.
"결과 문장이 길어졌다"
즉, 생성 문장 자체가 길어지다 보니깐 더욱 많은 정보를 담게 되고, 요약문과 더욱 비슷한 문장이 된다고 판단하였다.
(물론, AI Hub 데이터셋의 Golden Summary가 신경쓰지 않아도 되는 부분도 Golden Summary에 넣는 경향이 살짝 존재한다. 예를 들어, "나는 여행을 갔다와서 힘들다"로만 요약하면 되는데, "나는 ~와 3박 4일 여행을 갔다와서 힘들다"로 Golden Summary를 형성했다)
T2I Model의 Input 문장으로는 짧은 것이 더 좋은 성능을 낸다고 판단되었고 Metric 상 큰 점수 차이는 없는 것으로 판단되어 최종적으로 3 Epoch 실험으로 결정되었다.
논문에서 NER을 통해 화자 및 나오는 사람을 Input의 첫 부분에 넣어줌으로써 성능을 높일 수 있다고 하였다.
물론, 그 논문에선 모델에 Layer를 추가하였지만 우리는 모델의 크기를 키우지 않기로 하였기 때문에 더 이상 Layer를 추가하지 않았다.
실험해보았고, 결과가 그렇게 좋게 나오지는 않았다.
해당 논문에서는 추가되는 Layer에서 NER에 대한 추가적인 처리 로직이 존재하였다. 즉, 이 논문에서는 NER을 처리하는 Layer가 Encoder와 Decoder 사이에 끼워진 것이 핵심인데, 이 부분이 구현되지 않았기 때문에 점수 향상이 어려웠을 것이라고 생각했다.
NER을 통해 대화하는 화자는 아니지만 대화에 나오는 사람들도 모두 Input으로 넣어줬어야 한다. 하지만 이 부분을 구현하기 위해서는 NER을 위한 모델이 하나 더 필요했기 때문에, 이 부분을 활용하지 못했던 것이 점수 향상이 되지 않은 이유라고 생각했다.
모델(특히 T2I)이 너무 크기 때문에 Load할 때 마다 많은 시간이 소요되었다. 따라서, 모델을 항상 상주시켜 Load되는 시간을 줄이자고 판단하였다.
대화 요약은 2-3초 정도면 끝나는데 이미지는 11-12초 정도가 걸려 생성된다.
User가 처음부터 13-15초를 기다리는 것 보다는 먼저 대화 요약문을 보고, 이 대화 요약문으로 어떤 이미지가 나올까 기대하는 것이 유저의 체감 대기 시간을 확 줄일 수 있을 것이라고 판단하여 위처럼 로직을 구현하였다.
backend 및 Frontend에 메서드들이 너무 많아서 Backend와 Frontend 파일에서 핵심 내용이 잘 눈에 보이지 않았다.
따라서 메서드들을 최대한 밖으로 꺼내 모듈화시켜 Backend와 Frontend 파일에서는 Request 및 Respond 흐름에 집중할 수 있게 만들었다.
T2I Train Directory가 너무 커서 이 부분까지 서비스하는 GCP에 올려버리면 OOM 문제가 발생할 것 같았다.
따라서, T2I 및 대화 요약을 학습시키는 Directory는 배제하고 오로지 Service 디렉토리 및 main.py, app.py로만 서비스 제공이 가능하도록 하고 싶었다.
T2I 모델을 활용할 때 많은 부분에서 T2I Train Directory를 활용하였기 때문에 코드를 조금 읽어보고 필요한 부분만 뜯어와서 모듈화 시켰다.
이에 따라 Service Directory만으로도 Backend Logic이 실행될 수 있게 하였다.
1. Feasibility Check
이번 Project를 진행하면서 가장 뿌듯한 부분이였다.
원래 존재하던 Dataset 등을 활용하여 정말로 이 Project가 가능한가를 확인한 이후 Project를 진행하자 Project가 끊김없이 부드러운 흐름으로 진행되었다.
다음에도 Project가 진행된다면 대충이라도 Feasibility Check를 하여 해당 Task에 대한 이해도를 높인 다음 제대로 Project를 제대로 진행하는 것이 좋을 것이라는 좋은 경험이였다.
또한, 만약 구현 불가하다면 빠르게 내 실력으론 구현이 불가하다는 것을 인지하고 타인의 도움을 받거나 다른 주제로 선회하는 등 빠른 해결이 가능하다는 장점도 본 것 같아 이번 Project에서 가장 잘한 점이라고 생각한다.
2. 일정을 정하고 일정에 맞춰 프로젝트 진행
사실 이전 대회에서는 그냥 '~할 거예요!' 정도만 결정하고 일정을 딱히 세우지는 않았던 것 같다.
하지만 이번 프로젝트에는 시작일에 팀끼리 회의를 하여 기간을 정해 놓고, 해당 기간 동안 어떠한 행동을 할 것인지 토론하였다.
이렇게 프로젝트 기간 초반에 일정에 대한 계획을 세워두니 피드백이 조금 더 쉬워졌고, 다른 팀원의 작업물도 대충 예상이 가는 좋은 현상이 보였다.
또한, 누군가의 일정이 밀리면 해당 팀원도 그 부분을 인지하기 쉬워져 다른 팀원에게 도움을 요청하거나 조금 더 열심히 하는 등 많은 장점을 가지고 온 행동이였던 것 같다
3. 분업
이번 Project는 2개의 Task로 이루어져있었다.
따라서 처음 회의 때 어떻게 분업을 할 것인가 얘기하고, 대화 요약 팀에서도 누가 어떤 부분을 담당할지 많이 얘기했다.
이러다보니 분업이 잘 되었고, Project의 진행 현황이 예전보다 많이 빨라지고 효율적이 되었다는 것이 느껴졌다.
4. 모듈화
모듈화를 해보면서 코드에 대한 이해도가 더욱 높아졌다.
또한 모듈화를 하면서 기능을 나누다 보니, 기능 추가 및 기능 변경이 더욱 쉬워졌고, 이에 따라 yaml 파일 등을 활용하기도 쉬워졌다.
항상 모듈화를 머리에 기억해놓고, 코드를 짤 때 다른 사람도 특정 Directory가 어떤 기능을 담당하는지 확실히 알 수 있도록 모듈화시키는 것이 중요하다고 생각했다.
5. 원리 파악
이번 Project를 진행할 때 "원리"를 제대로 파악하는 것에 많은 힘을 썼다.
BART를 쓰기 전 BART 논문을 읽어보며 어떤 방식으로 BART가 학습되고 활용되는지 파악하였다.
또한 RDASS 논문을 읽으며 "어떠한 이유로 이 논문을 썼는가"에 집중하여 읽었으며, 여기에서 활용하는 Sentence-Bert에 대해서도 제대로 공부하여 논문 리뷰를 수행하였다.
이러다보니 BART를 활용하여 코드를 짤 때 에러가 많이 발생하지 않고, 발생하더라도 빠르게 해결 가능했다.
(특히 Train 코드를 1부터 짤 수 있었다는 것은 이를 보여준다고 생각한다)
또한 SBERT를 제대로 이해하고 RDASS 논문도 제대로 이해하니 단점이 무엇이고, 어떤 방식으로 이를 해결할 수 있는지 등에 대한 아이디어가 나왔다고 생각한다.
또한 GCP를 할 때도 최대한 "원리"에 집중하여 Product Serving 과정을 진행하다보니 AWS를 공부할 때 보다 빠르고 확실하게 공부된 것 같아 기분이 좋았다.
1. 시간의 부족
Project가 5주긴 한데, 사실 1주 정도는 강의 듣는데 써야 하고, 마지막 주는 네트워킹 데이 및 Wrap-Up Report 쓰기니 빼야하고, 4번째 주는 이미 초기 발표 영상을 찍고 피드백을 받아 발표 영상을 수정하는 주였다 보니 사실상 2주 정도밖의 시간밖에 없었다.
물론, Product Serving부분은 구현하지 않아도 발표 영상을 찍을 수 있다는 판단 하에 4주차에 Product Serving 부분만 집중하여 구현함으로써 최대한 시간을 효율적으로 활용했었지만, 그래도 짧다는 느낌은 지울 수가 없었다.
조금만 시간이 있었다면 더 좋은 결과를 도출하고 실험도 더 많이 해 볼 수 있었을 것 같은데.... 진짜 진짜 아쉽다.
2. 협업에 대한 이해도 부족
협업 자체는 잘 되었다.
이해도가 부족하다는 것은 "다른 팀과 협업을 어떻게 하는지"에 대한 이해도가 부족했다는 것이다.
대화 요약 팀끼리의 대화 및 협업은 잘 되었기 때문에 협업을 잘 했다고 생각하였다.
하지만 대화 요약과 T2I의 Pipeline이 형성되어야 한다는 것을 알았다면 T2I 팀과도 많은 대화를 나눠보며 협업을 해봐야 했을 것이다.
하지만 T2I 팀은 T2I 팀 나름대로 실험하고 대화 요약팀은 대화 요약팀 대로 실험하다보니 Pipeline을 구축하는데도 시간이 좀 걸렸고, 생각보다 결과도 만족스럽지 않아 T2I Model을 새로 학습시킨 경험이 있다.
실제로 Pipeline을 구현한 이후 필요성을 느끼고 재학습시킨 Model이 더 좋아지는 것을 보고, "다른 팀"과의 협업을 할 때에 대한 이해도가 많이 부족했었다는 것을 알았다.
이 부분을 먼저 알았다면 더 좋은 결과를 낼 수 있었을 텐데 아쉬웠다.
3. 실제로 상용화되었을 때의 문제점을 제대로 고려하지 못함
모델을 상주시키는 것이 속도 향상을 위해서 가장 좋은 방법이라고 생각했고, 회의를 통해 이렇게 하기로 Fix 하였다.
하지만, 실제로 Service하니 문제가 발생했다.
global, 즉 전역 변수 모델이다 보니깐 A와 B가 동시에 Request를 보냈을 때 A 요청을 먼저 처리하고 B 요청을 이후에 처리한다는 것을 알게 되었다.
이게 상용화 되었을 때는 단위가 백, 천일텐데 이럴 경우엔 큰 문제가 발생할 수도 있겠다는 생각이 들었다.
이런 부분을 실제로 Serving하고 고려해 봤어야 했는데, 그 당시 모델에 너무 집중하여 이런 부분을 제대로 고려하지 못한게 많이 아쉬웠다.
1. 상용화 할 모델이라면 배포한 이후의 실험도 많이 해보자!
모델 실험도 할수록 모델 성능이 좋아진다.
Product Serving도 마찬가지이다!
Serving 이후 실험(즉, Test)를 진행할 수록 어떤 부분이 부족한지, 어떤 부분을 보강해야하는지가 잘 보이는 것 같다.
따라서, 상용화가 목적이라면 모델 성능 향상도 중요하지만 실제로 Serving을 빨리 해봐서 Browser 상에서 많은 실험(Test)를 해보는 것도 중요한 것이라는 것을 느낀 Project였다.
다음 Project부터 이런 부분을 많이 고려해야 할 것 같다.
2. 제대로 된 협업 수행
실제로 취업을 하거나 대규모 Project를 진행하면 "다른 팀"과의 협업도 많이 필요할 것이다.
항상 우리 팀과의 협업만을 고려하지 말고, Pipeline 전체를 이해하고 이런 이해를 바탕으로 어떤 방식으로 다른 팀과 협업을 해야 더 좋은 전체 모델(Project)를 형성 할 수 있을지 고민해 보는 것이 필요할 것 같다.
3. 주제 정할 때 인간의 측면에서 많이 생각해보기
"나는 3박 4일 여행을 해서 피곤하다"
이 문장을 Image로 바꿔보자. 어렵지 않은가?
AI라는 것은 결국 "사람의 뇌"를 따라가기 위한 기술이다.
즉, 사람이 어렵다고 생각하는 Task는 AI에게도 어렵다는 것이다.
나는 이 프로젝트를 시작하기 전에는 기계가 전지전능해서 우리가 상상하지도 못한 결과를 내 줄 수 있을 것이라고 착각하였다.
하지만 아니였다. 결국 기계는 기계일 뿐, 사람이 미리 Input을 준 것에 대한 Output을 낼 수밖에 없는 존재이다.
따라서, Project 주제를 정할 땐 사람이 이 Task를 수행할 때 어떨지 생각해보고, 사람 입장에서 "가능하다"라는 생각이 들면 진행해도 되지만, 사람이 기계 대신 Project 주제를 수행하더라도 어렵다는 생각이 들면 다시 Project의 주제에 대해 생각해보는 것이 필요할 것 같다.
정말 많은 것을 쏟아 부은 Project였다.
(Project 끝나고 2일 연속 12시간 이상 잔 거면 말 다했지 ㅎㅎ......)
그래도 쏟아 부은 만큼 괜찮은 결과가 나와서 좋았던 것 같다.
마지막 Product Serving을 수행하고 결과를 도출할 때 처음 Boostcamp AI Tech 시작할 때가 생각났다.
"왜 내맘대로 안되지?", "왜 실행이 안되지?", "왜 에러가 뜨지?", "정말 이 길이 맞는걸까?" 등등...
나의 실력이 다른 사람보다 많이 떨어진다는 것이 느껴졌고 자괴감도 많이 심했었다.
또한 내 실력이 좋아진다는 것도 잘 느껴지지 않아 좌절스러웠다.
내가 Backend를 1년 더 공부했다면 이미 취업하지 않았을까? 그냥 하던 거 할 걸 괜히 새로운 걸 도전했나? 이런 후회도 많이 들었었다.
그래도 이를 악 물고 했다. 내가 선택한 길이라는 생각으로.
그리고 다른 팀원에게 최소한 부정적인 영향이나 해는 주지 말아야 되겠다는 생각으로.
이번 Project의 최종 결과물을 내면서 이런 부정적인 감정들이 조금은 녹아 내린 느낌이 들었다.
내가 한 선택은 잘못된 것은 아니였구나, 처음의 나와 비교하면 정말 큰 향상을 이뤘구나.
이번 Project와 Boostcamp AI Tech는 내 인생에서 매우 중요한 경험이 될 것 같다.
포기하지 않는 것에 대한 보상이라는 것을 알게 되었으며, 도전에 대한 달콤한 열매를 알게 되었고, 다른 사람에게 도움을 요청하고, 도와주는 것이 무엇인지 진정한 의미로 알게 된 느낌이 든다.
물론 다른 팀원들이 있어서 이런 성장이 가능했다. 다른 팀원들에게도 모두 감사한다.
하지만 이번 Project 끝난 이후에는 나에 대한 칭찬을 많이 하고 싶다.
고생했다 정말로. 포기하지 않아서 다행이였다.