1. BERT(Bidiresctional Encoder Representations from Transformers)
- 2018년도 google 에서 처음 제안한 모델로 Transformer의 인코더 기반의 모델
- 논문 : https://arxiv.org/abs/1810.04805
- 참고 : https://wikidocs.net/109251
1. BERT 모델의 개요 |
|
2. BERT 모델의 구조 |
|
3. BERT의 사전학습 |
|
◼ import
import urllib.request
import pandas as pd
import matplotlib.pyplot as plt
import random
|
◼ 데이터 불러오기
urllib.request.urlretrieve('https://raw.githubusercontent.com/songys/Chatbot_data/master/ChatbotData.csv', filename='ChatBotData.csv')
|
('ChatBotData.csv', <http.client.HTTPMessage at 0x7c3973c61180>) |
◼ 훈련 데이터 확인
train_dataset = pd.read_csv('ChatBotData.csv')
print(len(train_dataset))
train_dataset
|
11823 ---------------------------------------------------------------------------------------------------------------------------------------- |
◼ 결측값 확인 삭제
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))
|
False 11662 7731 |
◼최대 / 평균 길이 뽑기
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))
|
질문의 최대 길이: 56 질문의 평균 길이: 13.6732634846721 답변의 최대 길이: 76 답변의 평균 길이: 15.611563833915406 |
◼
response_candidates = random.sample(answer_list, 500)
response_candidates[:10]
|
['미안해하지 않아도 돼요. 새사람에게 충실하세요.', '안 좋은일이 있었나봐요.', '머릿속에 맴도는 것들을 입으로 내뱉는 거죠.', '어렵죠.', '곧 설레는 순간이 올 거예요.', '사람마다 집착하는 게 다르니 인정해주세요.', '그 말씀 꼭 지키기 바랄게요.', '같이 살자고 프로포즈 해보세요.', '마음이 많이 아프겠어요.', '축하해요.'] |
◼ 설치
! pip install kobert-transformers
|
◼ import
import torch
from kobert_transformers import get_kobert_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
|
◼
# Seqence Embeddings : 각 토큰의 대한 임베딩, 의미적 표현
# pooler_output : 입력 시퀀스에서 추출한 특징의 요약
# hidden_state : 모델 내부의 각 레이어에서의 숨겨진 상태값
output[0]
|
◼
Collecting kobert_tokenizer Cloning https://github.com/SKTBrain/KoBERT.git to /tmp/pip-install-z2khqp0c/kobert-tokenizer_6abbc084b55d4480a76950b785498ee4 Running command git clone --filter=blob:none --quiet https://github.com/SKTBrain/KoBERT.git /tmp/pip-install-z2khqp0c/kobert-tokenizer_6abbc084b55d4480a76950b785498ee4 Resolved https://github.com/SKTBrain/KoBERT.git to commit 47a69af87928fc24e20f571fe10c3cc9dd9af9a3 Preparing metadata (setup.py) ... done Building wheels for collected packages: kobert_tokenizer Building wheel for kobert_tokenizer (setup.py) ... done Created wheel for kobert_tokenizer: filename=kobert_tokenizer-0.1-py3-none-any.whl size=4633 sha256=02c21d6d8bdf1eef4f3ad14d45fbf32231180a1e807ef7fcc7804d7911944eed Stored in directory: /tmp/pip-ephem-wheel-cache-njk3d1m2/wheels/e9/1a/3f/a864970e8a169c176befa3c4a1e07aa612f69195907a4045fe Successfully built kobert_tokenizer Installing collected packages: kobert_tokenizer Successfully installed kobert_tokenizer-0.1 |
◼
from kobert_tokenizer import KoBERTTokenizer
|
◼
tokenizer = KoBERTTokenizer.from_pretrained('skt/kobert-base-v1')
|
◼
tokenizer.tokenize('[CLS] 한국어 모델을 공유합니다. [SEP]')
|
['[CLS]', '▁한국', '어', '▁모델', '을', '▁공유', '합니다', '.', '[SEP]'] |
◼
import numpy as np
import torch
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_idx = np.argmax(similarity_list)
return candidates[target_idx]
sample_query = '너 요즘 바뻐?'
# print(get_cls_token(sample_query))
print(get_cls_token(sample_query).shape)
|
(1, 768) |
◼
sample_query = '너 요즘 바뻐?'
sample_candidates = ['바쁘면 가버려', '아니 안바뻐', '오늘은 이만', '에붸붸붸']
predicted_answer = predict('sample_query', sample_candidates)
print(f'결과: {predicted_answer}')
|
결과: 아니 안바뻐 |
◼
sample_query = '힘든 연애 좋은 연애라는게 무슨 차이일까?'
sample_candidates = random.sample(answer_list, 100)
predicted_answer = predict('sample_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('\n')
|
'AI > 자연어처리' 카테고리의 다른 글
17. 자연어처리를 위한 모델 학습 (0) | 2024.07.11 |
---|---|
16. 문장 임베딩 | GPT (0) | 2024.07.05 |
14. 문장 임베딩 | ELmo / Transformer (1) | 2024.07.04 |
13. 문장 임베딩 | Attention Meshanism (0) | 2024.07.04 |
12. 문장 임베딩 | Seq2Seq (1) | 2024.07.03 |