[AI][NLP] 한국어 요약 모델 개발 코드 및 최적화 방법
참여 경진대회
한국어 문서 요약 경진대회
https://aiconnect.kr/competition/detail/223/task/272/taskInfo
- 최종 5위
모델 상세
HuggingFace T5 모델을 기반으로 파인튜닝된 한국어 뉴스 요약 T5 모델을 대회 데이터(전처리)로 파인튜닝하여 사용
코드 최적화 방법
- Baseline 모델 코드
- GPT 구조 이해 및 모델 구현 학습
- 자원 사용량과 학습 시간 문제 발생
- GPU RAM 초기화 방법 - colab에서 GPU RAM 초기화 방법
- 기존 모델에 파인튜닝 시도
- HuggingFace의 여러 모델로 파인튜닝
- 기존 성능이 좋았던 T5 모델을 채택
- 전처리 및 최적화 시도
- 줄바꿈 추가 - 제공된 데이터 가볍게 훑어보기
- 데이터 분석으로 추가적인 전처리
- 평가함수 재설정
# 학습용 평가
from datasets import load_metric
rouge_metric = load_metric("rouge")
def compute_metrics(pred):
predictions = pred.predictions
labels = pred.label_ids
# Decode the prediction and label ids to texts
# Replace -100 in the labels as we can't decode them.
predictions = [tokenizer.decode(pred, skip_special_tokens=True) for pred in predictions]
labels = [tokenizer.decode(np.where(np.array(label) == -100, 0, label).tolist(), skip_special_tokens=True) for label in labels]
# Calculate ROUGE scores
rouge_output = rouge_metric.compute(predictions=predictions, references=labels, use_stemmer=True)
# Extract precision, recall, fmeasure for each ROUGE score
rouge1 = rouge_output["rouge1"].mid
rouge2 = rouge_output["rouge2"].mid
rougeL = rouge_output["rougeL"].mid
return {
"rouge1_fmeasure": rouge1.fmeasure,
"rouge2_fmeasure": rouge2.fmeasure,
"rougeL_fmeasure": rougeL.fmeasure,
}
4. 후처리 및 모델 학습
- 맞춤법 검사 - 이틀 남았으니 전처리와 학습은 무리라고 생각되는 사람들에게
소스코드
Korean-Abstractive-Summarization: huggingface_t5-large-korean-text-summary¶
- TEAM: ChatGPT
1. Install and Setting library¶
In [ ]:
# line breaking library
!pip install kss
In [ ]:
# preprocessing library
!pip install emoji
!pip install unidecode
In [ ]:
# huggingface transformers library
!pip install transformers
In [ ]:
# dataset library
!pip install datasets
In [ ]:
# metrics library
!pip install rouge_score
In [ ]:
!pip uninstall sentencepiece
!pip install sentencepiece
2. Load Dataset¶
In [ ]:
# 구글 드라이브와 연동합니다. 권한 허용이 필요합니다.
from google.colab import drive
drive.mount('/content/drive')
In [ ]:
# 테스트 데이터를 HuggingFace Dataset으로 불러옵니다.
import pandas as pd
data_path = '/content/drive/MyDrive/공모전/GPT_Competition/data/train.csv'
train = pd.read_csv(data_path)
In [ ]:
train
Out[ ]:
id | text | summary | |
---|---|---|---|
0 | REPORT-news_r-00007-00001 | 보수진영 사분오열 속 ‘국민통합연대’ 띄운 비박계 크리스마스를 앞둔 지난 23일 오... | 국민통합연대가 연 창립대회에 자유한국당 홍 전 대표 등 의원 20여 명을 포함한 5... |
1 | REPORT-news_r-00018-00001 | 가난 속에서 맨손으로 혼자 창업해 30대 중반에 코스닥 상장까지 일궈낸 이가 있다.... | 아이엘사이언스 대표 송 씨는 발광다이오드 조명용 실리콘 렌즈를 세계 최초로 개발하여... |
2 | REPORT-news_r-00020-00002 | SK텔레콤은 ‘T끼리 온가족 할인’ 요금제로, 가족 구성원의 가입 합산 기간이... | SK텔레콤은 T끼리 온가족 할인으로 요금을 깎아주거나 30년 이상 가입자를 위해 호... |
3 | REPORT-news_r-00024-00001 | “박스 테이프는 어디 갔죠?” 1일 오전 서울 중구의 한 대형마트.\n 장을 본 ... | 대형마트 3사가 장바구니 사용을 독려하고 플라스틱 폐기물을 줄이기 위해 포장용 테이... |
4 | REPORT-news_r-00029-00001 | 현대차그룹 고급 브랜드 제네시스의 첫 스포츠유틸리티차량(SUV), GV80이 드디어... | 현대차그룹은 제네시스를 이끌 GV80의 내·외관 사진을 공개하며 이달 중 출시한다고... |
... | ... | ... | ... |
40395 | REPORT-speech-16815-00004 | 이것들이 잘할 수 있도록 저희들이 워크숍을 예정하는데 한국고용정보원하고 한국청소년정... | 전국기능경기대회는 심각한 코로나 상황으로 인해 방역에 특히 신경을 써서 추진하고자 한다. |
40396 | REPORT-speech-16815-00005 | 그래서 10~12월간 제조업체 등을 대상으로 해서 관련된 자율진단을 하고 필요하면 ... | 이륜차 사고예방 시범사업은 이동시간 논란이 많은 배달업 종사원들에 대해 안전 배달시... |
40397 | REPORT-speech-16817-00002 | 마지막으로 10월 4일에는 슈타인 마이어 독일 연방정부 대통령을 예방합니다. 이 자... | 강원도 철원군에서 2021년 통일로가요 결선 경연을 개최하며 결선에 진출한 12개 ... |
40398 | REPORT-speech-16819-00001 | 안녕하십니까? 국민권익위원회 대변인 허재우입니다. 9월 넷째 주 정례브리핑입니다. ... | 국민권익위는 경기도 소재 21개 중·고등학교를 표본으로 실태조사를 한 결과 저소득층... |
40399 | REPORT-speech-16820-00001 | 안녕하십니까? 과기정통부 대변인실 김세준입니다. 9월 27일 월요일 정례브리핑을 시... | 국립중앙과학관은 국민이 직접 만든 영상 콘텐츠, 국민들과 과학관이 함께 만드는 영상... |
40400 rows × 3 columns
In [ ]:
train['text'].loc[0]
Out[ ]:
'보수진영 사분오열 속 ‘국민통합연대’ 띄운 비박계 크리스마스를 앞둔 지난 23일 오전 서울 프레스센터 국제회의실.\n 보수분열 극복을 내건 ‘국민통합연대’가 창립대회를 열었다.\n 햇살 없이 착 가라앉은 날씨에 동지 바람이 매서웠지만 행사장 안은 달아올랐다.\n 문재인 정권을 향한 맹폭격이 이어졌고 ‘무능, 기만의 오만방자한 정권에 사망을 선고한다’는 창립선언문이 나왔다.\n 홍준표 전 자유한국당 대표 등 전현직 의원 20여명을 포함해 500여명이 자리를 빼곡하게 메웠다.\n 총선이 불과 석달 남짓이다.\n 야권 인사들이 정권을 두들겨 패는 거야 이상한 일이 아니다.\n 눈 여겨 볼 대목은 모인 사람이 대부분 친이·비박계(친이명박·비박근혜) 인사들이란 점이다.\n 박관용 전 국회의장, 이문열 작가와 함께 보수쪽 명망가 여럿이 이름을 올리고 더러 참석했다.\n 전광훈 목사는 축사를 했다.\n 그래도 이명박 정권서 요직을 맡았던 사람들이 주축이다.\n 이재오 중앙집행위원장과 홍준표 전 대표가 한가운데 있다.\n 두 사람은 ‘친박 그룹’에 둘러싸인 황교안 대표와 한국당에 불편한 기색을 감추지 않는 중이다.\n 홍 전 대표는 이튿날 “무기력한 야당만 믿고 따르기엔 너무 답답하고 앞날이 보이지 않아 창립한 게 국민통합연대”란 글을 올렸다.\n 31일엔 “한국당 지도부는 총사퇴하고 비상대책위를 꾸려야 한다”고 황 대표 사퇴를 요구했다.\n 이재오 위원장은 지난 10월3일 광화문의 조국 규탄집회장에서 “자유한국당은 집회에서 빠지라”고 외쳤다.\n 가뜩이나 뿔뿔이 흩어진 각자도생의 보수세력이다.\n 한국당과 우리공화당에다 새로운 보수당, 이언주 신당, 이정현 신당이 나올 판이다.\n 게다가 개정선거법의 준연동형 비례대표제는 군소정당에 유리한 분열요인이다.\n 중앙선관위에 등록된 정당이 34개인데 창당준비위원회를 설립한 예비정당만 16개에 달한다.\n 야권 빅텐트를 외칠만한 상황이긴 하다.\n 그런데 통합을 내건 이재오 위원장은 “어느 한 정당이나 단체 중 힘 있는 정당, 단체를 중심으로 뭘 하자는 식의 통합은 어렵다”고 주장했다.\n 황교안 대표와 한국당 중심의 보수 통합론을 가로막고 나선 셈이다.\n 그렇다고 ‘힘 있는’ 한국당이 ‘힘 없는’ 국민통합연대의 주문에 따를 리는 없다.\n 결국 친이계가 떨어져 나가는 ‘보수 4분열’이란 해석이 나왔다.\n 정말 그럴까.\n 국민통합연대는 조만간 친이 비박 신당으로 탈바꿈할 것인가.\n '
2-1. Line breaking¶
- 일부 데이터에서 줄바꿈되지 않은 문장이 존재하여 변환
In [ ]:
from kss import split_sentences
idx= []; org_idx = []
for i in range(len(train)):
if '\n' not in train['text'][i]:
idx.append(i)
else:
org_idx.append(i)
refine_df = train.iloc[idx, :];org_df = train.iloc[org_idx, :]
for i in idx:
refine_df.loc[i,'text'] = '\n'.join(split_sentences(refine_df.loc[i,'text']))
final_df = pd.concat([org_df,refine_df], axis = 0)
final_df = final_df.sort_index(ascending=True)
In [ ]:
final_df.to_csv('/content/drive/MyDrive/공모전/GPT_Competition/data/retain_train.csv', index=False)
In [ ]:
final_df = pd.read_csv('/content/drive/MyDrive/공모전/GPT_Competition/data/retain_train.csv')[['id', 'text', 'summary']]
In [ ]:
final_df.head()
Out[ ]:
id | text | summary | |
---|---|---|---|
0 | REPORT-news_r-00007-00001 | 보수진영 사분오열 속 ‘국민통합연대’ 띄운 비박계 크리스마스를 앞둔 지난 23일 오... | 국민통합연대가 연 창립대회에 자유한국당 홍 전 대표 등 의원 20여 명을 포함한 5... |
1 | REPORT-news_r-00018-00001 | 가난 속에서 맨손으로 혼자 창업해 30대 중반에 코스닥 상장까지 일궈낸 이가 있다.... | 아이엘사이언스 대표 송 씨는 발광다이오드 조명용 실리콘 렌즈를 세계 최초로 개발하여... |
2 | REPORT-news_r-00020-00002 | SK텔레콤은 ‘T끼리 온가족 할인’ 요금제로, 가족 구성원의 가입 합산 기간이... | SK텔레콤은 T끼리 온가족 할인으로 요금을 깎아주거나 30년 이상 가입자를 위해 호... |
3 | REPORT-news_r-00024-00001 | “박스 테이프는 어디 갔죠?” 1일 오전 서울 중구의 한 대형마트.\n 장을 본 ... | 대형마트 3사가 장바구니 사용을 독려하고 플라스틱 폐기물을 줄이기 위해 포장용 테이... |
4 | REPORT-news_r-00029-00001 | 현대차그룹 고급 브랜드 제네시스의 첫 스포츠유틸리티차량(SUV), GV80이 드디어... | 현대차그룹은 제네시스를 이끌 GV80의 내·외관 사진을 공개하며 이달 중 출시한다고... |
In [ ]:
# document length
train_text = final_df['text'].apply(len)
In [ ]:
train_text.describe() # 1500
Out[ ]:
count 40400.000000
mean 921.470074
std 221.744665
min 687.000000
25% 738.000000
50% 805.000000
75% 1208.000000
max 1499.000000
Name: text, dtype: float64
In [ ]:
# summary length
train_summ = final_df['summary'].apply(len)
In [ ]:
train_summ.describe() # 100
Out[ ]:
count 40400.000000
mean 80.493094
std 15.862411
min 16.000000
25% 70.000000
50% 84.000000
75% 94.000000
max 100.000000
Name: summary, dtype: float64
2-2. Preprocessing¶
In [ ]:
import re
import emoji
from unidecode import unidecode
import numpy as np
#remove html tags
def removeHTML(x):
html=re.compile(r'<.*?>')
return html.sub(r'',x)
def dataPreprocessing(x):
# x = x.lower() # 대소문자 분류가 필요할지도 몰라서 주석처리
x = removeHTML(x)
x = emoji.demojize(x, delimiters=(" ", " "))
x = re.sub(r'[^ 가-힣A-Za-z0-9\'.,?!/\n\r()%\[\]\-+~$&"]·', '', x)
x = re.sub(r'[ ]+', ' ', x) # 공백 두칸 이상 지우기
x = x.strip()
return x
In [ ]:
final_df["text"]=final_df["text"].apply(lambda x: dataPreprocessing(x))
In [ ]:
final_df.head()
Out[ ]:
id | text | summary | |
---|---|---|---|
0 | REPORT-news_r-00007-00001 | 보수진영 사분오열 속 ‘국민통합연대’ 띄운 비박계 크리스마스를 앞둔 지난 23일 오... | 국민통합연대가 연 창립대회에 자유한국당 홍 전 대표 등 의원 20여 명을 포함한 5... |
1 | REPORT-news_r-00018-00001 | 가난 속에서 맨손으로 혼자 창업해 30대 중반에 코스닥 상장까지 일궈낸 이가 있다.... | 아이엘사이언스 대표 송 씨는 발광다이오드 조명용 실리콘 렌즈를 세계 최초로 개발하여... |
2 | REPORT-news_r-00020-00002 | SK텔레콤은 ‘T끼리 온가족 할인’ 요금제로, 가족 구성원의 가입 합산 기간이 20... | SK텔레콤은 T끼리 온가족 할인으로 요금을 깎아주거나 30년 이상 가입자를 위해 호... |
3 | REPORT-news_r-00024-00001 | “박스 테이프는 어디 갔죠?” 1일 오전 서울 중구의 한 대형마트.\n 장을 본 사... | 대형마트 3사가 장바구니 사용을 독려하고 플라스틱 폐기물을 줄이기 위해 포장용 테이... |
4 | REPORT-news_r-00029-00001 | 현대차그룹 고급 브랜드 제네시스의 첫 스포츠유틸리티차량(SUV), GV80이 드디어... | 현대차그룹은 제네시스를 이끌 GV80의 내·외관 사진을 공개하며 이달 중 출시한다고... |
In [ ]:
final_df.loc[100]['text']
Out[ ]:
'유튜브가 정치권에 미치는 영향이 날로 커지고 있다.\n 각종 정치 이슈가 확대·재생산되며 각 당과 의원들도 민감하게 반응하고 있다.\n 6일로 100일 앞으로 다가온 4·15 총선에서 ‘유튜브 활용법’이 판도를 가를 것이란 분석까지 나온다.\n 이번 총선은 여러 면에서 기존 선거와 다른 양상을 보일 것으로 예상된다.\n 우선 진보와 보수 모두 극단적 쏠림 현상이 뚜렷하다.\n 자유한국당은 황교안 대표가 ‘탄핵 국면’을 적극 활용하며 보수색이 더 짙어졌다.\n 더불어민주당 역시 이른바 ‘문빠(문재인 대통령 열혈 지지자)’ 등 지지 세력을 규합하는데 총력을 쏟고 있다.\n 중원(中原)을 겨냥해 표심을 확장하는 통상의 선거 전략과는 다른 모습이다.\n 더불어민주당의 한 핵심 관계자는 "각 당이 우선은 ‘집토끼’를 확실히 붙잡아 둬야 한다는 압박이 있어 당분간은 여야 모두 중도층을 공략하는 전략보단 지지 세력을 규합하기 위한 움직임이 계속될 것”이라고 말했다.\n 이런 상황에서 집토끼를 단속하기 위한 수단으로 유튜브의 중요성이 더 부각되고 있다.\n 현재 유튜브 정치 지형은 보수 진영이 우위를 선점한 가운데 진보 진영이 세를 확장하려는 상황으로 요약된다.\n 유튜브 장악한 보수 채널 유튜브 내 정치 생태계에선 보수 채널이 강세다.\n 정치 관련 유튜브 채널 중 구독자 수 1위인 ‘신의 한수’가 대표적이다.\n 애국보수를 표방하는 이 채널은 구독자 수가 116만명에 달한다.\n 지난해 12월부터 이어지는 한국당의 집회·농성장에 참가자들을 끌어 모으는 구심점 역할을 했다.\n 이외에도 진성호방송(구독자 76만명)·딴지방송국(71만명)·정규재TV(63만명)·고성국TV(51만명)·TV홍카콜라(36만명) 등이 있는데, 열혈팬이 많은 편이다.\n 유튜브에선 통상 구독자 수 대비 조회수 기준으로 해당 채널의 활동성과 파급력을 평가한다.\n 보수 성향의 주요 유튜브 채널은 구독자 수 대비 조회수가 평균 50% 수준으로, 구독자 중 절반 이상은 채널에 올라오는 영상을 빠짐 없이 본다는 얘기다.\n 또 보수 유튜브 채널에선 트위터·페이스북 등 소셜네트워크서비스(SNS) 흐름에 상대적으로 소외됐던 중·장년층의 활동이 유독 활발하단 특징도 있다.\n 구독자 76만명의 진성호방송을 운영하는 진성호 전 새누리당(한국당 전신) 의원은 “유튜브의 가장 큰 장점은 빠른 피드백과 그에 따른 양방 소통”이라며 “유튜브를 기성 언론과 굳이 비교하자면 일반 기사가 아닌 제도권 언론의 사설·평론과 비슷한 형식인데 그 누구의 간섭도 받지 않고 내 소신과 신념에 따라 가치관을 담은 영상을 내보낼 수 있다”고 말했다.'
In [ ]:
# document length
train_text = final_df['text'].apply(len)
train_text.describe() # 100
Out[ ]:
count 40400.000000
mean 912.081089
std 213.444188
min 579.000000
25% 735.000000
50% 802.000000
75% 1183.000000
max 1491.000000
Name: text, dtype: float64
In [ ]:
# document length
train_summ = final_df['summary'].apply(len)
train_summ.describe() # 100
Out[ ]:
count 40400.000000
mean 80.493094
std 15.862411
min 16.000000
25% 70.000000
50% 84.000000
75% 94.000000
max 100.000000
Name: summary, dtype: float64
2-3. Split train and test dataset¶
In [ ]:
from sklearn.model_selection import train_test_split
# train과 test 데이터로 분리
train_df, test_df = train_test_split(final_df, test_size=0.2, random_state=24)
3. Load model and tokenizer¶
- Train Model: T5
In [ ]:
# from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, Seq2SeqTrainingArguments, DataCollatorForSeq2Seq, Seq2SeqTrainer
- fine tuning을 위한 tokenizer 및 model 로드
In [ ]:
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, T5Tokenizer
tokenizer = AutoTokenizer.from_pretrained("noahkim/KoT5_news_summarization")
model = AutoModelForSeq2SeqLM.from_pretrained("/content/drive/MyDrive/공모전/GPT_Competition/t5_large_230328/results_t5_large_230328/checkpoint-100") # 지난 최적 모델부터 다시 학습
- device 설정 (GPU 사용을 권장)
In [ ]:
import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
- 입력과 출력 길이 설정
In [ ]:
max_input_length = 1024
max_output_length = 100
- 입력 및 출력 토큰화 함수 정의
In [ ]:
def tokenize(batch):
return tokenizer(batch['text'], padding='max_length', truncation=True, max_length=max_input_length)
def summarize(batch):
return tokenizer(batch['summary'], padding='max_length', truncation=True, max_length=max_output_length)
- 학습 데이터셋 및 데이터로더 생성
In [ ]:
train_dataset = []
for i in range(len(train_df)):
data = {
'id': train_df.iloc[i]['id'],
'input_ids': None,
'attention_mask': None,
'decoder_input_ids': None,
'decoder_attention_mask': None,
'labels': None
}
# 입력과 출력을 토큰화
input = tokenizer.encode_plus(train_df.iloc[i]['text'], max_length=max_input_length, padding='max_length', truncation=True, return_tensors='pt')
output = tokenizer.encode_plus(train_df.iloc[i]['summary'], max_length=max_output_length, padding='max_length', truncation=True, return_tensors='pt')
# 토큰 ID와 어텐션 마스크를 입력 데이터로 저장
data['input_ids'] = input['input_ids'][0]
data['attention_mask'] = input['attention_mask'][0]
# 토큰 ID와 어텐션 마스크를 출력 데이터로 저장
data['decoder_input_ids'] = output['input_ids'][0]
data['decoder_attention_mask'] = output['attention_mask'][0]
# 라벨 데이터로 저장
data['labels'] = output['input_ids'][0].clone().detach()
# 라벨에서 PAD 토큰의 위치를 마스크하여 불필요한 손실 계산 방지
data['labels'][data['labels'] == tokenizer.pad_token_id] = -100
train_dataset.append(data)
In [ ]:
test_df.iloc[0]
Out[ ]:
id REPORT-minute-00015-02490
text 노웅래 위원] "이상입니다."\n위원장 진영] "수고하셨습니다. 다음은 강기윤 위원...
summary 강 위원은 안전처가 생긴다면 소방공무원은 어떻게 해야 할까 하는 의문이 들어야 하고...
Name: 11459, dtype: object
- 테스트 데이터셋 및 데이터로더 생성
In [ ]:
test_dataset = []
for i in range(len(test_df)):
data = {
'id': test_df.iloc[i]['id'],
'input_ids': None,
'attention_mask': None,
'decoder_input_ids': None,
'decoder_attention_mask': None,
'labels': None
}
# 입력과 출력을 토큰화
input = tokenizer.encode_plus(test_df.iloc[i]['text'], max_length=max_input_length, padding='max_length', truncation=True, return_tensors='pt')
output = tokenizer.encode_plus(test_df.iloc[i]['summary'], max_length=max_output_length, padding='max_length', truncation=True, return_tensors='pt')
# 토큰 ID와 어텐션 마스크를 입력 데이터로 저장
data['input_ids'] = input['input_ids'][0]
data['attention_mask'] = input['attention_mask'][0]
# 토큰 ID와 어텐션 마스크를 출력 데이터로 저장
data['decoder_input_ids'] = output['input_ids'][0]
data['decoder_attention_mask'] = output['attention_mask'][0]
# 라벨 데이터로 저장
data['labels'] = output['input_ids'][0].clone().detach()
# 라벨에서 PAD 토큰의 위치를 마스크하여 불필요한 손실 계산 방지
data['labels'][data['labels'] == tokenizer.pad_token_id] = -100
test_dataset.append(data)
- 데이터 수집기 및 학습/테스트 데이터셋 로더 생성
In [ ]:
data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer,model=model)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=True, collate_fn=data_collator)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=4, shuffle=True, collate_fn=data_collator)
4. Custom metrics¶
- ROUGE-1,2,L (F1)
In [ ]:
# 학습용 평가
from datasets import load_metric
rouge_metric = load_metric("rouge")
def compute_metrics(pred):
predictions = pred.predictions
labels = pred.label_ids
# Decode the prediction and label ids to texts
# Replace -100 in the labels as we can't decode them.
predictions = [tokenizer.decode(pred, skip_special_tokens=True) for pred in predictions]
labels = [tokenizer.decode(np.where(np.array(label) == -100, 0, label).tolist(), skip_special_tokens=True) for label in labels]
# Calculate ROUGE scores
rouge_output = rouge_metric.compute(predictions=predictions, references=labels, use_stemmer=True)
# Extract precision, recall, fmeasure for each ROUGE score
rouge1 = rouge_output["rouge1"].mid
rouge2 = rouge_output["rouge2"].mid
rougeL = rouge_output["rougeL"].mid
return {
"rouge1_fmeasure": rouge1.fmeasure,
"rouge2_fmeasure": rouge2.fmeasure,
"rougeL_fmeasure": rougeL.fmeasure,
}
- GPU 캐시 초기화
In [ ]:
import torch
import gc
torch.cuda.empty_cache()
gc.collect()
Out[ ]:
16
In [ ]:
import torch
import gc
torch.cuda.empty_cache()
gc.collect()
Out[ ]:
0
5. Train model¶
In [ ]:
from transformers import EarlyStoppingCallback
# EarlyStoppingCallback 초기화
early_stopping = EarlyStoppingCallback(early_stopping_patience=100, early_stopping_threshold=0.01)
In [ ]:
from transformers import Seq2SeqTrainer, Seq2SeqTrainingArguments
from transformers import AdamW
# 파인튜닝을 위한 argument 설정
training_args = Seq2SeqTrainingArguments(
output_dir='/content/drive/MyDrive/공모전/GPT_Competition/t5_final_model/results_t5_final_230329',
evaluation_strategy = "steps",
eval_steps = 100, # Number of update steps between two evaluations.
save_steps= 100, # after # steps model is saved
warmup_steps= 200,# number of warmup steps for learning rate scheduler
num_train_epochs = 5,
learning_rate = 2e-5,
per_device_train_batch_size = 2,
per_device_eval_batch_size = 2,
weight_decay = 0.01,
push_to_hub=False,
logging_dir='/content/drive/MyDrive/공모전/GPT_Competition/t5_final_model/logs_t5_final_230329',
logging_steps=100,
overwrite_output_dir=True,
predict_with_generate=True,
load_best_model_at_end = True,
gradient_accumulation_steps=2,
seed=42
)
optimizer = AdamW(model.parameters(), lr=training_args.learning_rate, eps=1e-8)
# trainer 객체 생성
trainer = Seq2SeqTrainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=test_dataset,
data_collator=data_collator,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
callbacks=[early_stopping],
optimizers=(optimizer, None)
)
# 파인튜닝 시작
trainer.train()
/usr/local/lib/python3.9/dist-packages/transformers/optimization.py:391: FutureWarning: This implementation of AdamW is deprecated and will be removed in a future version. Use the PyTorch implementation torch.optim.AdamW instead, or set `no_deprecation_warning=True` to disable this warning
warnings.warn(
You're using a T5TokenizerFast tokenizer. Please note that with a fast tokenizer, using the `__call__` method is faster than using a method to encode the text followed by a call to the `pad` method to get a padded encoding.
[ 901/40400 7:52:56 < 346:19:36, 0.03 it/s, Epoch 0.11/5]
Step | Training Loss | Validation Loss | Rouge1 Fmeasure | Rouge2 Fmeasure | Rougel Fmeasure |
---|---|---|---|---|---|
100 | 0.785900 | 0.705539 | 0.126698 | 0.017760 | 0.126457 |
200 | 0.779000 | 0.704115 | 0.123370 | 0.017065 | 0.123409 |
300 | 0.778200 | 0.702407 | 0.119287 | 0.016661 | 0.118929 |
400 | 0.776200 | 0.700535 | 0.118460 | 0.016214 | 0.118268 |
500 | 0.790200 | 0.698328 | 0.123577 | 0.017110 | 0.123425 |
600 | 0.778700 | 0.701000 | 0.123772 | 0.017168 | 0.123563 |
700 | 0.758500 | 0.702042 | 0.126056 | 0.017560 | 0.125614 |
800 | 0.759400 | 0.698527 | 0.124525 | 0.017035 | 0.124081 |
[1110/4040 15:18 < 40:27, 1.21 it/s]
In [ ]:
model.save_pretrained("/content/drive/MyDrive/공모전/GPT_Competition/t5_final_model/results_t5_final_230329") # 모델 저장장
In [ ]:
# trainer.evaluate()
6. Sumbit test data¶
In [ ]:
import pandas as pd
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
# 모델 로드
# model_name = 'google/pegasus-large'
# tokenizer = AutoTokenizer.from_pretrained(model_name)
# model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained("noahkim/KoT5_news_summarization")
model = AutoModelForSeq2SeqLM.from_pretrained("/content/drive/MyDrive/공모전/GPT_Competition/t5_final_model/results_t5_final_230329/checkpoint-500")
# test 데이터프레임 읽기
test = pd.read_csv('/content/drive/MyDrive/공모전/GPT_Competition/data/test.csv')[['id', 'text']]
In [ ]:
test["text"]=test["text"].apply(lambda x: dataPreprocessing(x))
In [ ]:
from kss import split_sentences
idx= []; org_idx = []
for i in range(len(test)):
if '\n' not in test['text'][i]:
idx.append(i)
else:
org_idx.append(i)
refine_df = test.iloc[idx, :];org_df = test.iloc[org_idx, :]
for i in idx:
refine_df.loc[i,'text'] = '\n'.join(split_sentences(refine_df.loc[i,'text']))
test = pd.concat([org_df,refine_df], axis = 0)
test = test.sort_index(ascending=True)
WARNING:root:Oh! You have mecab in your environment. Kss will take this as a backend! :D
<ipython-input-140-c666655ad207>:12: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
refine_df.loc[i,'text'] = '\n'.join(split_sentences(refine_df.loc[i,'text']))
In [ ]:
# 토큰화 함수 정의
def tokenize(text):
input_ids = tokenizer.encode(text, truncation=True, max_length=max_input_length, padding='max_length', return_tensors='pt')
return input_ids
# test 데이터프레임에 대해 토큰화 수행
test_dataset = test['text'].apply(tokenize)
In [ ]:
model.to(device)
Out[ ]:
In [ ]:
# generate 함수로 요약 결과 생성
generated_summaries = []
for input_ids in test_dataset:
summary = model.generate(input_ids=input_ids.to(device), max_length=max_input_length, num_beams=4, early_stopping=True)
summary = tokenizer.decode(summary[0], skip_special_tokens=True)
generated_summaries.append(summary)
# 생성된 요약 결과를 test 데이터프레임에 추가
test['summary'] = generated_summaries
- 후처리 작업
In [ ]:
import requests
import json
checked = []
for text in test['summary']:
sentences = [t+"." for t in text.split(". ")]
new_sentences = []
for sentence in sentences:
new_sentence = sentence
response = requests.post('http://164.125.7.61/speller/results', data={'text1': sentence})
data = response.text.split('data = [', 1)[-1].rsplit('];', 1)
if len(data) > 1:
data = json.loads(data[0])
for err in data['errInfo']:
if (int(err['correctMethod']) == 2 or int(err['correctMethod']) == 4) and '|' not in err['candWord']:
new_sentence = new_sentence.replace(err['orgStr'],err['candWord'])
new_sentences.append(new_sentence)
if len(new_sentences) > 0:
checked.append(' '.join(new_sentences))
else:
checked.append(' '.join(sentences))
In [ ]:
test['summary'] = checked
In [ ]:
def dataAtferPreprocessing(x):
x = re.sub(r'[.]+', ' ', x) # 결과에서 나타나는 .... 지우기
x = re.sub(r'[‘’]', ' ', x) # 결과에서 나타나는 ‘지우기
x = x.strip() # 문자열 양끝 공백 및 줄바꿈(\n) 제거
return x
In [ ]:
test["summary"]=test["summary"].apply(lambda x: dataAtferPreprocessing(x))
In [ ]:
sumbit = pd.read_csv('/content/drive/MyDrive/공모전/GPT_Competition/data/sample_submission.csv')
In [ ]:
sumbit['summary'] = test['summary']
In [ ]:
sumbit
- 제출 파일 생성
In [ ]:
sumbit.to_csv('/content/drive/MyDrive/공모전/GPT_Competition/t5_large_final_submission_230329.csv', index=False)
In [ ]:
# 자동으로 세션을 종료하고 싶을때 사용하세요.
from google.colab import runtime
runtime.unassign()
'IT > 인공지능' 카테고리의 다른 글
[Deep Learning Specialization] Neural Networks and Deep Learning (1) | 2024.07.14 |
---|---|
[LLM][RAG] RAG(Retrieval-Augmented Generation) 소개 및 설명 (1) | 2024.06.04 |
[LLM][프롬프트엔지니어링] CoT(Chain of Thought) (0) | 2024.05.07 |
[LLM] ReALM: Reference Resolution As Language Modeling 논문 리뷰 (0) | 2024.04.21 |
[LLM] Social Skill Training with Large Language Models 논문 리뷰 (0) | 2024.04.10 |