본문 바로가기
자연어 처리(NLP)

간단한 답변 랭킹 모델 만들기

by 곽정우 2024. 7. 1.

import urllib.request
import pandas as pd
 
urllib.request.urlretrieve('https://raw.githubusercontent.com/songys/Chatbot_data/master/ChatbotData.csv', filename='ChatBotData.csv')
 
train_dataset = pd.read_csv('ChatBotData.csv')
print(len(train_dataset))

train_dataset.replace('', float('NaN'), inplace=True)
print(train_dataset.isnull().values.any())

train_dataset = train_dataset.drop_duplicates(['Q']).reset_index(drop=True)
print(len(train_dataset))

train_dataset = train_dataset.drop_duplicates(['A']).reset_index(drop=True)
print(len(train_dataset))

import matplotlib.pyplot as plt
question_list = list(train_dataset['Q'])
answer_list = list(train_dataset['A'])
print('질문의 최대 길이:', max(len(question) for question in question_list))
print('질문의 평균 길이:', sum(map(len, question_list)) / len(question_list))

print('답변의 최대 길이:', max(len(answer) for answer in answer_list))
print('답변의 평균 길이:', sum(map(len, answer_list)) / len(answer_list))

import random
 
question_list = list(train_dataset['Q'])
answer_list = list(train_dataset['A'])
 
response_candidates = random.sample(answer_list,500)
 
response_candidates[:10]

 

!pip install kobert-transformers
import torch
from kobert_transformers import get_kobert_model, get_distilkobert_model
model = get_kobert_model()

model.eval()

# 문장에서 토큰들의 인덱스
input_ids = torch.LongTensor([[31,51,99],[15,5,0]])

# 모델이 어떤 토큰을 무시해야 하는지 나타내는 텐서(0: 무시, 1: 고려)
attention_mask = torch.LongTensor([[1,1,1],[1,1,0]])

# 다중 문장 입력을 다룰 때, 각 토큰이 어떤 문장에 속하는지 구분(0, 1)
token_type_ids = torch.LongTensor([[0,0,1],[0,1,0]])

output = model(input_ids, attention_mask, token_type_ids)
output

# Sequence Embeddings: 각 토큰의 대한 임베딩, 의미적 표현
# pooler_output: 입력 시퀀스에서 추출한 특징의 요약
# hidden_states: 모델 내부의 각 레이어에서의 숨겨진 상태값

output[0]

pip install 'git+https://github.com/SKTBrain/KoBERT.git#egg=kobert_tokenizer&subdirectory=kobert_hf'

from kobert_tokenizer import KoBERTTokenizer
tokenizer = KoBERTTokenizer.from_pretrained('skt/kobert-base-v1')

tokenizer.tokenize('[CLS] 한국어 모델을 공유합니다. [SEP]')

tokenizer.convert_tokens_to_ids(['[CLS]', '▁한국', '어', '▁모델', '을', '▁공유', '합니다', '.', '[SEP]'])

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
def get_cls_token(sentence):
  model.eval()
  tokenized_sent = tokenizer(
      sentence,
      return_tensors = 'pt',
      truncation = True,
      add_special_tokens = True,
      max_length = 128
  )

  input_ids = tokenized_sent['input_ids']
  attention_mask = tokenized_sent['attention_mask']
  token_type_ids = tokenized_sent['token_type_ids']

  with torch.no_grad():
    output = model(input_ids, attention_mask, token_type_ids)
  
  cls_output = output[1]
  cls_token = cls_output.detach().cpu().numpy()
  return cls_token
get_cls_token('너 요즘 바뻐?')

def predict(query, candidates):
  candidates_cls = []

  for cand in candidates:
    cand_cls = get_cls_token(cand)
    candidates_cls.append(cand_cls)

  candidates_cls = np.array(candidates_cls).squeeze(axis=1)
  query_cls = get_cls_token(query)
  similarity_list = cosine_similarity(query_cls, candidates_cls)
  target_ids = np.argmax(similarity_list)
  return candidates[target_ids]
samle_query = '너 요즘 바뻐?'
print(get_cls_token(samle_query).shape)

samle_query = '너 요즘 바뻐?'
sample_candidates = ['바쁘면 가라','아니 안바뻐','오늘은 이만','에붸붸붸']

predicted_answer = predict('samle_query', sample_candidates)
print(f'결과: {predicted_answer}')

samle_query = '힘든 연애 좋은 연애라는게 무슨 차이일까?'
sample_candidates = random.sample(answer_list,100)

predicted_answer = predict('samle_query', sample_candidates)
print(f'결과: {predicted_answer}')

end = 1
while end == 1:
  sentence = input('질문을 입력하세요:')
  if len(sentence) == 0:
    break
  predicted_answer = predict (sentence, response_candidates) 
  print (predicted_answer)
  print('Wn')

'자연어 처리(NLP)' 카테고리의 다른 글

12. PLM을 이용한 실습  (0) 2024.07.08
11. 자연어처리를 위한 모델 학습  (0) 2024.07.08
한국어 챗봇  (0) 2024.07.01
10. 문장 임베딩  (0) 2024.06.21
9. LSTM과 GRU  (0) 2024.06.21