경진대회 개요
Dialogue Summarization 경진대회는 주어진 한글 데이터를 활용하여 일상 대화에 대한 요약을 효과적으로 생성하는 모델을 개발하는 대회다.
이 대회에서는 ROUGE-1-F1, ROUGE-2-F1, ROUGE-L-F1, 총 3가지 종류의 metric으로부터 산출된 평균 점수를 더하여 최종 점수를 계산한다.
현재 데이터 건수는 다음과 같다.
- train : 12457
- dev : 499
- test : 250
- hidden-test : 249
데이터 구성은 다음과 같다.
최소 2 턴, 최대 60 턴으로 대화가 구성되어 있고, 대화(dialogue)를 보고 이에 대한 요약(summary)을 예측하는 것이 최종 목표다.
베이스라인 코드의 변수들은 다음과 같다.
- model_name: "digit82/kobart-summarization"
- lr_scheduler_type: 'cosine'
- optim: 'adamw_torch',
- epoch
여기서 아무것도 수정하지 않고 실행한 결과는 다음과 같다.
차례대로 ROUGE-1, ROUGE-2, ROUGE-L, FINAL_RESULT 값이다.
여기서 dialogue의 발화자를 표시하는 #Person1#, #Person2# 같은 스페셜 토큰이 있는데 이 외에도 개인정보 같은 것들에 대한 스페셜 토큰을 추가해주고 수행한 결과는 다음과 같다.
여기서 일단 데이터 증강을 시도해 봤다.
데이터 증강 - Back Translation
AEDA보다 조금 더 확실한 방법 같아서 한글 -> 영어 -> 한글로 back translation을 해줬다.
def back_translation(text, src_lang='ko', intermediate_lang='en'):
translator = Translator()
try:
translated = translator.translate(text, src=src_lang, dest=intermediate_lang).text
back_translated = translator.translate(translated, src=intermediate_lang, dest=src_lang).text
return back_translated
except Exception as e:
return text # 오류 발생 시 원본 텍스트 반환
잘 진행되고 있는지 확인하기 위해 배치로 나눠서 프린트하는 코드를 추가하고 데이터 증강이 완료되고 데이터를 확인해 보자.
batch_size = 50
new_rows = []
for start_idx in range(0, len(train_df), batch_size):
batch = train_df.iloc[start_idx:start_idx + batch_size]
for index, row in batch.iterrows():
new_dialogue = back_translation(row['dialogue'].replace("\\n", "\n")) # Back Translation 수행
new_fname = f"train_{len(train_df) + len(new_rows)}" # 새로운 fname 생성
new_row = {
'fname': new_fname,
'dialogue': new_dialogue,
'summary': row['summary'],
'topic': row['topic']
}
new_rows.append(new_row)
print(f"Batch {start_idx // batch_size + 1} completed.") # 배치 처리 완료 메시지 출력
이렇게 데이터를 증강시키고 제출했을 때의 성능이다.
저번보단 올랐지만 이미 우리 팀에서 49.4839를 찍었기 때문에 최고성능은 아니다.
우리 팀에서 최고 성능인 49.4839가 나오게 된 방법은 다음과 같다.
- back tranlation
- 모델 수정 (gogamza/kobart-base-v2)
- 학습 데이터셋에서 자음/모음 필터링
- dialogue 중에 소괄호 안에 있는 내용(다른 발화자가 끼어드는듯한 내용) 삭제한 데이터
이렇게 진행했을 때 최고 성능이 갱신됐다.
일단 정말 데이터 증강이 유의미한지 확인해 보기 위해 데이터 증강을 한 데이터셋이랑 원본 데이터셋을 돌려서 성능차이가 있는지 확인해 봤는데 데이터 증강이 된 데이터로 학습했을 때 약 1.5점 더 높은 성능을 보였다!!
SEED 고정
이렇게 저렇게 시도하다가 같은 코드를 여러 번 돌렸을 때 성능이 계속 바뀌는 이슈가 생겼었다. 비록 코드 안에 seed를 고정시켜 주는 부분이 있는데 우리가 놓치고 있는 부분이 있는 것 같아서 따로 시드를 고정시켜 주는 코드를 추가해 줬다.
from transformers import set_seed
set_seed(42)
모델 수정 (bart-r3f)
이 모델은 BART를 기반으로 하고 AIHub의 한국어 대화 요약 데이터를 활용하여 학습되었다. 특히 R3F 기법을 적용하여 대화 요약 성능을 향상했다.
https://huggingface.co/alaggung/bart-r3f?utm_source=chatgpt.com
아까 성능이 잘 나온 데이터셋에서 모델만 수정해주고 했을 때 나온 성능이다.
그렇게 생각보다 많이 오르진 않았다.
이상치 제거
일단 20000건이 넘는 학습 데이터셋이 있어서 dialogue의 길이가 75% 이상인 데이터는 지워줬다.
def remove_outliers(data, column):
"""
Remove upper outliers based on the IQR method for a specific column.
Args:
data (pd.DataFrame): DataFrame containing the data.
column (str): The column name to check for outliers.
Returns:
pd.DataFrame: DataFrame with outliers removed.
"""
Q1 = data[column].quantile(0.25)
Q3 = data[column].quantile(0.75)
IQR = Q3 - Q1
upper_bound = Q3 + 1.5 * IQR
return data[data[column] <= upper_bound]
# Remove outliers for dialogue and summary columns
filtered_data = train_df.copy()
columns_to_filter = ['dialogue_char_count', 'summary_char_count', 'dialogue_word_count', 'summary_word_count']
for column in columns_to_filter:
filtered_data = remove_outliers(filtered_data, column)
# 결과 확인
print(f"Original Data Count: {len(train_df)}")
print(f"Filtered Data Count: {len(filtered_data)}")
그리고 기존 kobert 모델에서 이상치를 제거하고 실행해 보니 성능이 이렇게 나왔다.
(사실상 스페셜 토큰만 추가한 것보다 더 안 좋게 나왔다ㅠㅠ)
WandB Sweep
사실 벌써 하이퍼파라미터 튜닝을 하면 의미가 없긴 하지만 이때는 몰랐다,,,,,,,,,
일단 데이터 전처리는 놔두고 하이퍼파라미터 튜닝을 알아봤다. sweep에 사용된 모델은 hyunwoongko/kobart 이 모델이다.
- 특징
- SKT에서 공개한 KoBART의 미세조정되지 않은 일반 모델 (Pre-trained BART).
- 특정 데이터셋에 학습되지 않았으며, 사용자가 원하는 작업(예: 대화 요약)에 맞게 파인튜닝 필요.
- 장점
- 다양한 작업에 맞게 커스터마이즈 가능.
- 대화 데이터를 직접 학습시켜 대화 요약에 더 최적화 가능.
- 한계
- 학습 데이터와 파인튜닝 작업이 추가로 필요.
그리고 sweep config는 다음과 같이 설정했다.
# Sweep Configuration
sweep_config = {
"method": "bayes",
"metric": {"name": "avg_rouge", "goal": "maximize"},
"parameters": {
"epoch": {"values": [7, 10, 14]},
"lr": {"min": 1e-5, "max": 1e-3},
"batch_size": {"values": [8, 16, 32]},
},
}
# Sweep 생성
sweep_id = wandb.sweep(sweep_config, project="nlp_pj_yj")
그리고 sweep으로 찍을 로그는 다음과 같다.
wandb.log({
"lr": lr,
"batch_size": batch_size,
"epoch": epoch,
"avg_rouge": avg_rouge,
"rouge-1": scores["rouge1"].mid.fmeasure,
"rouge-2": scores["rouge2"].mid.fmeasure,
"rouge-L": scores["rougeL"].mid.fmeasure,
})
이렇게 하고 베스트 모델로 제출하니 최하점수,, 뭐야,,,,
그 외 시도해 본 방법들,,,
데이터 전처리 위주로 1주 차는 좀 보냈던 것 같다.
1. 한글 데이터의 오타랑 띄어쓰기를 고쳐주려고 Py-hanspell을 적용해보려고 했는데 이 라이브러리는 제대로 동작하지 않았다.
2. 한국어 불용어도 학습 데이터셋에서 제거해 주고 스페셜 토큰(#으로 둘러싸인 단어)들 중에서 #으로 제대로 안 닫힌 것들도 있어서 그런 것들을 잘 고쳐주고 학습시켜봤는데 성능 개선이 되지 않았다.
3. 우리는 학습에 dialogue, summary 컬럼만 사용했어서 혹시 topic 컬럼도 학습에 추가하면 좋지 않을까 해서 '[Topic - 토픽] dialogue' 이렇게 topic+dialogue를 합친 컬럼을 새로 만들어서 학습에 적용시켰는데도 성능 개선이 되지 않았다.
앙상블에 대한 얘기도 나왔는데 사실 회귀문제나 분류문제가 아니라 대화 요약에 대한건 어떻게 모델을 앙상블 해야 할지조차 막막했다. 그리고 원래 앙상블은 제일 마지막쯤에 시도해 보는 방법이니(아직 뭐가 베스트 모델이고 최고성능이 뭔 지조차 잘 모르는 상황) 모델 앙상블은 조금 미뤄두기로 했다,,,,
위에 상세하게 작성하진 않았지만 우리가 시도한 모델은 다음과 같다.
- kobert
- t5
- bert_r3f
경진대회 2주차 + 자체 평가 및 회고는 👇 요기에!
2024.12.01 - [Upstage AI Lab 4기] - Dialogue Summarization (일상 대화 요약) 경진대회 2주차 + 자체 평가 및 회고
'Upstage AI Lab 4기' 카테고리의 다른 글
Dialogue Summarization (일상 대화 요약) 경진대회 2주차 + 자체 평가 및 회고 (0) | 2024.12.01 |
---|---|
[CV 경진대회] 최종 제출, 자체 평가 및 회고 (1) | 2024.11.08 |
[CV 경진대회] offline 데이터 증강 그리고 하이퍼파라미터 수정 (7) | 2024.11.07 |
[CV 경진대회] TTA 실패기,,, (0) | 2024.11.04 |
[CV 경진대회] K-fold 적용 (0) | 2024.11.04 |