boostcampaitech4lv23nlp1 / final-project-level3-nlp-03

Multi-Modal Model for DocVQA(Document Visual Question Answering)
3 stars 0 forks source link

The reason why 'question marker' does not have any effect on our project unlike having on 'Relation Extraction' task #30

Open chanmuzi opened 1 year ago

chanmuzi commented 1 year ago

Question Marker를 추가한 이유

모델이 추론을 질문을 이해하고 답변을 도출하는 과정에서 어떤 부분에 집중하게 되는지 확인한 결과에 따르면, text 기준 Question + Context의 구조에서 Question에는 거의 가중치를 두지 않는 경향이 있음을 알 수 있었다. 따라서 질문에 대한 보다 정확한 이해를 할 수 있도록 Question의 앞뒤에 각각 [QUE], [/QUE] 라는 special token을 추가하고 그 결과를 이전과 비교해보기로 했다.

Question Marker 추가 방법

  1. LayoutLMPreprocess.py 파일에서 문장이 tokenizer에 입력으로 주어지기 전에 각 question의 앞뒤에 각각 [QUE], [/QUE]라는 문자열을 추가한다.
    
    for idx in range(len(train_data['question'])):
    tmp = train_data['question'][idx]
    train_data['question'][idx] = '[QUE] ' + tmp + ' [/QUE]'

tokenized_sentences = self.tokenizer( train_data['question'], train_data['words'], train_data['boxes'], truncation="only_second", # max_seq_length까지 truncate한다. pair의 두번째 파트(context)만 잘라냄. max_length=self.max_length, stride=self.stride, return_token_type_ids=True, # BERT 모델일 경우에만 반환 return_overflowing_tokens=True, # (List[int]) : 여러개로 쪼갠 문장들이 하나의 같은 context라는 것을 나타내주는 리스트, batch 단위일때 사용합니다. padding="max_length", add_special_tokens=True # 추가 토큰 반영해주는 옵션 )

이때 tokenizer에 `add_special_tokens=True`를 해주어야 [QUE]와 [/QUE]를 special token으로 처리해준다.

2. train.py 파일에서 tokenizer 선언 이후 tokenizer에 special token을 추가해준다.
```python
tokenizer = AutoTokenizer.from_pretrained(config.model.model_name, use_fast=True)
tokenizer.add_special_tokens({"additional_special_tokens":["[QUE]","[/QUE]"]})

이때 dict 형태로 special token 리스트를 전달해야 제대로 반영된다. special token이 추가되었는지는 tokenizer.__call__을 통해 확인할 수 있다.

  1. train.py 파일에서 model 선언 이후 token embedding size를 조정한다.
    model = getattr(Model, config.model.model_class)(
    model_name = config.model.model_name,
    num_labels=2,
    dropout_rate = config.train.dropout_rate,
    )
    # embedding size 조정    
    model.model.resize_token_embeddings(tokenizer.vocab_size + 2)

    여기서는 model이 한 번 packaging 되어 있으므로 model.model로 접근을 해야한다. 우리가 추가한 special token은 두 개이므로 기존 tokenizer의 vocab size에 2를 더해준다.

    model.model.get_input_embeddings

    참고로 위 코드를 통해 input_embedding에 대한 정보를 확인할 수 있다.

Question Marker를 적용하기 전후의 결과 비교

적용하기 전

image image

적용한 후

image

여러 카테고리 중 우리는 'Figure/Diagram' 유형에 집중하기로 했다. 결과 분석 당시에도 해당 유형에 대해 분석을 진행했고 그 결과를 기반으로 작업을 진행했으나 유의미한 성과는 없었다. 'Figure/Diagram'에 대해서는 다소 유의미한 성능 향상이 있지만 다른 유형에 대해서는 오히려 성능이 떨어지게 된 것을 알 수 있다.

chanmuzi commented 1 year ago

Question Marker가 유의미한 영향을 주지 못한 이유를 추론한 결과

  1. 본 프로젝트에 사용되는 모델의 입력으로 이미 token_type_ids를 사용하고 있다.
  2. question marker를 train dataset에만 추가하여 validation, inference에는 noise를 추가한 꼴이 되었다.

token_type_ids

tokenizer에 입력을 줄 때, return_token_type_ids=True 옵션을 주어야지 반환된다. 두 개 이상의 문장이 합쳐졌을 때 앞의 문장인지 뒤의 문장인지를 0,1로 구분해준다. 만약 max_len = 10이고 앞 문장의 길이는 3, 뒷 문장의 길이가 5인 경우 다음 결과가 반환된다.

token_type_ids = [0,0,0,1,1,1,1,1,0,0]

1. token_type_ids

marker를 추가하는 아이디어는 Relation Extraction 당시 query에 대한 marker를 추가하던 작업에서 착안한 것이다. 따라서 본 프로젝트에 적용한 것과 Relation Extraction 프로젝트에 적용한 코드를 비교해보았다.

따라서 special token을 추가하는 이 작업이 큰 영향을 주지 못한 것으로 볼 수 있다.

2. validation, test set

작업자의 미숙함으로 dataset의 question 앞뒤에 special token을 추가하는 작업을 train dataset에 대해서만 진행했다. 따라서 validation이나 inference 과정에서 추가된 special token은 오히려 noise가 되었을 가능성이 높다.

위에서 기술한 바와 같이 이미 token_type_ids라는 embedding이 존재하는 상황에서 special token을 추가하는 작업 자체가 무의미한 것이 될 수 있으나, 모델이 기존에 비해 question에 더욱 집중할 수 있게 되는지는 valid/test set에 대해서도 동일한 작업을 진행하여 실험한 뒤 결과를 분석해봐야 알 수 있을 것이다.