또르르's 개발 Story

[Stage 2 - 07] 최적의 Hyperparameter 찾기 본문

[P Stage 2] KLUE/프로젝트

[Stage 2 - 07] 최적의 Hyperparameter 찾기

또르르21 2021. 4. 23. 10:08

 1️⃣ Goal

 

  • [BaseLine 작성] (추가 : 4/12, 새로운 Baseline code)

  • [Data Processing]

    - Exploratory Data Analysis (추가 : 4/12, 기간 : 4/12 ~ 4/12 )


    - Cross-validation 사용 (추가 : 4/12)

    - 데이터 불균형 해소 (추가 : 4/12, Huggingface Trainer)

    - 한국어 전처리 (추가 : 4/13, 기간 : 4/13 ~ 4/13 )

    - 새로운 tokenizer 사용 (추가 : 4/12, 기간 : 4/13 ~ ) 

    - 형태소 분류기 -> BERT wordpiece (추가 : 4/13)

    - [ENT][/ENT] tag를 추가해서 train 돌리기 (추가 : 4/14, 기간 : 4/20 ~ )

    - Pororo 사용해보기 (추가 : 4/20, 기간 : 4/20 ~ 4/21)

  • [Model]

    - BERT 모델 사용 (추가 : 4/12, 기간 : 4/14 ~ 4/20 )

    - Roberta 모델 사용 (추가 : 4/20, 기간 : 4/20 ~ 4/21 )

    - xlm-roberta 모델 사용 (추가 : 4/20, 기간 : 4/21 ~ 4/22 )

    - GPT 모델 사용 (추가 : 4/12, 취소 : 생성모델이라 대회 목적과 다름)

    - KoELECTRA 모델 사용 (추가 : 4/12)

    - KoBERT 모델 사용 (추가 : 4/12, 기간 : 4/14 ~ 4/16 )

  • [Training]

    - 앙상블 시도 (추가 : 4/12, 기간 : 4/22 ~ )

    - Hyperparameter 변경 (추가 : 4/12, 기간 : 4/21 ~ )

    - Learning Schedular 사용 (추가 : 4/12, HuggingFace Trainer)

    - 좋은 위치에서 Checkpoint 만들기 (추가 : 4/12, huggingface trainer 사용)

    - Wandb (Auto ML) 사용 (추가 : 4/12)

  • [Deploy]

    - Python 모듈화 (추가 : 4/12, baseline code)

 

 

 

 

2️⃣ Learning

1) 다양한 NLP 모델들

dororo21.tistory.com/147

 

[Stage 2 - 이론] 다양한 NLP 모델들

1️⃣ XLNet BERT는 MASK된 문장을 다시 복원하는 과정을 통해 훈련합니다. 그렇기 때문에 문제점이 발생할 수 있습니다. BERT는 MASK token을 독립적으로 예측하게 됩니다. 따라서 예측의 대상이 MASK toke

dororo21.tistory.com

 

2) koGPT-2 챗봇 만들기

dororo21.tistory.com/148

 

[Stage 2 - 이론] koGPT-2 챗봇 만들기

또르르's 개발 Story [Stage 2 - 이론] koGPT-2 챗봇 만들기 본문 카테고리 없음 [Stage 2 - 이론] koGPT-2 챗봇 만들기 또르르21 또르르21 2021. 4. 23. 00:05 Prev 1 2 3 4 5 ··· 147 Next

dororo21.tistory.com

 

 

3️⃣ Main Task

1) 최적의 Hyperparameter 찾기

대회 마지막날이였기 때문에 최적의 Hyperparameter를 찾아 성능을 높이는 것에 주력했습니다.

 

  • (기존 방식) xlm-roberta 모델 + xlmrobertaTokenizer

    - 하이퍼파라미터 : epoch-10, checkpoint-2600, batch_size-20, label_smoothing_factor: 0.4, Model-"xlm-roberta-large"

    - tokenized_sentence : "# \ entity01개체명 \ entity01 # [SEP] @ ^ entity02 개체명 ^ entity02 @" + "#,@,\,^ 전체 문장"

 

 

 

  • (시도 1) xlm-roberta 모델 + xlmrobertaTokenizer + 하이퍼파라미터 변경

    - 하이퍼파라미터 : epoch-10, checkpoint-2200, batch_size-25, label_smoothing_factor : 0.4, Model-"xlm-roberta-large"

    - tokenized_sentence : "# \ entity01개체명 \ entity01 # [SEP] @ ^ entity02 개체명 ^ entity02 @" + "#,@,\,^ 전체 문장"

    - batch size를 늘려주니 오히려 성능 하락이 있었습니다.

 

 

  • (시도 2) xlm-roberta 모델 + xlmrobertaTokenizer + 하이퍼파라미터 변경

    - 하이퍼파라미터 : epoch-10, checkpoint-2600, batch_size-20, label_smoothing_factor : X, Model-"xlm-roberta-large"

    - tokenized_sentence : "# \ entity01개체명 \ entity01 # [SEP] @ ^ entity02 개체명 ^ entity02 @" + "#,@,\,^ 전체 문장"

    - Label smoothing factor를 빼니 성능이 더 떨어졌습니다.

 

 

