- 관계 추출은 지식 그래프 구축을 위한 핵심 구성 요소로, 구조화된 검색, 감정 분석, 질문 답변하기, 요약과 같은 자연어처리 응용 프로그램에서 중요하다.
- 비구조적인 자연어 문장에서 구조적인 triple을 추출해 정보를 요약하고, 중요한 성분을 핵심적으로 파악할 수 있다.
김현수 | 이성구 | 이현준 | 조문기 | 조익노 |
---|---|---|---|---|
Elasticsearch 구성 KoELECTRA 학습 및 평가 BERT(multilingual) 학습 및 평가 |
ColBERT Retriever 적용 및 개선 ColBERT와 BM25 앙상블 |
데이터 전처리 데이터 증강 klue/RoBERTa-large 학습 및 평가 |
K-fold 구현 최종 앙상블 구현 |
BM25 구현 Elasticsearch 구현 |
# data (51.2 MB)
tar -xzf data.tar.gz
# 필요한 파이썬 패키지 설치.
bash ./install/install_requirements.sh
.
|-- README.md
|
|-- arguments.py # data, model, training arguments 관리
|
|-- colbert # dense retrieval(ColBERT) 학습 및 추론
| |-- evaluate.py
| |-- inference.py
| |-- model.py
| |-- tokenizer.py
| `-- train.py
|
|-- es_retrieval.py # sparse retrieval(Elasticsearch) connetion
|-- retrieval.py # tfidf, bm25, elasticsearch retrieval class
|-- settings.json # elasticsearch settings
|
|-- kfold_ensemble_hard.py # k-fold hard voting
|-- kfold_ensemble_soft.py # k-fold soft voting
|-- make_folds.py
|
|-- models # model 저장소
| `-- model_folder
|
|-- outputs # matrix 저장소
| `-- output_folder
|
|-- train.py # reader 학습
|-- train_kfold.py # reader 학습(with. k-fold)
|-- inference.py # retrieval + reader (end-to-end) 평가 및 추론
|-- trainer_qa.py # Trainer class
`-- utils_qa.py # utility function
./data/ # 전체 데이터
./wikipedia_documents.json # 위키피디아 문서 집합. retrieval을 위해 쓰이는 corpus.
총 약 60000개의 위키피디아 문서에서 context 가 온전히 동일한 데이터에 한해서 중복 제거를 통해 약 56000개의 데이터로 진행.
데이터셋은 편의성을 위해 Huggingface 에서 제공하는 datasets를 이용하여 pyarrow 형식의 데이터로 저장되어 있음. 데이터셋의 구성
./data/ # 전체 데이터
./train_dataset/ # 학습에 사용할 데이터셋. train 과 validation 으로 구성
./test_dataset/ # 제출에 사용될 데이터셋. validation 으로 구성
외부 데이터인 KorQuAD, Ko-WIKI를 추가하여 약 12만개의 데이터셋 구성.
./data/ # 전체 데이터
./wiki_korQuAD_aug_dataset/ # 학습에 사용할 외부 데이터셋.
data에 대한 argument 는 arguments.py
의 DataTrainingArguments
에서 확인 가능.
만약 arguments 에 대한 세팅을 직접하고 싶다면 arguments.py
를 참고.
roberta 모델을 사용할 경우 tokenizer 사용시 아래 함수의 옵션을 수정해야함.
tokenizer는 train, validation (train.py), test(inference.py) 전처리를 위해 호출되어 사용됨.
(tokenizer의 return_token_type_ids=False로 설정해주어야 함)
# train.py
def prepare_train_features(examples):
# truncation과 padding(length가 짧을때만)을 통해 toknization을 진행하며, stride를 이용하여 overflow를 유지함.
# 각 example들은 이전의 context와 조금씩 겹쳐짐.
tokenized_examples = tokenizer(
examples[question_column_name if pad_on_right else context_column_name],
examples[context_column_name if pad_on_right else question_column_name],
truncation="only_second" if pad_on_right else "only_first",
max_length=max_seq_length,
stride=data_args.doc_stride,
return_overflowing_tokens=True,
return_offsets_mapping=True,
# return_token_type_ids=False, # roberta모델을 사용할 경우 False, bert를 사용할 경우 True로 표기해야함.
padding="max_length" if data_args.pad_to_max_length else False,
)
# 학습 예시 (train_dataset 사용)
python train.py --output_dir ./models/train_dataset --do_train
-
train.py
에서 sparse embedding 을 훈련하고 저장하는 과정은 시간이 오래 걸리지 않아 따로 argument 의 default 가 True로 설정되어 있음. 실행 후 sparse_embedding.bin 과 tfidfv.bin 이 저장됨. 만약 sparse retrieval 관련 코드를 수정한다면, 꼭 두 파일을 지우고 다시 실행! 안그러면 기존 파일이 load 됨. -
모델의 경우
--overwrite_cache
를 추가하지 않으면 같은 폴더에 저장되지 않음. -
./outputs/
폴더 또한--overwrite_output_dir
을 추가하지 않으면 같은 폴더에 저장되지 않음.
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
- TF-IDF
단어의 등장빈도(TF)와 단어가 제공하는 정보의 양(IDF)를 이용한 function
- BM25
기존 TF-IDF보다 TF의 영향력을 줄인 알고리즘으로 TF의 한계를 지정하여 일정 범위를 유지하도록 한다.
BM25는 문서의 길이가 더 작을수록 큰 가중치를 부여하는 function
- Elasticsearch
Elasticsearch는 기본적으로 scoring function으로 bm25 알고리즘을 사용한다.
위의 bm25와 차이점은 k=1.2
, b=0.75
를 사용했다.
검색엔진의 Elasticsearch는 다양한 플러그인을 사용할 수 있는데 우리는 형태소 분석기인 nori-analyzer를 사용했다. 자세한 setting은 settings.json
파일을 참고할 수 있다.
- ColBERT
ColBERT는 BERT 기반의 Encoder를 사용하는 모델로 Query 인코더의
하나의 BERT모델을 공유하여 이를 구분하기 위해 *[Q], [D]*의 스페셜 토큰을 사용하며 Query와 Document의 relevance score를 구하는 함수는 Cosine similarity를 사용했다.
ColBERT는 각 문서에 대한 점수를 생성하고 Cross-entropy loss를 이용하여 최적화를 진행한다.
다양한 실험을 통해 ColBERT와 BM25간의 가중치를 부여한 Ensemble모델을 채택하여 사용했으며 자세한 실험 내용은 이곳에서 확인할 수 있다.
Masked Language Modeling
과 Next Sentence Prediction
을 통한 사전학습
- klue/bert
- data : 모두의 말뭉치, 위키, 뉴스 등 한국어 데이터 62GB
- vocab size : 32000
- wordpiece tokenizer
- bert-multilingual
- data : 104개 언어의 위키피디아 데이터
- vocab size : 119547
- wordpiece tokenizer
Dynamic Masking
기법과 더 긴 학습 시간과 큰 데이터 사용
- klue/RoBERTa
- data : 위키피디아, 뉴스 등
- vocab size : 32000
- wordpiece
- xlm/RoBERTa
- data : 100개의 언어가 포함되고 필터링된 CommonCrawl (2.5TB)
- vocab size : 250002
- sentencepiece
- Koelectra
- data : 뉴스, 위키, 나무위키 모두의 말뭉치 등 (20GB)
- vocab size : 35000
- wordpiece
각 모델들의 결과값의 확률분포를 통해 가장 큰 확률을 나타내는 값에 해당하는 값을 최종 결과값으로 채택하는 방식
각 모델들이 추론한 N개의 확률 값을 동일한 정답을 가진 확률을 모두 더하여 가장 높은 확률을 채택하는 방식
Soft Voting을 기반으로 총 합이 10이 되도록 하는 가중치를 분배하여 weighted voting을 수행
Model | Exact Match | F1 score |
---|---|---|
klue/bert-base | 46.25 | 54.89 |
bert-base-multilingual | 49.58 | 55.50 |
klue/roberta-large | 69.58 | 76.84 |
xlm-roberta-large | 61.67 | 71.85 |
KoELECTRA | 57.5 | 63.11 |
Public & Private 1st