본문 바로가기

코딩공부/패스트캠퍼스 AI 부트캠프

[Fastcampus Upstage AI Lab] 대화문 요약 대회 후기

대회 설명

일상 대화 데이터가 입력으로 주어지면 해당 대화의 요약문을 만들어 내는 모델을 만들어야 합니다.
데이터는 12457개의 학습데이터, 499개 valid data가 주어지고, 250개의 test data가 주어집니다.
평가지표는 Rouge를 사용합니다.
데이터는 원래 영어 데이터였던 것을 번역한 것으로 이루어져 있습니다.

대회 결론 스포!!!

저희조는 41.9213점을 내서 3등을 차지 했습니다.
1, 2, 3등 모두 LLM을 이용해서 고득점을 차지했습니다. 특히, 2 등 팀은 데이터 정재 전혀 하지 않고 큰 모델을 어떻게 파인튜닝 할지에 대해 몰두 해서 했더니 성적이 좋았다고 합니다.
많은 팀들이 데이터 정재와 데이터 증강에 노력을 많이 했는데 효과는 미미하거나 오히려 떨어졌습니다.
그 이유로는 이번 대회에 사용된 데이터가 번역체로 되어있는 데이터 인데 test 마저 오염되어 있어서 깔끔하게 바꿔줘도 점수가 오르지 않는 점. 그리고 대회에 사용한 Rouge 점수가 자연어의 문맥적 자연스러움은 전혀 보지않는 아쉬운 평가지표이기에 이러한 일이 발생했습니다.
즉, Rouge 점수 올리는 것에는 큰 의미가 없고 정성적 평가를 해가면서 모델을 구축하는 것에 더 의미있었던 대회인것 같습니다.
정성적 평가가 좋다고 점수가 오르지 않는 건 함정...

데이터 길이 분포에 따른 데이터 사용

단순이 발화의 개수, 문장의 수, 단어 수를 파악해 보았습니다. test dataset이 validation dataset 보다 train dataset과 유사하다는 것을 알 수있습니다. 그래서 validation dataset을 사용하지 않고 train dataset을 hold out을 사용해서 8:2로 나눠 사용해 보았습니다. 오히려 0.1 점 정도 성능 하락이 있었습니다. 그렇기에 데이터의 길이 분포가 유사하다고 좋은 점수가 나오는 것은 아니었습니다.

Special token 추가

baseline code에는 단순히 몇 가지 Special token을 사용하였지만 직접 읽어보면 위 사진과 같이 Special token들을 더 추가해야한 다는 것을 알 수 있었습니다. 실제로 Special token을 추가하는 것만으로도 0.3점 정도의 점수 향상이 있었다.

데이터 정제

원본 데이터는 영어로 되어 있었는데 한글로 번역하여 만든 데이터라 데이터에 오염이 많이 있었다.

자음 모음이 하나만 있는 경우이다. 데이터들을 보면 오타도 있고 ㅋㅋ 같은 이모티콘들도 있는 것으로 확인 되었다.
오타는 올바를 글자로 대체해 주었다.

의성어들이 중복되어 표현되는 경우가 있었다. 상식적으로 이러한 감탄사는 조사 같은 것들은 불용어를 통해 제거 해주는 것이 좋지만
이번 대회는 데이터 셋이 많이 이상해서 불용어를 제거해 주는 것이 오히려 성능을 떨어뜨렸다.
따라서 우리는 2글자를 남기는 것(아아아아 -> 아아)으로 해당 데이터들을 정제해 주었다.

#이 부적절하게 들어가 있거나 들어가야 할 곳에 들어가지 않은 경우가 있었다. 이러한 데이터들을 찾아 올바르게 교체해 주었다.

데이터에서 대화문을 제대로 요약하지 못한 것들이 있을 것이라 생각했다. 그래서 대화문과 요약문의 유사도를 측정하였다.
유사도를 측정한 결과 중 하위 200개 데이터를 직접 읽고 판단 해보았다. 이때 위 사진과 같은 데이터들이 요약이 엉뚱하게 되어있는 것을 발견할 수 있었다.

그 뿐만 아니라 요약문의 영어비율을 측정해보았다. 이때 요약문 전체가 영어로되어있는 데이터가 존재했다.
이런 데이터들을 번역을 통해 사용할 수 있지만 번역기의 성능의 믿기 힘들었고 또한 그렇게 만든 데이터의 질을 장담하기 힘들어서
요약이 잘못된 데이터와 영어로만 적힌 데이터들은 삭제하였다.

그 외에도 너무많은 오타들이 있었다. 이러한 데이터들은 직접 보면서 최대한 수정해주었지만 파도파도 끝도 없이 나와서 모든 데이터들을 확인해서 완벽하게 데이터 정제를 하지는 못했다.

