# mrc-level2-nlp-10 ------------------------------- ## ODQA란? ![](https://i.imgur.com/YBIhbW6.png) **ODQA(Open Domain Question and Answering)**:  지문이 따로 주어지지 않고 사전에 구축되어있는 Knowledge resource 에서 질문에 대답할 수 있는 문서를 찾은 후, 해당 문서에서 질문에 대한 대답을 찾는 문제 ## 소개 ![](https://i.imgur.com/sOdxQ2G.png) 본 조에서는 **Retriever-Reader Model**을 통해 ODQA 문제를 해결하고자 하였다. - **Retriever** : Query가 주어졌을 때, Query에 대한 대답을 할 수 있는 문서를 문서 사전에서 찾아오는 모델 - **Reader** : Retriever를 통해 반환된 문서에서, Query와 가장 관련 깊은 Phrase를 찾아오는 모델 ### 요구 사항 ```bash datasets==1.5.0 transformers==4.5.0 tqdm==4.41.1 pandas==1.1.4 scikit-learn==0.24.1 konlpy==0.5.2 Elasticsearch==7.15.1 ``` ### Elastic Search 및 Nori Analyzer 설치 ``` apt-get update && apt-get install -y gnupg2 wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add - apt-get install apt-transport-https echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | tee /etc/apt/sources.list.d/elastic-7.x.list apt-get update && apt-get install elasticsearch service elasticsearch start cd /usr/share/elasticsearch bin/elasticsearch-plugin install analysis-nori service elasticsearch restart ``` ## 설치 방법 ``` git clone https://github.com/boostcampaitech2/mrc-level2-nlp-10.git cd mrc-level2-nlp-10.git bash ./install/install_requirements.sh ``` ## 파일 구성 ### 저장소 구조 ```bash ./assets/ # readme 에 필요한 이미지 저장 ./install/ # 요구사항 설치 파일 ./data/ # 전체 데이터. 아래 상세 설명 ./data_preprocessing/. # 데이터 전처리 arguments.py # 모델, 데이터셋 argument가 dataclass 의 형태로 저장 trainer_qa.py # MRC 모델 평가에 대한 trainer 제공 utils_qa.py # 기타 유틸 함수 제공 preprocessing.py # 학습을 위한 전처리 함수를 반환 postprocessing.py # eval을 위한 후처리 함수를 반환 make_dataset.py # 전처리가 적용된 데이터셋을 반환 modelList.py # config, tokenizer, model를 반환 model.py # QA task를 수행하는 모델들 train.py # MRC 모델 학습 및 평가 inference.py # ODQA 모델 평가 또는 제출 파일 생성 elastic_search.py # 엘라스틱서치를 통해 쿼리에 대한 문서를 조회 ensemble.py # 여러 모델의 결과를 앙상블 sweep.yaml # wandb sweep 설정 파일 ``` ## 데이터 소개 ![](https://i.imgur.com/slKzAjd.png) MRC 데이터의 경우, HuggingFace에서 제공하는 `datasets` 라이브러리를 이용하여 접근이 가능합니다. 해당 directory를 dataset_name 으로 저장한 후, 아래의 코드를 활용하여 불러올 수 있습니다. ```python= # train_dataset을 불러오고 싶은 경우 from datasets import load_from_disk dataset = load_from_disk("./data/train_dataset/") train_dataset = dataset["train"] valid_dataset = dataset["validation"] ``` Retrieval 과정에서 사용하는 문서 집합(corpus)은 `./data/wikipedia_documents.json` 경로로 저장되어있습니다. 약 5만 7천개의 unique 한 문서로 이루어져 있습니다. 데이터셋은 편의성을 위해 Huggingface 에서 제공하는 `datasets`를 이용하여 pyarrow 형식의 데이터로 저장되어있습니다. 다음은 ./data 구조입니다. ```python # 전체 데이터 ./data/ # 학습에 사용할 데이터셋. train 과 validation 으로 구성 ./train_dataset/ # 제출에 사용될 데이터셋. validation 으로 구성 ./test_dataset/ # 위키피디아 문서 집합. retrieval을 위해 쓰이는 corpus. ./wikipedia_documents.json ``` ## 데이터 예시 ### Wikipedia에 "미국 상원"을 검색했을 때의 결과 ![](https://i.imgur.com/TFKMvEW.png) ### 실제 데이터셋의 형태 ![](https://i.imgur.com/aLTCmXQ.png) - `title` : 문서(context)의 제목 - `context` : 문서의 내용 - `question` : 문서를 통해 답을 찾을 수 있는 질문 - `id` : question의 고유 id - `answers` : 문서를 통해 도출해낼 수 있는 답 - `document_id` : 문서의 고유 id ## 훈련, 평가, 추론 ### train data에 대한 argument 는 `arguments.py` 의 `DataTrainingArguments` 에서 확인 가능합니다. 만약 arguments 에 대한 세팅을 직접하고 싶다면 `arguments.py` 를 참고해주세요. klue/roberta-large, klue/bert-base, monologg/koelectra-base-v3-discriminator모델을 사용하여 위에 MLP를 쌓거나 conv1d를 사용하여 QA 리더 모델을 구성했습니다. 각 QA모델 구조는 `model.py`에서 볼 수 있습니다. 또한, wandb sweep이 세팅되어 있어 `sweep.yaml`와 아래 wandb 정보를 수정하시면 fine tuning이 가능하도록 작성되었습니다. wandb를 disabled하고 `defaults`를 수정하면 수동으로 하이퍼파라미터를 변경할 수 있습니다. 각 모델에 대한 weight와 eval 결과는 ./models/train_dataset/{model_name}에 저장됩니다. ```python if __name__ == "__main__": defaults = dict(learning_rate=1e-5, epochs=2, weight_decay=0.009) wandb.init( config=defaults, project="", entity="", name="", ) wandb.agent(entity="", project="", sweep_id="") config = wandb.config main(config) ``` ``` # 학습 예시 (train_dataset 사용) python train.py --output_dir ./models/train_dataset --do_train --overwrite_output_dir ``` ### eval 모델이 train하면서 `training_args.eval_step` 마다 evaluation을 진행합니다. 이때 Exact Match 스코어가 가장 높은 모델이 저장되도록 작성되어 따로 evaluation을 위한 코드를 실행할 필요가 없습니다. ### inference retrieval 과 mrc 모델의 학습이 완료되면 `inference.py` 를 이용해 odqa 를 진행할 수 있습니다. * 학습한 모델의 test_dataset에 대한 결과를 제출하기 위해선 `--model_name_or_path`에 ./model/train_dataset/{model_name}을 넣고 추론(`--do_predict`)을 진행하면 됩니다. * 추론 후 prediction_{model_name}.json와 nbest_prediction_{model_name}.json이 생성됩니다. ``` # ODQA 실행 (test_dataset 사용) python inference.py --output_dir ./outputs/test_dataset/ --dataset_name ../data/test_dataset/ --model_name_or_path ./models/train_dataset/{model_name} --do_predict ``` ### Ensemble RobertaQA, BertQA, ElectraQA의 결과를 앙상블하는 `ensemble.py`가 작성되었습니다. ``` python ensemble.py ``` ### How to submit `inference.py` 파일을 위 예시처럼 `--do_predict` 으로 실행하면 `--output_dir` 위치에 `predictions.json` 이라는 파일이 생성됩니다. 해당 파일을 제출해주시면 됩니다. ### 모델 학습 결과 다음은 실험한 MRC 모델의 결과를 보여줍니다. |model|eval|Public LB|Private LB| |-|-|-|-| |RobertaForQuestionAnswering|72|53.75|50.56| |RobertaQA|**74.58**|**60.00**|**60.56**| |BertQA|57.08|.|.| |ElectraQA|57.08|.|.| |Roberta+Conv-1d|.|59.17|58.06| |Ensemble|.|58.75|58.61|