- Retriever Task와 Reader Task를 구성하고 통합하여, 질문을 던졌을 때 답변을 해주는 ODQA 시스템 개발
- Retriever
- 방대한 Open Domain Dataset에서 질의에 알맞은 지문을 찾아오는 Task
- Machine Reading Comprehension(MRC)
- 지문이 주어진 상황에서 질의에 대해 응답하는 기계 독해 Task
- Open-Domain Question Answering(ODQA)
- Retriever 와 MRC Task를 결합한 시스템
아래는 제공하는 데이터셋의 분포를 보여준다.
데이터셋은 편의성을 위해 Huggingface 에서 제공하는 datasets를 이용하여 pyarrow 형식의 데이터로 구성
.
mrc-level2-nlp-06
|-- arguments.py -> 학습 관련 설정
|-- dense_retrieval.py -> retriever 모델 학습
|-- inference.py
|-- elastic_inference.py
|-- install
| `-- install_requirements.sh
|-- retrieval.py
|-- train.py -> reader 모델 학습
|-- trainer_qa.py
|-- utils_qa.py
|-- utils
| |-- init_wandb.py
| |-- postprocess.py
| |-- preprocess.py
| |-- trainer_qa.py
| |-- utils_dpr.py
| `-- utils_qa.py
`-- wandb_arguments.py -> wandb 설정
data에 대한 argument 는 arguments.py
의 DataTrainingArguments
에서 확인 가능하다.
bash install_requirements.sh
- Custom Hyperparameter :
arguments.py
참고 - Using roberta Model : tokenizer 사용시 아래 함수의 옵션을 수정
- tokenizer의 return_token_type_ids=False로 설정
# Retriever 학습 예시 # 내부에서 변경
python dense_retriver.py
# Reader 학습 예시 (train_dataset 사용)
python train.py --output_dir ./models/train_dataset --do_train
- MRC 모델의 평가 :
--do_eval
사용 - 위의 예시에
--do_eval
을 추가로 입력해서 훈련 및 평가를 동시에 진행할 수도 있다.
# mrc 모델 평가 (train_dataset 사용)
python train.py --output_dir ./outputs/train_dataset --model_name_or_path ./models/train_dataset/ --do_eval
retrieval 과 mrc 모델의 학습이 완료되면 inference.py
를 이용해 odqa 를 진행한다.
- 학습한 모델의 test_dataset에 대한 결과를 제출하기 위해선 추론(
--do_predict
)만 진행한다. - 학습한 모델이 train_dataset 대해서 ODQA 성능이 어떻게 나오는지 알고 싶다면 평가(--do_eval)를 진행한다.
# ODQA 실행 (test_dataset 사용)
# wandb 가 로그인 되어있다면 자동으로 결과가 wandb 에 저장되고 아니면 단순히 출력된다.
python inference.py --output_dir ./outputs/test_dataset/ --dataset_name ../data/test_dataset/ --model_name_or_path ./models/train_dataset/ --do_predict
- DataTrainingArguments
dpr:bool - 학습된 dpr encoder와 bm25를 정한 비율로 결합해서 inference
dpr_negative:bool - dense_retriver.py에 있는 코드를 통해 학습된 모델로 inference
- 학습한 모델의 test_dataset에 대한 결과를 제출하기 위해선 추론(
--do_predict
)만 진행하면 됩니다. 위와 과정은 동일하고 실행 파일만 변경하면 됩니다. (elastic search를 통한 retrieval 구성이 포함되어 있는 파일입니다.) - elastic search 사용을 위해 현재 버전으로 저장되어 있는 폴더 내에 user_dic을 만들고 안에 stopwords.txt를 넣어야 한다.
# ODQA 실행 (test_dataset 사용)
python elastic_inference.py --output_dir ./outputs/test_dataset/ --dataset_name ../data/test_dataset/ --model_name_or_path ./models/train_dataset/ --do_predict
- Data Training Arguments
elastic_score: bool = field(
default = True,
metadata={"help": "whether to score to top_k of each query"}
)
# elastic search로 context만 뽑아내고 싶다면 False
# score도 함께 뽑아내고 싶다면 True
inference.py
파일을 위 예시처럼 --do_predict
으로 실행하면 --output_dir
위치에 predictions.json
이라는 파일이 생성되고 해당 파일을 제출한다.
- 동일한 문장의 데이터가 42개, 동일하면서도 라벨이 달랐던 데이터가 5개 존재했고 둘 중 올바른 라벨로 수정하였다.
preprocess_wiki_documents(contexts)
- 들어온 contexts 중에 한글이 포함되지 않거나, 한글이 포함되었지만 code로 구성된 context, 그리고 특정 글자를 포함하는 contexts를 제거하였고, 남은 contexts 에서 특정 문자, 또는 특정 문자를 포함하는 문장을 제거하였다.
use_wiki_preprocessing=True
인 경우 해당 함수를 사용할 수 있다.
-
DPR retriever
- TF-IDF , BM25 기반 Negative Sample: wiki-context와 mrc-context를 내적하는 방법으로 접근했다.
- In-Batch: query와 positive sentence로 이루어진 미니 배치 내부에서 다른 example들 사이에서 내적을 통한 유사도에서 가장 높은 유사도에 해당하는 example으로 prediction한다.
- 단일 DPR을 활용하기 보단 BM25의 점수를 선형결합해서 단일 모델 중 가증 큰 성능을 보였다.
- BM25 단일모델 EM : 55 -> BM25+DPR EM : 61.240
-
BM25 retriever
- Okapi bm25 github의 라이브러리를 상속해서 구현했다.
- bm25, bm25L, bm25Plus, 다양한 토크나이저 실험 중 성능이 가장 좋은 bm25와 klue/bert-base 토크나이저를 사용하여 비교했다.
- retrieval accuracy: top 1: 0.5875, top 10: 0.9041, top 20: 0.9208
-
Elasticsearch retriever
- Okapi bm25의 성능이 task에서 높은 것을 파악하고 빠르게 동작시키기 위해 사용했다.
- python 내에서 돌아가도록 Elastic search의 index setting을 구성했다.
- stopwords filter와 pororo 라이브러리 기반의 tokenizing을 통해 context를 분석했다.
- KLUE/Roberta-large
- 다른 기학습 가중치를 활용해보았으나 KLUE 데이터셋을 기반으로 전이 학습된 모델이 평균적으로 더 높은 성능을 보였다.
-
Ensemble
-
성능이 향상된 방법
-
Baseline
-
train.py
에서 sparse embedding 을 훈련하고 저장하는 과정은 시간이 오래 걸리지 않아 따로 argument 의 default 가 True로 설정되어 있다. 실행 후 sparse_embedding.bin 과 tfidfv.bin 이 저장이 된다. 만약 sparse retrieval 관련 코드를 수정 시 존재하는 파일이 load되지 않도록 두 파일을 지우고 다시 실행한다 -
모델의 경우
--overwrite_cache
를 추가하지 않으면 같은 폴더에 저장되지 않는다. -
./outputs/ 폴더 또한
--overwrite_output_dir
을 추가하지 않으면 같은 폴더에 저장되지 않는다.
- 나요한_T2073 : https://github.com/nudago
- 백재형_T2102 : https://github.com/BaekTree
- 송민재_T2116 : https://github.com/Jjackson-dev
- 이호영_T2177 : https://github.com/hylee-250
- 정찬미_T2207 : https://github.com/ChanMiJung
- 한진_T2237 : https://github.com/wlsl8135
- 홍석진_T2243 : https://github.com/HongCu