또 우리를 괴롭힌 데이터는 '이름' 이었다. valid dataset과 test ddataset은 모두 한글로 이름이 적혀있었지만 train dataset은 영어로 된 이름들이 많이 존재 했다. 

영어이름을 한글로 바꿔줘야 할 필요를 느끼고 NER을 사용해서 해결 하려고 했다.
NER을 통해 영어이름들을 추출 한 뒤 번역기를 통해 번역을 해서 한글로 만들었다. 단순히 이렇게 끝나면 좋겠지만 대화문이나 요약문에 해당 영어이름의 한글이름이 존재하는 경우가 허다 했다. 이 경우 해당 한글 이름과 똑같이 바뀌었는지 확인하기 위해서 한국어 NER을 통해 이름들을 추출한 뒤 한글 이름과 번역한 이름의 유사도를 측정해서 유사하면 해당 한글 이름으로 대체해주는 방식으로 영어이름을 한글 이름으로 바꾸어 주었다.

이러한 방법으로 데이터를 정제하고 결과를 확인했을 때, 정성적인 방법으로는 꾀 괜찮고 정확히 데이터들이 올바른 한글 이름으로 바뀐 것을 확인 할 수 있었다. 하지만 정량적인 평가를 봤을 때는 0.6점 정도 성능 하락이 있었다.

아마도 test dataset에서도 많은 오염들이 있어 올바르게 정제했어도 좋은 성능으로 이어지지 못 한것 같다.


 이름은 결국 일일히 찾아가며 name dictionary를 만들어서 대체해 주었다. 그리고 앞서 언급한 것들도 모두 정제한 후 결과를 확인해 보니 0.5점 정도의 성능 향상이 있었다. 하지만 private 로 가면 오히려 0.05점 정도의 성능 하락이 있었다. 

마지막으로 submission.csv 파일도 열어보면 적절하지 못한 곳에 띄어쓰기가 되어있는 것을 확인 할 수 있었다.
다행히도 규칙적으로 띄어쓰기가 잘 못되어 있어서 해당 부분들을 코드로 쉽게 처리할 수 있었다.
간단한 정제였지만 0.04점 정도의 성능 향상이 있었다.


모델 설렉션

요약 task 에서는 주로 사용하는 것이 BART 와 T5 같은 Encoder - Decoder 모델이다.

한국어로 pretrained 된 것들 중에 위 사진처럼 총 6개의 모델을 비교해 보았다. 이때 baseline code에 사용되었던 digit82/kobart-summarization이 가장 성능이 우수하게 나왔다. 따라서 bart를 사용할 때는 digit82/kobart-summarization을 사용하였다.
학습 시간도 짧아서(약 40분) 많은 실험들을 하기에는 정말 좋았다.

T5모델들은 3가지를 비교해 보았다. 성능이 좋았던 것은 t5-large 모델로 약 44점 대의 성능을 보였다.
bart에 비하면 매우 높은 성능을 보여주었지만 학습 시간이 약 10시간 이상 걸려 비교 실험을 하기에는 매우 힘들었다.

마지막으로 LLM을 사용해 보았다. 앞서 스포했듯이 LLM을 사용한 사람만이 고득점을 쟁취했다. 우리도 yanolja 모델이 public과 private에서 최고점을 경신해서 3등을 간신히 차지했다. 당연하듯이 학습속도는 최악이다. 거의 20시간 이상 걸렸다.

학습 시간 뿐만 아니라 OOM(Out Of Memory)문제가 밥먹듯이 난다. 특히 full fine tuning은 생각 할 수 없었다. PEFT 기법을 사용하고 파라미터도 최대한 조정하여 OOM문제를 회피하기 급급했다.

keyword

성능 향상을 위해서 키워드를 활용하고자 노력했다. 일단 키워드를 활용하기 위해서는 키워드를 찾아야한다.

키워드를 찾기위해서  Okt, kkma, Komoran, Hananum 을 사용하여 키워드를 추출했다.
어떤 토크나이저를 사용하여 뽑은 키워드가 더 좋은지 비교하기 위해서 TF-IDF, ROUGE-1, Jaccard유사도, 단순카운팅을 평가지표로 사용했다. 이를 바탕으로 판단했을 때, 모든 지표에서 komoran을 사용해서 뽑은 키워드가 가장 좋았다.

뽑은 키워드는 대화문 앞에 스페셜 토큰으로 감싸서 추가해 주었다.
예를 들어,

#Person1#: 안녕, 제인. 어디가고 있어?
#Person2#: 나는 지금 도서관에 가고 있어. 

라는 대화문이 있을 때 "어디, 도서관"이 키워드로 뽑혔다고 하자. 그러면

<keyword> 어디, 도서관 </keyword>
#Person1#: 안녕, 제인. 어디가고 있어?
#Person2#: 나는 지금 도서관에 가고 있어. 

