2024 하계 모각코

모각코 1회차 - 7/3일, 14시~17시

nanocat 2024. 7. 3. 14:02

목표

koGPT2 ChatBot 만들기 연습

 

결과

1. koGPT2 ChatBot 만들기 연습

https://wikidocs.net/158023

 

9-3. koGPT2 ChatBot

프로그래밍에 사용된 패키지들의 버전은 다음과 같다. * huggingface-hub 0.2.1 pypi_0 pypi *…

wikidocs.net

위 사이트를 많이 참고하였다.

사용 챗봇 데이터 : 송영숙님의 챗봇 데이터 (https://github.com/songys/Chatbot_data)

 

- koGPT2를 colab에 가져와보았다.

import torch
from transformers import GPT2LMHeadModel

from transformers import PreTrainedTokenizerFast
tokenizer = PreTrainedTokenizerFast.from_pretrained("skt/kogpt2-base-v2", bos_token='</s>', eos_token='</s>', unk_token='<unk>', pad_token='<pad>', mask_token='<mask>')

tokenizer.tokenize("안녕하세요. 한국어 GPT-2 입니다.😤:)l^o")
['▁안녕', '하', '세', '요.', '▁한국어', '▁G', 'P', 'T', '-2', '▁입', '니다.', '😤', ':)', 'l^o']

 

- 입력된 텍스트에 따라 다음 문장 생성

model = GPT2LMHeadModel.from_pretrained('skt/kogpt2-base-v2')

text = '공부를 잘 하려면'
input_ids = tokenizer.encode(text)
gen_ids = model.generate(torch.tensor([input_ids]),
                           max_length=128,
                           repetition_penalty=2.0,
                           pad_token_id=tokenizer.pad_token_id,
                           eos_token_id=tokenizer.eos_token_id,
                           bos_token_id=tokenizer.bos_token_id,
                           use_cache=True)
generated = tokenizer.decode(gen_ids[0,:].tolist())
print(generated)
 공부를 잘 하려면 어떻게 해야 할까? 그것은 바로 '자기계발'이다. 이런 자기 계발을 위해서는 먼저 자신의 능력을 계발하고 이를 바탕으로 스스로 목표를 설정하고 실천해야 한다. 그리고 그 목표에 도달하기 위해 필요한 것은 무엇이며, 어떤 방법으로 성취할 수 있는 것인지를 구체적으로 생각해 보아야 하며, 그것을 이루기 위한 구체적인 방법을 찾아보아야 하는 것이다. 또한 이러한 과정을 통해 자신이 원하는 것을 이룰 때 비로소 진정한 자아실현의 길이 열릴 것이라고 생각한다. 자아성취란 단순히 주어진 일을 열심히 해 나가는 것만으로는 부족하다는 사실을 깨달을 때, 가능해진다. 즉, 자기가 하고 싶은 일에 집중하는 것이야말로 자신을 성장시키고 발전시키는 데 큰 도움이 된다는 뜻이다. 따라

 

- 모델 학습

# 필요한 라이브러리 import
import numpy as np
import pandas as pd
import torch
from pytorch_lightning import Trainer
from pytorch_lightning.callbacks import ModelCheckpoint
from pytorch_lightning.core.module import LightningModule # core.lightning은 core.module로 바뀜
from torch.utils.data import DataLoader, Dataset
from transformers.optimization import AdamW, get_cosine_schedule_with_warmup
from transformers import PreTrainedTokenizerFast, GPT2LMHeadModel
import re

# huggingface의 토큰 사용
Q_TKN = "<usr>"
A_TKN = "<sys>"
BOS = '</s>'
EOS = '</s>'
MASK = '<unused0>'
SENT = '<unused1>'
PAD = '<pad>'

# pretrained model을 가져옴
koGPT2_TOKENIZER = PreTrainedTokenizerFast.from_pretrained("skt/kogpt2-base-v2",
            bos_token=BOS, eos_token=EOS, unk_token='<unk>',
            pad_token=PAD, mask_token=MASK) 
model = GPT2LMHeadModel.from_pretrained('skt/kogpt2-base-v2')

import urllib.request
# 송영숙님의 챗봇 데이터 (https://github.com/songys/Chatbot_data) 다운로드
urllib.request.urlretrieve(
    "https://raw.githubusercontent.com/songys/Chatbot_data/master/ChatbotData.csv",
    filename="ChatBotData.csv",
)
Chatbot_Data = pd.read_csv("ChatBotData.csv")
# Test 용으로 300개 데이터만 처리한다.
Chatbot_Data = Chatbot_Data[:300]
Chatbot_Data.head()

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
train_set = ChatbotDataset(Chatbot_Data, max_len=40)
#윈도우 환경에서 num_workers 는 무조건 0으로 지정, 리눅스에서는 2
train_dataloader = DataLoader(train_set, batch_size=32, num_workers=0, shuffle=True, collate_fn=collate_batch,)

model.to(device)
model.train()

# 하이퍼 파라미터 설정
learning_rate = 3e-5
criterion = torch.nn.CrossEntropyLoss(reduction="none")
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

epoch = 10
Sneg = -1e18

# 모델 학습
print ("start")
for epoch in range(epoch):
    for batch_idx, samples in enumerate(train_dataloader):
        optimizer.zero_grad()
        token_ids, mask, label = samples

        token_ids = token_ids.to(device)
        mask = mask.to(device)
        label = label.to(device)

        out = model(token_ids)
        out = out.logits      #Returns a new tensor with the logit of the elements of input
        mask_3d = mask.unsqueeze(dim=2).repeat_interleave(repeats=out.shape[2], dim=2)
        mask_out = torch.where(mask_3d == 1, out, Sneg * torch.ones_like(out))
        loss = criterion(mask_out.transpose(2, 1), label)
        # 평균 loss 만들기 avg_loss[0] / avg_loss[1] <- loss 정규화
        avg_loss = loss.sum() / mask.sum()
        avg_loss.backward()
        # 학습 끝
        optimizer.step()
print ("end")

 

- 학습된 koGPT2 모델을 테스트하는 코드

with torch.no_grad():
    while 1:
        q = input("user > ").strip()
        if q == "quit":
            break
        a = ""
        sent = ""  # sent 변수 초기화
        while 1:
            # 입력 토큰을 LongTensor로 변환
            input_ids = torch.LongTensor(koGPT2_TOKENIZER.encode(Q_TKN + q + SENT + sent + A_TKN + a)).unsqueeze(dim=0)

            # input_ids를 모델이 있는 디바이스로 이동
            input_ids = input_ids.to(device)

            # 모델 예측
            pred = model(input_ids)
            pred = pred.logits

            # 예측된 토큰을 텍스트로 변환
            gen = koGPT2_TOKENIZER.convert_ids_to_tokens(torch.argmax(pred, dim=-1).squeeze().cpu().numpy().tolist())[-1]

            # 종료 토큰이 나올 경우 반복 종료
            if gen == EOS:
                break

            # 생성된 토큰을 누적하여 응답 생성
            a += gen.replace("▁", " ")

        print("Chatbot > {}".format(a.strip()))
user > 안녕
Chatbot > 저도 좋아해주세요
user > 즐거운 일이 있어
Chatbot > 즐거운 일부터 하세요
user > 넌 최고야
Chatbot > 어서 더 좋은 곳에서 살 수 있을 거예요
user > 오후 3시다
Chatbot > 좋은 아침이에요
user > quit

 

느낀 점 : 생각보다 좋은 결과를 내진 못했다. 동문서답을 한다.