Day8 (10.4, 월)

  • 데이터 전처리 작업 (증강, 정제)

  • 제출 1회하기

작업 결과물

1. 오기입된 Type 데이터 제거

label_type_mapped = {
    "no_relation": []
    ,"org:dissolved": [('ORG', 'DAT')] # 지정된 조직이 해산된 날짜 O
    ,"org:founded": [('ORG', 'DAT')] # 지정된 조직이 설립된 날짜 O
    ,"org:place_of_headquarters": [('ORG', 'LOC'), ('ORG', 'ORG'), ('ORG', 'POH')] # 지정된 조직의 본부가 있는 장소(본사위치)
    ,"org:alternate_names": [('ORG', 'ORG'), ('ORG', 'POH')] # 지정된 조직을 참조하기 위해 사무실 이름 대신 호출되는 대체 이름
    ,"org:member_of": [('ORG', 'ORG'), ('ORG', 'POH'), ('ORG', 'LOC')]
    ,"org:members": [('ORG', 'ORG'), ('ORG', 'POH'), ('ORG', 'LOC')]
    ,"org:political/religious_affiliation": [('ORG', 'ORG'), ('ORG', 'POH')]
    ,"org:product": [('ORG', 'POH')]
    ,"org:founded_by": [('ORG', 'PER')]
    ,"org:top_members/employees": [('ORG', 'PER')]
    ,"org:number_of_employees/members": [('ORG','NOH')]
    ,"per:date_of_birth": [('PER', 'DAT')]
    ,"per:date_of_death": [('PER', 'DAT')]
    ,"per:place_of_birth": [('PER', 'LOC')]
    ,"per:place_of_death": [('PER', 'LOC')]
    ,"per:place_of_residence": [('PER', 'LOC')]
    ,"per:origin": [('PER', 'LOC'), ('PER', 'ORG')]
    ,"per:employee_of": [('PER', 'ORG')]
    ,"per:schools_attended": [('PER', 'ORG')]
    ,"per:alternate_names": [('PER', 'PER')]
    ,"per:parents": [('PER', 'PER'), ('PER', 'POH')]
    ,"per:children": [('PER', 'PER'), ('PER', 'POH')]
    ,"per:siblings": [('PER', 'PER'), ('PER', 'POH')]
    ,"per:spouse": [('PER', 'PER'), ('PER', 'POH')]
    ,"per:other_family": [('PER', 'PER'), ('PER', 'POH')]
    ,"per:colleagues": [('PER', 'PER')]
    ,"per:product": [('PER', 'POH')]
    ,"per:religion": [('PER', 'ORG'), ('PER', 'POH')]
    ,"per:title": [('PER', 'POH')]
}
  • 내가 생각했을때 label 별로 조합이 가능한 type pair를 명명하고, 이를 활용하여 일치하지 않는 데이터를 제거 한다.(수정하고자 했으나, 양이 많이 힘듬)

2. 중복 건 제거

  • 중복 데이터 42건 + label만 다르게 기입된 건 제거

  • 총 30,798 건 남김

3. 데이터 증강작업 with AEDA

import random

random.seed(42)

# Insert punction words into a given sentence with the given ratio "punc_ratio"
def insert_punctuation_marks(original_data, punc_ratio=0.3):
    PUNCTUATIONS = ['.', ',', '!', '?', ';', ':']    
    new_data = original_data.copy()

    if original_data.subject_idx < original_data.object_idx:
        sentence_s = original_data.sentence[:original_data.subject_idx[0]]
        sentence_m = original_data.sentence[original_data.subject_idx[1]+1:original_data.object_idx[0]]
        sentence_e = original_data.sentence[original_data.object_idx[1]+1:]
    else:
        sentence_s = original_data.sentence[:original_data.object_idx[0]]
        sentence_m = original_data.sentence[original_data.object_idx[1]+1:original_data.subject_idx[0]]
        sentence_e = original_data.sentence[original_data.subject_idx[1]+1:]


    words_s = sentence_s.split(' ')
    words_m = sentence_m.split(' ')
    words_e = sentence_e.split(' ')

    new_line = []

    words_length = len(words_s) + len(words_m) + len(words_e)
    q = random.randint(1, int(punc_ratio * words_length + 1))
    qs = random.sample(range(0, words_length), q)

    j = 0

    for idx, words in enumerate([words_s, words_m, words_e]):
        for word in words:
            if j in qs:
                new_line.append(PUNCTUATIONS[random.randint(0, len(PUNCTUATIONS)-1)])
                new_line.append(word)
            else:
                new_line.append(word)
            j += 1

        length = 0 if len(new_line) == 0 else sum([len(w) for w in new_line]) + len(new_line)

        if idx == 0:
            if original_data.subject_idx < original_data.object_idx:
                new_data.subject_idx = (length, length+len(original_data.subject_word)-1)
                new_line.append(original_data.subject_word)
            else:
                new_data.object_idx = (length, length+len(original_data.object_word)-1)
                new_line.append(original_data.object_word)
        elif idx == 1:
            if original_data.subject_idx < original_data.object_idx:
                new_data.object_idx = (length, length+len(original_data.object_word)-1)
                new_line.append(original_data.object_word)
            else:
                new_data.subject_idx = (length, length+len(original_data.subject_word)-1)
                new_line.append(original_data.subject_word)

    new_data.sentence = ' '.join(new_line)
    return new_data
  • subject_indexobject_index 를 지정해줘야하는 문제점 때문에 코드가 다소 지저분해졌다. sub, obj 의 앞뒤 문장을 각각 나눠서 PUNCTUATION 을 추가해주었다.

  • 우선 데이터가 2000개 미만인 데이터에 한해서 2000개 까지 증강작업을 진행하였는데 문제가 있지 않을까 고민이 되었다.

    • 데이터 수가 50개 남짓인 데이터에 대해서 2000개 까지 증강하게 되면, 과적합이 되지않을까??

    • AEDA를 통해 증강해도 되는 비율(?) 정도를 알아봐야 될 것 같다.

제출

1차 제출

model_name = klue/bert-base
optimizer_name = AdamW
scheduler_name = CosineAnnealingLR

loss_name = CrossEntropy_weighted
num_train_epochs = 10
learning_rate = 5e-5
batch_size = 64
warmup_steps = 500
weight_decay = 0.01
early_stopping = 3 # with eval/loss
random_state= 42

eval_steps = 500
seed = 42
  • 증강된 데이터 사용

  • Wandb 에서는 validation set과 증강된 데이터에 중복이 발생하여 유의미한 그래프를 얻지 못함.

    • 과적합으로 너무 좋게 나옴.. (살짝 설렜)

🤷‍♂️❓ 원인

  • 무분별한 증강은 성능향상에 도움이 되지않을 것 같다. 적정 비율의 증강이 필요할 듯

💭 해볼 만한 것.

  • Train set / Validation set 나눈 후 Train set을 증강해서 wandb로 성능체크

  • 모든 데이터 2배로 증강해서 테스트 (class 비율을 1:1:...:1 이 아닌 기존 비율 그대로 증강)

Summary

오늘은 코드를 작성하는데 시간이 다소 많이 소요되어서, 시도해보고자 했던 것들을 하지 못하였다. 내일은 수업을 들으면서 증강, 정제 python 코드 정리 + 모델 테스트를 진행해보면 어떨까 싶다. (roberta-large가 좋다는 소문소문)

Last updated