처럼 대화문 앞에 키워드를 추가하고 학습을 시켰다.
이때 0.5정도의 성능 향상이 있었다. 


서술형 텍스트 변형

모델이 생성해낸 요약문을 보면 많은 데이터에서 #Person1#이 누구인지, #Person2#이 누구인지 헷갈려 할 때가 많다.
이런 문제를 해결하고자 대본 형식의 데이터를 평서문 형식으로 바꿔주었다 예로 들면

#Person1# : B씨, 그 손에 들고 있는 건 뭐예요?

라는 글을 

#Person1#이 말했다. "B씨, 그 손에 들고 있는 건 뭐예요?"

식으로 변경해 주었다.
정성적 평가를 했을 때는 아직 부족하지만 그래도 전 보는 많은 데이터에서 누가 누구인지 정확히 파악하고 요약을 해주는 듯 했다.
하지만 정량적 평가에서는 오히려 성능이 떨어졌었다.

생각해보니 대본 형식의 대화문에서는 #Person1# 과 같은 토큰이 스페셜 토큰인 것이 적절 했지만 평서문으로 바꿨을 때는 일반 토큰으로 취급해 주는 것이 문맥을 이해하는데 더 도움이 되지않을까 해서 실험을 했다.
실험 결과 public에서는 nomal token으로 취급하는 방식이 유효했지만 private 로 가면 오히려 성능이 떨어졌다.


또다른 문제가 있는데 바로 대화문에 등장하지도 않은 사람이 요약문에서 등장하는 것이다.
이러한 문제를 해결하고자 키워드에서 사용했던 방법을 응용해서 사용하기로 했다.

대화문에서 등장하는 #PersonN#들을 찾아서 대화문 시작 맨 앞에 스페셜 토큰으로 감싸서 넣은 방식이다.
그 결과 정성적 평가에서는 모든 데이터에서 대화문에서 없었던 친구들이 등장하는 문제는 더이상 발생하지 않았다.
놀라운 점은 이렇게 성능이 많이 개선 됐음에도 불구하고 정량적 성능 지표는 오히려 떨어지는 결과를 보였다.

keyword 와 평서문 변경 부분을 진행하면서 느낀 점은 정성적 평가와 정량적 평가가 비례하지 않는 다는 것이다.
이는 아쉽게도 대회측 문제가 존재했다. 대회에서 test dataset마저 오염이 있어 정확한 점수를 판단하기 어렵게 되었다.

그리고 이러한 실험들을 통해 알게 된 점은
"요약 task에서는 meta data가 유효하다"는 점이다.

정확히 meta data template를 꾸려서 대화문 앞에 넣어주면 더 좋은 성능 향상이 있지 않았을까 싶다. 


LLM 시도들

pretrained 된 LLM을 들고와서 직접 fine tuning 해본 경험은 처음이라 어떤 모델이 좋은지도 감이 잡히질 않았다.
그래서 summarization이 가능한 모델을 찾을 때면 일단 시도해 보았다.

# 1. 성능 이슈 

upstage solar 와 beomi/KoAlpaca-Polyglot-12.8B 모델을 사용해 보았다. fine tuning 하지 않고 일단 기본 pretrained 된 것으로만 실행 했을때 성능이 너무 좋지 않았다.
특히, 프롬프트에 여러 제약 조건들을 달았음에도 불구하고 제약 조건들을 지켜지지 않았다.( 대화문의 20%길이로 해줘, 3인칭 관점에서 요약해줘. 등)

#2. GPU 이슈

말 그대로 GPU 이슈가 너무 많이 발생했다. 해당 실험을 하면서 서버만 4번이 터졌다...


LLM Fine Tuning

Full fine tuning은 GPU문제도 있고 시간 문제도 있어서 사용하기 어렵다.
따라서 PEFT를 이용해서 ROLA를 사용해서 fine tuning을 하였다. 
ROLA를 사용하더라도 시간의 약 20시간 이상 걸렸다. 심지어 early stopping으로 학습을 멈춘 것이 아니라 5epoch으로 제한을 두고 학습을 시켰다.(즉, 5epoch 이상 돌면 성능이 조금 더 올라 갈 수있었는데... 시간이 ...)

신기한 점은 추론을 할때 최대한 상상력을 뺄 수록(temperateure, do_sample) 성능 향상에 도움이 되었다.


번외

그외 여러 시도들이 있었다.
역변역도 해보았고 데이터 증강도 시도 해보았다.
다른 조들도 이전 CV때 데이터 증강으로 재미를 본 것을 기억으로 많은 시간을 투자 한 것 같던데 아쉽게도 데이터 증강 부분은 성능 향상에 도움이 되질 않았다. 아무래도 데이터 자체가 질 좋은 데이터가 아니다 보니 이러한 방법들이 성능 향상에 도움이 되질 못 한것 같다.