# 랩업 리포트(화이트 보드)(odqa)
# ODQA using KLUE-MRC data
## 1. 프로젝트 개요
### I. 프로젝트 주제 및 개요
**ODQA**(**O**pen **D**omain **Q**uestion and **A**nswering)은 지문이 따로 주어지지 않고 사전에 구축되어있는 Knowledge resource 에서 질문에 대답할 수 있는 문서를 찾은 후, 해당 문서에서 질문에 대한 대답을 찾는 문제이다.
프로젝트는 `[질문, 질문와 관련된 문서, 답]`을 포함한 데이터 셋을 통해 어떤 문제가 주어졌을 때, 그 질문에 해당하는 답을 찾는 모델을 구축하는 것을 목적으로 한다.
### II. 개발환경
본 프로젝트는 리눅스 환경 하(Ubuntu 18.04.5)에서 개발되었다. 통합 개발환경으로는 Visual Studio Code와 Jupyter Notebook을 병행하여 사용하였으며, 학습을 위한 GPU로는 v100을 제공받았다. 또한, 개발에 사용된 주요 프레임워크와 라이브러리는 다음과 같다.
- Pytorch (1.7.1)
- transformers (4.5.0)
- pandas (1.1.4)
- scikit-learn (0.24.1)
- datasets (1.5.0)
- tqdm (4.41.1)
- konlpy (0.5.2)
- Elasticsearch (7.15.1)
### III. 프로젝트 구조
```
├── arguments.py
├── data_preprocessing
│ ├── data_preprocessing.py
│ ├── split_kfold.py
│ └── wiki_data_preprocessing.py
├── elastic_search.py
├── ensemble.py
├── inference.py
├── install
│ └── install_requirements.sh
├── make_dataset.py
├── model.py
├── modelList.py
├── postprocessing.py
├── preprocessing.py
├── readme.md
├── sweep.yaml
├── train.py
├── trainer_qa.py
└── utils_qa.py
```
### IV. 기대효과 (수정 필요)
전체적인 과정이 Retriever와 Reader 과정으로 진행되기 때문에, 각 과정에 가장 적합한 모델을 만들도록 다양한 방법론을 접할 수 있다.
## 2. 프로젝트 팀 구성 및 역할 (가나다순)
- 고지호(T2007): ElasticSearch Retrieval 성능 높이기 (User_dict 추가, kss 이용한 문장단위 쪼개기와 단락단위 쪼개기 시도)
- 김민성(T2024): Reader model 구현 및 실험
- 김범찬(T2031): Data preprocessing, Elastic Search
- 김정현(T2051): EDA
- 심현덕(T2125): Elastic Search등 Retrieval
- 최수홍(T2228): Data preprocessing, Data version control, Reader model 구현 및 실험
## 3. 프로젝트 수행 절차 및 방법
### I. 프로젝트 기획
기존 MRC 태스크들(SQuAD 2.0, KorQuAD 2.0)을 분석해 data handling 전략이나 사용된 모델들의 특성을 분석했다. 그 후 강의들을 듣고 baseline code를 분석하며 이번 MRC 태스크의 특성과 사용될 코드들을 분석했다. 또한 SOTA 모델들과 논문들, 부스트캠프 특강들, 공개된 1기 git을 참고해 Dense Retrieval, Elastic Search, Negative Sampling, 다양한 BERT-base 모델들과 LSTM, Conv-1d 모델링 등을 시도했다.
### II. 프로젝트 수행
본프로젝트 수행을 위한 일련의 과정은 다음과 같다.
1. 학습데이터가 어떤 형태로 구성되어 있으며, 어떠한 특수기호를 통해 의미가 형성되고 구분되는지 파악한다.
2. 정규식을 활용하여 동일하지만 다른 형태를 가진 기호들을 동일한 기호로 치환하며, 기호가 가진 고유한 의미가 없거나 학습에 영향을 미치지 않을 정도로 작은 기호는 제거한다.
3. Retriever의 변수 설정을 달리하여 최적의 검색율을 보이는 설정을 찾는다.
4. BERT, RoBERTa, Electra, CNN 등 다양한 모델을 통해 최적의 성능을 내는 모델과 hyper parameter를 찾는다.
5. 이후 이들 모델들의 결과값을 토대로 Ensemble을 통해 성능을 높인다.
### III. 프로젝트 결과
**LB score (public)**:
- EM : 60.000, F1 : 70.180
**LB score (private)**:
- EM : 60.560, F1 : 72.280
## 4. 프로젝트 수행 결과
### I. 탐색적분석 및 전처리
#### i. 데이터 소개
학습 데이터는 3952개의 `train` 데이터와 240 개의 `valid` 데이터로 구분되며, Retriever가 검색할 수 있는 문서들의 목록인 `wikipedia_documents.json`가 제공되었다. 각각의 데이터는 `[title, context, question, id, answers, document_id]`의 형태를 띠고 있다.
평가 데이터로는 240개의 `public` 데이터와 360개의 `private` 데이터가 제공되었으며, 각각의 데이터는 `[query, id]`의 형태를 띠고 있다.
#### ii. 전처리
가령, 『동의보감』, 《동의보감》, <동의보감>은 "동의보감"이라는 서적을 참조한다는 의미지만 그 형태가 다르다. 같은 의미를 가짐에도 다른 형태를 띈다면 학습에 혼란을 줄 수 있기 때문에 같은 의미를 가진 특수기호는 모두 같은 기호로 치환하였다.
또한, 줄바꿈 기호(`\n`)와 단락바꿈 기호(`\n\n`)는 문서 작성자에 따라 다르게 사용되며, 큰 의미를 가지고 있지 않다고 판단하여 모두 띄어쓰기로 변환해주었다. 특수기호 치환의 예시는 다음과 같다.
- `#`, `\n\n`, `\n` 문자 제거
- 따옴표 관련 기호(`“, ”, ‘, ’`) → 작음 따옴표(`'`)로 치환
- 인용 관련 기호 (`〈〉<><>「」≪≫《》『 』`) → 꺾쇠(`<>`)로 치환
### II. 모델 개요
#### i. Retriever
Retriever로는 `ElasticSearch` library를 사용했으며, indexing 데이터로는 앞서 언급한 전처리 과정을 거친`wikipedia_documents.json` 파일을 사용하였다.
ElasticSearch instance에 query를 넣으면, 해당 query와 가장 연관이 깊은 문서 상위 10개를 가져오는 식으로 Retrieval을 진행하였다.
#### ii. Reader
Reader model은 huggingface에서 정의된 `Bert`, `RoBERTa`, `Electra`를 사용하였다.
### III. 모델 선정 및 분석
#### i. Retriever
`index_config`에서는 기본적 설정에 더불어 `filter`와 `analyzer`를 추가해주었다. `filter`는 한국어 불용어 사전을 참고한 text파일을 설정하였으며, `analyzer`는 Elastic Search 라이브러리에서 기본적으로 제공하주는 `nori-analyzer`를 사용하였다.
또한, `[query, id, answer]`는 불필요한 데이터로 판단했기 때문에, `[title, context, document_id]`로만 indexing을 진행하였다. 또한, `title` 없이는 `context` 내 주체를 확인할 수 없는 경우도 있기 때문에, `context` 앞에 `title`을 추가해주는 것으로 `context`만 보고도 설명의 대상이 되는 객체가 무엇인지 알 수 있게 하였다.
실제로 불용어와 `nori-analyzer`를 추가했을 때, 불용어 없는 `standard-analyzer`에 비해 압도적인 성능향상을 보여주었으며, `context` 앞에 `title`을 추가해주는 것 역시 보다 높은 검색율을 확인할 수 있었다.
#### ii. Reader
각각의 모델에 대해 `batch_size = 8`, `epochs = 2`, `weight_decay = 0.009`, `learning_rate = 0.0001`로 hyper parameter 설정을 하여 학습하였다.
추가적으로 각각의 모델에 fully-conneted layer 3개를 추가적으로 올리고, `RoBERTa` 모델 위에 각각 `[1,3,5]`의 kernel size를 가진 Convolution Layer 3개를 추가적으로 쌓은 모델 역시 실험에 사용하였다.
fully-connected layer를 올린 모델은 vanilla 모델보다 성능적으로 우수한 결과를 보여주었다.
### IV. 검증(validation) 전략, 앙상블 방법
#### i. 검증
train dataset 안에 있는 validation set을 이용하여 eval step마다 evaluation을 진행했다. 매 eval에서 exact match를 측정하여 가장 높은 EM을 가진 모델이 저장되도록 했다.
### V. 차후 모델 개선 방안
#### 자체 모델 개선
모델을 구성한 후 fine tuning을 충분히 시도하지 못하였다. 이는 타인의 코드를 이해하는 데에 시간이 걸렸기 때문이라고 판단된다. 따라서 `argparse`를 사용하여 변수 값만 입력해주면 다양한 hyper-parameter를 실험해 볼 수 있는 도구를 만들면 좋겠다고 생각했다.
#### 앙상블
여러 모델들이 성능 면에서 큰 차이가 없었으며 모델의 결과에 추가적인 레이어를 쌓는 것 역시 눈에 띄는 성능 변화가 없었기 때문에 앙상블 보다는 단일 모델의 성능향상에 주력했다. 단일 모델의 성능 향상에 집중하였기 때문에 여러 모델을 전부 학습할 여유가 없어 앙상블을 시도하지 못했다.
#### augmentation
이전 RE 문제처럼 데이터를 분류할 수 있는 기준이 마련되지 않아 EDA를 진행하지 못했다. 따라서 어느 데이터가 부족하고 어느 데이터가 편향되어 있는지 등을 확인하지 못해 데이터 증강을 시도하지 않았다. 그럼에도 마스터 클래스에서 발표한 `pororo`처럼 데이터를 증강시켰다면 결과가 좋았지 않았을까 싶다.
## 5. 프로젝트 후기
- 고지호(T2007): Retrieval과 Reader 중 어느 것을 파야하는지, 어떻게 파볼 것인지 방향을 전혀 잡지 못하고 헤맸던 프로젝트였습니다. 다음 강의에서는 더더욱 빠르게 강의를 듣고 다른 git을 참고하여 이미 나와있는 방법들을 빠르게 시도해봐야겠습니다.
- 김민성(T2024): 어려웠던 문제였지만 huggingface 소스를 분석하는 등의 많은 것을 얻어갈 수 있었습니다.
- 김범찬(T2031): Retrieval에 집중하여 Reader 부분에선 도움이 되지 못했다. 한 가지에 집중하는 것도 좋지만 전체적인 과정의 전반적 이해가 우선시되어야 한다는 것을 배웠다.
- 김정현(T2051): 데이터 처리나 모델링에 도움이 되고 싶었으나 한계를 마주하여서 아쉬웠다. 좀 더 열심히 공부해야겠다. 좋은 방법들을 팀원들이 함께 의논해주셔서 많이 배운 것 같다. 감사합니다.
- 심현덕(T2125): 기간안에 태스크를 처리해야 되는 경우 관련 내용을 구글링해서 적극적으로 참고하는 것이 중요하다고 생각했다. 물론 다 해보는것이 최선이지만 성능향상을 위한 우선순위를 두는것? 이 중요하다고 생각되었다.
- 최수홍(T2228): 데이터를 효율적으로 관리하는 방법을 통해 팀원들에게 편하게 데이터를 사용할 수 있도록 제공하였고 타인이 작성한 코드를 약간이나마 분석하여 사용 할 수 있게 됐습니다.
## 6. 참조
* https://arxiv.org/pdf/2105.09680.pdf #klue dataset
* https://arxiv.org/pdf/1907.11692.pdf #RoBERTa
* https://arxiv.org/abs/1810.04805.pdf #BERT
* https://arxiv.org/abs/2003.10555.pdf #Electra
* https://github.com/bcaitech1/p3-mrc-team-ikyo # 1기 MRC github (team Ikyo)