Day6 (11.1, 월)

  • 앙상블 전략 세우기 및 코드 구현하기

이런 저런 자료를 찾아보다보니 앙상블로 좋은 결과를 도출할 수 있었다는 기록이 많았다. 어차피 대회의 마지막은 앙상블을 시도해 볼 것이기도 하고, 코드를 보니 다양한 방법의 앙상블을 시도할 수 있을 것 같았다. (아직 앙상블로 인해 성능이 월등히 향상되는게 딱히 납득이 가진 않는다...)

오늘의 한 일

앙상블 전략을 수립하고, 코드를 구현한다.

1. Prediction Hard Voting

결과파일 Prediction.json 파일에서 나온 answer들의 출현 빈도로 하드보팅하는 방식

  • 같은 갯수의 단어가 나왔을 때 어느 것을 선택할지

    • 먼저 나온 값

import os
import json
from collections import Counter

def ensemble_with_hardvoting(file_directory, output_file):
    """
    hard voting with prediction files
    Arguments:
        file_directory(str):
            str 로 이루어진 prediction 파일들이 있는 폴더 경로
        output_filename(str):
            str 로 이루어진 output 파일 경로+이름
    Return:
        None
    """
    file_list = os.listdir(file_directory)
    
    json_dataset_list = []

    for file in file_list:
        with open(os.path.join(path, file)) as json_data:
            json_dataset_list.append(json.load(json_data))
            
    ensembled_data = dict()

    for index in range(0, len(json_dataset_list[0].items())):
        temp_list = []
        for json_data in json_dataset_list:
            temp_list.append(list(json_data.values())[index])
        temp_counter = Counter(temp_list)
        ensembled_data[list(json_data.keys())[index]] = temp_counter.most_common()[0][0]
        
    with open(output_file, 'w', encoding='UTF-8') as fp:
        json.dump(ensembled_data, fp, indent=4, ensure_ascii=False)

2. Probability Soft Voting

nbest_predictions.json 파일을 보면 start_logit , end_logit , probability 값이 존재한다. 현재 코드는 이 중 가장 높은 값을 정답으로 선정하게 되어있는데 여기서 probability를 합산하여 높은 값을 정답으로 하게끔 앙상블을 진행.

[방법1]

현재 코드상으로 nbest_predictions.json 파일이 항상 생성되도록 되어있다. 이 파일을 가지고 앙상블을 진행하는 방법.

  • 추출되는 단어가 다를 수 있음.

  • 단어는 같지만, 위치가 다를 수 있음...

3. validation set 사용하기

Train Data가 3952개로 매우 작다... validation 240개가 얼마 되진 않지만 이도 학습하는 것이 Test를 추론함에 있어서는 도움이 될 것이라고 생각 되었다.

train_dataset = concatenate_datasets([datasets['train'], datasets['validation']])

결과 값은 EM 50.000 / F1 62.470 으로 추가하기전과 EM값은 차이가 없었다... 너무 적은 양이었던것 같다.

4. NER로 Augmentation 하기

정답이 나올 수 있는 단어는 주로 명사형태이다. NER 태깅을 통해 단어의 개체명을 입력시키고, 해당 값을 정답으로 하는 질문을 생성하여, 학습데이터를 증강하고자 하였다.

from pororo import Pororo
ner =Pororo(task="ner", lang="ko")

ner("마이클 제프리 조던(영어: Michael Jeffrey Jordan, 1963년 2월 17일 ~ )은 미국의 은퇴한 농구 선수이다.")
[('마이클 제프리 조던', 'PERSON'),
 ('(', 'O'),
 ('영어', 'CIVILIZATION'),
 (':', 'O'),
 (' ', 'O'),
 ('Michael Jeffrey Jordan', 'PERSON'),
 (',', 'O'),
 (' ', 'O'),
 ('1963년 2월 17일 ~', 'DATE'),
 (' ', 'O'),
 (')은', 'O'),
 (' ', 'O'),
 ('미국', 'COUNTRY'),
 ('의', 'O'),
 (' ', 'O'),
 ('은퇴한', 'O'),
 (' ', 'O'),
 ('농구 선수', 'OCCUPATION'),
 ('이다.', 'O')]
  • 'O' (조사, 특수문자를 제거)

위와 같이 추출한 단어를 정답으로 두고 pororo 질문생성기(강민님)로 생성해 보았다.

하지만 안타깝게도 질문과 정답이 매칭되지 않는 케이스가 반정도 되어서 직접 필터링을 하지 않을 것이라면 사용하기 어렵다고 생각되었다. 기존에 title을 정답으로 두고 생성했던 것도 마찬가지 문제를 겪었다.

시도해 보고자 하는 것은 다시 해당 질문으로 정답을 찾도록 해보는 작업을 진행하고자 했다. 또한 retriever를 학습함에 있어서는 context와 question만으로도 의미가 있는 작업이기에 10,000건 정도의 증강을 시키고 오늘 작업을 마무리 할 수 있었다.

Last updated