2) Hard Votes Ensemble 사용

Ensemble을 사용하기 위해 기존에 만들어 두었던 CSV를 사용했습니다.

(Soft votes나 K-fold cross-validation을 사용하고 싶었지만 시간관계상 부족했습니다. 또한, 모델의 크기도 너무 커서 각각의 모델을 가지고 있기에 어려움이 있었습니다.)

 

Hard votes는 상위 5개의 csv파일을 가지고와서 Ensemble했습니다.

각각의 성능은 78.5%, 78%, 77.6%, 77%, 76.3%의 csv파일을 가지고 왔습니다.

import pandas as pd

from collections import Counter

import operator


MULTI_LABEL_CLASSES = 42


_multi_list = [								# 앙상블하고 싶은 파일 path

       '/content/output (4).csv',
       
       '/content/output (5).csv',
       
       '/content/output (6).csv',
       
       '/content/output (7).csv',
       
       '/content/output (8).csv',
]


multi = []

for idx, path in enumerate(_multi_list):

    multi.append(pd.read_csv(path))
    

submission = {'pred':[]}


for j in range(len(multi[0]['pred'])):

  temp = []
  
  for i in range(len(multi)):
  
      temp.append(multi[i]['pred'][j])
      

  c = Counter(temp)
  
  max_key = max(c.items(), key=operator.itemgetter(1))[0]		# 가장 votes가 많이 나온 key값
  
  submission['pred'].append(max_key)
  

pd_submission = pd.DataFrame.from_dict(submission)

pd_submission.to_csv('submission.csv')

 

결과는 다음과 같습니다.

 

  • (시도 3) hard votes ensemble

    - 현재 최고 성능인 78.5%보다 0.1% 떨어진 성능이 나왔습니다.

    - 성능이 떨어지는 4개를 votes했기 때문에 약간 떨어지게 나왔던 것 같습니다. 만약 78%가 넘는 csv파일들을 모두 ensemble했다면 더 좋은 성능이 나왔을 것 같습니다.

 

 

 

3) Pororo NER 사용법 변경

어떤 캠퍼분이 올려주신 Pororo NER에서 tagging 방식을 수정해서 성능향상이 있었다고 하길래 도움을 받아봤습니다.

def return_tag(tagging_list, is_first):

    tag = ''
    
    if len(tagging_list) != 1:
    
        tagging = [tag[1] for tag in tagging_list if tag[1] != 'O']
        
        if tagging:
        
            tag = ' '.join(list(set(tagging)))
            
        else:
        
            tag = 'o'


    else:
    
        tag = tagging_list[0][1]
        

    assert tag!='', 'tagging이 빔'
    

    if is_first:
    
        return ' ₩ ' + tag.lower() + ' ₩ '
        
    else:
    
        return ' ^ ' + tag.lower() + ' ^ '
sentence_list = []

  for sent, ent01, ent02, start1, end1, start2, end2 in tqdm(zip(dataset['sentence'], dataset['entity_01'], dataset['entity_02'],\
  
          dataset['entity_01_idx0'], dataset['entity_01_idx1'], dataset['entity_02_idx0'], dataset['entity_02_idx1']), total=len(dataset['sentence'])):


      ner_01 = return_tag(ner(ent01), True)
      
      ner_02 = return_tag(ner(ent02), False)

 

이 방식은 tagging_list에서 하나를 선택주는 것이 아닌, 'o'를 제외하고 하나의 문자열로 합쳐서 entity의 개체명으로 사용하는 방법입니다.

 

