본 글은 Kaggle - LLM Science Exam 후기 글입니다.
대회 개요
Kaggle - LLM Science Exam은 약 3개월(2023.07.12 ~ 2023.10.11 )의 기간 동안 진행된 QA task의 대회이다.
질문(prompt)과 객관식 답(A~E)이 input으로 들어가고 질문에 대한 적절한 답을 추론하는 모델을 개발하는 것이 목적이다.
평가 지표
평가 지표는 MAP@3 이다.
평가 지표에 대해 간략히 설명하면 모델은 정답일 것 같은 답을 확신이 높은 순서로 3개 출력한다.
예를 들어 1번 문제에 대해 A, B, C를 순서대로 답변으로 출력하였고, 정답이 A 면 해당 문제에 대한 점수는 1, 정답이 B라면 해당 문제에 대한 점수는 1/2 이런 식으로 점수가 계산된다.
정확한 값은 아니고 대략 저런 식으로 가중치가 매겨져 계산됨.
제한 사항
원래 캐글이 이런 지는 모르겠지만 제한사항이 몇 가지 있다.
1. CPU Notebook <= 9 hours run-time
2. GPU Notebook <= 9 hours run-time
3. Internet access disabled
1, 2번은 너무 큰 모델 쓰는 것을 방지하기 위한 조항인거 같고, 3번 문제는 chatgpt 같은 API를 호출하여 문제를 푸는 것을 방지 하기 위한 조항이다.
한 마디로 너무 큰 모델 쓰지 말고 API 써서 문제 풀 생각 하지 말라는 거다.
여기서 한 가지 문제가 발생하는데, 대회 명이 LLM Science Exam이지만 너~무 Large 한 모델은 못쓴다는 것이다. 그래서 그런지 일반적으로 대회 참가자들은 LLM 모델을 사용하지 않았다.
대회 접근 방식
1. Prompt Engineering
말 그대로 생성형 LLM 모델에 prompt 엔지니어링 해서 답변을 얻는 방식이다. 간단하게 아래처럼 prompt를 작성할 수 있다.
'''
아래 문제를 읽고 A, B, C, D, E 중 답변이 될 수 있는 확률을 구해줘
그리고 답변일 확률이 높은 3개의 선택지를 알려줘
문제 : data['prompt']
A : data['A']
B : data['B']
C : data['C']
D : data['D']
E : data['E']
'''
위 프롬프트를 이용해 문제를 푼 경우는 아래 링크에서 확인할 수 있다. 사용한 모델은 Falcon-7B이고 Public score는 0.740 정도 나왔다고 한다.
2. Large Language Model 활용
다음은 생성형 LLM이 아닌 Deberta 계열의 Model을 활용한 경우이다.
DataCollator를 해당 문제에 맞게 custom(multiple choice)하였고, input 구조를 아래처럼 변경해서 모델 학습에 활용하였다.
# 변경 전
1. data['prompt'] + data['A'] + data['B'] + data['C'] + data['D'] + data['E']
# 변경 후
1. data['prompt'] + data['A']
2. data['prompt'] + data['B']
3. data['prompt'] + data['C']
4. data['prompt'] + data['D']
5. data['prompt'] + data['E']
input 구조를 변경해 5개의 답변에 대한 정답 확률을 얻었고, 확률이 높은 순으로 3개의 최종 정답을 추출하는 방식으로 bert를 학습시켜 활용하였다. 해당 내용의 코드는 아래 링크에서 확일 할 수 있고, public score는 0.540 정도 나왔다.
3. Context 데이터 추가 - RAG
1, 2번 방식의 문제점은 문제를 풀기 위한 정보가 너무 부족하다는 것이다. LLM이라 할지라도 7B정도 크기를 사용하는 게 전부 이기 때문에, 해당 모델의 weight에 저장된 정보 만으로 문제를 풀기에는 무리가 있고, LM은 0.540의 수치가 나온 것도 신기할 따름이다.
그래서 사람들은 문제와 관련된 context(문맥)을 추가하려는 시도를 하였고, 결과적으로 문맥에서 문제와 관련된 정답을 찾아내는 형식으로 task를 변형시켰다. 무슨 말인지 헷갈릴 수 있는데, 아래 그림을 보면 조금 이해가 될 것이다.
위 그림을 간략히 설명하면
(1) 우선 주어진 prompt와 A~E까지의 텍스트로 위키피디아에서 유사한 context를 추출한다. (그림 1~3번까지 내용)
(2) context가 추가된 형태로 모델을 학습해 활용한다 (그림 4~5번 내용)
# 변경 전 input 구조
data['prompt'] + ['A']
...
data['prompt'] + ['E']
# 변경 후 input 구조
data['context'] + data['prompt'] + ['A']
...
data['context'] + data['prompt'] + ['E']
input 구조가 변경되면서 단순히 문제를 보고 정답을 맞히는 task에서 지문을 읽고 문제를 보고 정답을 맞히는 task로 변형되었다.
해당 접근법이 공유된 이후 모든 참가자들의 점수가 상향 평준화 되었다.
4. 그 외 방법들
그 외 점수를 올리기 위해 시도된 방법들은 크게 2가지로 나뉜다.
(1) 모델 학습 데이터 확보
(2) 주어진 문제와 유관한 context를 더 잘 찾는 방법
두 가지 방법과 관련된 링크는 아래에서 확인 할 수 있다.
- 모델 학습 데이터 확보 : 링크
- context를 더 잘 찾는 방법 : 링크
결론
대회를 참가하며 조금 아쉬웠던 건 동메달을 휙득했지만, 우리 팀이 시도한 방법들 중에 획기적으로 성능 향상에 기여했다고 할 만한 것이 없다는 것이다..
그럼에도 불구하고 Prompt tuning이나 Multiple choice와 같이 모델을 최적화하는 다양한 방법에 대해 알게 되었고, 주어진 문제를 해결하기 위해 단순한 방법(input 구조 개선)부터 차근차근 고민하고 적용시켜봐야 한다는 생각이 들었다.
그리고 여러 사람의 코드를 참고해 우리 팀 만의 코드를 작성해 갔는데, 새로운 코드가 공유될 때마다 우리 코드를 다 뜯어고치고 하다 보니 쓸데없이 시간이 많이 낭비되었던 거 같다.
큰 틀에서 코드를 잘 정리하는 능력이 아직 많이 부족한 거 같다.
이 글에서 다룬 내용 말고도, context 데이터를 뽑기 위한 임베딩 방법(sentence bert, TF-IDF), elastic search 활용 등 다양한 방법으로 대회를 참가한 사람들이 많이 있다. 다음에 시간이 되면 코드 위주로 글을 작성해서 공유해 봐야겠다..
Reference
https://www.kaggle.com/competitions/kaggle-llm-science-exam/overview
https://www.kaggle.com/code/cdeotte/how-to-train-open-book-model-part-1
https://www.kaggle.com/code/cdeotte/how-to-train-open-book-model-part-2
https://www.kaggle.com/code/debarshichanda/qlora-falcon-7b-training/notebook
https://www.kaggle.com/code/peilwang/train-infer-llm-deberta-v3-base
https://www.kaggle.com/code/wlifferth/starter-notebook-ranked-predictions-with-bert/notebook
https://www.kaggle.com/code/mbanaei/86-2-with-only-270k-articles
'딥러닝 > LLM' 카테고리의 다른 글
Supervised Fine-tuning: customizing LLMs (0) | 2024.08.06 |
---|---|
Gemma 2 (9B & 27B) Evaluation vs. Open/Closed-Source LLMs (0) | 2024.08.01 |
Pretraining LLMs (0) | 2024.07.31 |
데이콘 - 도배 하자 질의 응답 처리 후기 (0) | 2024.05.05 |
LLM과 LangChain (0) | 2023.05.23 |