이 방법에 대한 결과는 다음과 같습니다.

 

  • (시도 4) xlm-roberta 모델 + xlmrobertaTokenizer + Pororo tagging list 수정

    - 하이퍼파라미터 : epoch-10, checkpoint-2600, batch_size-20, label_smoothing_factor : 0.4, Model-"xlm-roberta-large"

    - tokenized_sentence : "# \ entity01개체명 \ entity01 # [SEP] @ ^ entity02 개체명 ^ entity02 @" + "#,@,\,^ 전체 문장"

    - NER을 바꿔줘서 넣어주니 성능향상이 있었습니다.

 

 

4) entity layer 추가 (대회 끝난 후)

model.bert.BertEmbeddings.set_entity_embeddings(entity) # 여기 이렇게 수정해보기

 

 

 

 

4️⃣ Sub Task

 

없음.

 

 

 

5️⃣ Evaluation

 

Data processing
& Tokenizer
Model Training Time Accuracy
4/13 -
EDA
-
    1h -
  "   -
new baseline
code
-
30m 59.3000%
4/14 " -
KoBERT
-
-
epoch : 20
max_len : 128
batch_size : 32
-
23m 72.0000%
4/17 " -
"bert-base-multilingual-cased"
BERT
-
-
epoch : 4
batch_size : 16
-
14m 72.8000%
4/19 -
"entity01[SEP]entity02" + "[ENT]가 들어간 전체 문장"
-
" " 16m 71.2000%
  -
"[ENT]가 들어간 전체 문장"

-
" " 17m 52.5000%
4/20 -
pororo NER
-
"#,@,\,^를 사용해서 구분한 전체 문장"
-
" -
epoch : 10
checkpoint : 5000
-
50m 70.8000%
  -
"#entity01 # [SEP] @entity02 @"
+
"#,@,\,^ 전체 문장"
-
" -
checkpoint : 2500
-
16m 71.6000%
  -
"# \ entity01개체명 \ entity01 # [SEP] @ ^ entity02 개체명 ^ entity02 @"
+
"#,@,\,^ 전체 문장"
-
" -
epoch : 5
checkpoint : 1500
-
12m  74.5000%
4/21 -
"entity01[SEP]entity02" + "[ENT]가 들어간 전체 문장"
-
xlmrobertaTokenizer
(sentencePiece)
-
-
xlm-roberta-large
-
" 31m 74.6000%
  -
"# \ entity01개체명 \ entity01 # [SEP] @ ^ entity02 개체명 ^ entity02 @"
+
"#,@,\,^ 전체 문장"
-
" -
epoch : 10
checkpoint : 2400
batch_size : 32
label_smoothing_factor : 0.5
-
51m 76.3000%
  " " -
checkpoint : 2000
batch_size : 16
label_smoothing_factor:0.3
-
31m 77.6000%
  " " -
checkpoint : 2600
batch_size : 20
label_smoothing_factor : 0.4
46m 78.5000%
4/22 " " -
checkpoint-2200,
batch_size-25
-
34m 77.0000%
  " " -
checkpoint-2600,
batch_size-20,
 
label_smoothing_factor : X
-
33m 76.2000%
  " " -
Hard Votes Ensemble
-
1m 78.4000%
  -
Pororo NER 수정
-
"

-
checkpoint-2400,
batch_size-20, label_smoothing_factor : 0.4
-

46m 79.3000%

 

1) 최적의 Hyperparameter 찾기

 

최적의 Hyperparameter를 찾으려고 했지만, 계속되는 성능 저하로 인해 이렇게 게속 찾으면 안되겠다는 생각이 들었습니다. 따라서 Hyperparameter만 찾으려는 노력보다는 다른 방법에 눈길을 돌렸던 것 같습니다.

 

2) Hard Votes Ensemble

Ensemble 방법 중에 가장 빠르게 할 수 있는 방법이라서 선택했던 것 같습니다. 그렇기 때문에 아쉬움이 남는 것 같습니다. 성능이 잘 나온 모델들 위주로 ensemble을 했다면 성능이 더 향상되었을 것 같습니다.

 

3) Pororo NER 수정

마지막에 NER을 수정하면서 성능 향상이 있었습니다. NER에 대해 기초지식이 부족한 상태에서 시작해서 그런지 NER을 100% 활용하는 방법을 찾지 못했던 것 같습니다. 조금 더 연구해보고 생각해봐야할 분야인 것 같습니다.

 

Comments