1. 구글 BERT의 MLM
1.마스크드 언어 모델과 토크나이저
- 기본 임포트
!pip install transformers
from transformers import TFBertForMaskedLM
from transformers import AutoTokenizer
model = TFBertForMaskedLM.from_pretrained('bert-large-uncased')
tokenizer = AutoTokenizer.from_pretrained('bert-large-uncased')
https://huggingface.co/google-bert/bert-large-uncased
영어에 대한 사전 학습된 모델로, 마스크 언어 모델링(MLM) 목적을 사용합니다.
소개된 논문: https://arxiv.org/abs/1810.04805
이 저장소 에서 처음 공개되었습니다 .
이 모델은 대소문자 구분하지 않습니다.
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
We introduce a new language representation model called BERT, which stands for Bidirectional Encoder Representations from Transformers. Unlike recent language representation models, BERT is designed to pre-train deep bidirectional representations from unla
arxiv.org
google-bert/bert-large-uncased · Hugging Face
BERT large model (uncased) Pretrained model on English language using a masked language modeling (MLM) objective. It was introduced in this paper and first released in this repository. This model is uncased: it does not make a difference between english an
huggingface.co
2. BERT입력
inputs = tokenizer('Soccer is a really fun [MASK].', return_tensors='tf')
# 토크나이저로 변환된 결과에서 문장을 구분하는 세그먼트 인코딩 결과확인
inputs['token_type_ids']
<tf.Tensor: shape=(1, 9), dtype=int32, numpy=array([[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)>
마스크를 주고 리턴타입은 기본적으로 파이토치지만 텐서객체로 리턴할수도 있습니다.
그래서 tf로 주었습니다.
텐서객체로 토큰화된 객체값이 나오게되는것을 확인할 수 있습니다.
현재의 입력은 문장이 두 개가 아니라 한 개이므로 여기서는 문장길이만큼의 0 시퀀스를 얻습니다.
두번째 문장이 시작되는 구간부터는 1의 시퀀스가 나오게되지만, 여기서는 해당되지않겠죠.
토크나이저로 변환된 결과에서 attention_mask를 통해서 실제 단어와 패딩 토큰을 구분하는 용도인 어텐션 마스크 확인이 가능합니다.
inputs = ['attention_mask]
#결과
<tf.Tensor: shape=(1, 9), dtype=int32, numpy=array([[1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)>
현재의 입력에서는 패딩이 없으니 여기서는 문장길이만큼의 1시퀀스를 얻습니다.
그런데 만약에 뒤에 패딩이 있었다면 패딩이 시작되는 구간부터 0의 시퀀스가 나오게됩니다.
여기서는 역시나 해당되지 않습니다.
[MASK] 토큰 예측하기
from transformers import FillMaskPipeline
pip = FillMaskPipeline(model=model, tokenizer=tokenizer)
pip('Soccer is a really fun [MASK].')
의 결과가 나타난것을 볼 수 있습니다.
마스크 위치에는 sport, game, thing, activity이다 라는것을 예측하고있습니다. 꽤 그럴싸하죠~
pip('The Avengers is a really fun [MASK].')
Avengers라는 영화를 말했는데도 예측을 하는지 궁금했는데
사전학습된 모델은 진짜 대단하다는것을 알 수 있습니다. 영화로 제대로 인식했다는것을 알 수 있습니다.
pip('I went to the [MASK] this morning.')
여기서 잘 보면 정관사 THE를 붙였는데 아래는 the를 붙이지 않은것에 대해서 또 해보겠습니다.
현재는 장소를 잘 예측하고 있는것을 확인할 수 있습니다.
pip('I went to [MASK] this morning.')
the가 안붙는것들에 대해서 예측을 하고있다는것을 알 수 있습니다.
wow자연어의 매력은 진짜 어마무시하네요.
한국어 BERT의 MLM
마스크드 언어 모델과 토크나이저
model = TFBertForMaskedLM.from_pretrained('klue/bert-base')
tokenizer = AutoTokenizer.from_pretrained('klue/bert-base')
# https://huggingface.co/klue/bert-base
klue는 한국어에 대해서 사전학습된 모델입니다.
BERT입력
inputs = tokenizer('축구는 정말 재미있는 [MASK]다.', return_tensors='tf')
여기서 INPUT을 하면 토크나이저가 잘 된 것을 볼 수 있습니다
2, 4713, 2259...으로 쭉 나열되어있는것을 확인할 수 잇습니다. 정수토큰화 완료!
그리고 한문장이기때문에
inputs['token_type_ids']
# numpy=array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
inputs['attention_mask']
# numpy=array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
가 되는것도 확인할 수 있습니다.
한국어 [MASK] 토큰 예측하기
pip = FillMaskPipeline(model=model, tokenizer=tokenizer)
pip('축구는 정말 재미있는 [MASK]다.')
오 제가 생각한것보다 더 다양하게 나오는것을 볼 수 있었습니다.
물론 스포츠가 좀 압도적으로 높다는것을 확인할 수 있습니다.
pip('어벤져스는 정말 재미있는 [MASK]다.')
구글 BERT의 NSP
1. 다음문장 예측 모델과 토크나이저
from transformers import TFBertForNextSentencePrediction
# https://huggingface.co/transformers/v3.0.2/model_doc/bert.html#tfbertfornextsentenceprediction
model = TFBertForNextSentencePrediction.from_pretrained('bert-base-uncased')
tokenizer = AutoTokenizer.from_pretrained('bert-base-uncased')
# https://huggingface.co/google-bert/bert-base-uncased
2. BERT의 입력
# 다음문장예측 을 위해 문맥상으로 실제 이어지는 두개의 문장
prompt = "In Italy, pizza served in formal settings, such as at a restaurant, is presented unsliced."
next_sentence = "pizza is eaten with the use of a knife and fork. In casual settings, however, it is cut into wedges to be eaten while held in the hand."
# 두개의 문장, 정수 인코딩
encoding = tokenizer(prompt, next_sentence, return_tensors='tf')
encoding
''''
{'input_ids': <tf.Tensor: shape=(1, 58), dtype=int32, numpy=
array([[ 101, 1999, 3304, 1010, 10733, 2366, 1999, 5337, 10906,
1010, 2107, 2004, 2012, 1037, 4825, 1010, 2003, 3591,
4895, 14540, 6610, 2094, 1012, 102, 10733, 2003, 8828,
2007, 1996, 2224, 1997, 1037, 5442, 1998, 9292, 1012,
1999, 10017, 10906, 1010, 2174, 1010, 2009, 2003, 3013,
2046, 17632, 2015, 2000, 2022, 8828, 2096, 2218, 1999,
1996, 2192, 1012, 102]], dtype=int32)>, 'token_type_ids': <tf.Tensor: shape=(1, 58), dtype=int32, numpy=
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)>, 'attention_mask': <tf.Tensor: shape=(1, 58), dtype=int32, numpy=
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)>}
'''
# 정수 인코딩된 결과
encoding['input_ids']
'''
<tf.Tensor: shape=(1, 58), dtype=int32, numpy=
array([[ 101, 1999, 3304, 1010, 10733, 2366, 1999, 5337, 10906,
1010, 2107, 2004, 2012, 1037, 4825, 1010, 2003, 3591,
4895, 14540, 6610, 2094, 1012, 102, 10733, 2003, 8828,
2007, 1996, 2224, 1997, 1037, 5442, 1998, 9292, 1012,
1999, 10017, 10906, 1010, 2174, 1010, 2009, 2003, 3013,
2046, 17632, 2015, 2000, 2022, 8828, 2096, 2218, 1999,
1996, 2192, 1012, 102]], dtype=int32)>
'''
여기서 101과 102는 특별한 토큰입니다. [CLS]토큰 그리고 [SEP]토큰입니다.
print(tokenizer.cls_token, ':', tokenizer.cls_token_id)
print(tokenizer.sep_token, ':', tokenizer.sep_token_id)
확인을 해보자면
[CLS]는 101 [SEP]는 102라는것을 알 수 있습니다.
인코딩 결과를 다시 디코딩해서 입력을 확인해보면
# 인코딩 결과를 다시 디코딩하여 입력 확인 가능.
tokenizer.decode(encoding['input_ids'][0])
[CLS] in italy, pizza served in formal settings, such as at a restaurant, is presented unsliced. [SEP] pizza is eaten with the use of a knife and fork. in casual settings, however, it is cut into wedges to be eaten while held in the hand. [SEP]
라는 결과가 나옵니다.
BERT에서 두개의 문장이 입력으로 들어갈 경우에는 맨 앞에는 [CLS]토큰이 존재하고
첫번째 문장이 끝내면 [SEP] 토큰 그리고 두번째 문장이 종료되었을때 다시 추가적으로 [SEP]토큰이 추가됩니다.
문장을 구분하는 세그먼트 임베딩 결과도 확인할 수 있습니다.
encoding['token_type_ids']
'''
<tf.Tensor: shape=(1, 58), dtype=int32, numpy=
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int32)>
'''
이제 0과 1이 구분되는것을 확인할 수 있었습니다.
다음 문장 예측하기
import tensorflow as tf
logits = model(encoding['input_ids'], token_type_ids=encoding['token_type_ids'])[0]
softmax = tf.keras.layers.Softmax()
probs = softmax(logits)
print(probs)
#결과값
tf.Tensor([[9.9999714e-01 2.8381912e-06]], shape=(1, 2), dtype=float32)
모델입력으로 넣고 logit으로 받고 softmax를 입력하게되면 텐서플로우형으로결과가 나오는것을 확인할 수 있습니다.
인덱스0 [0]은 문장이 하나이기때문에 추가했습니다. 또한 probs는 확률값을 의미합니다.
print('최종 예측 레이블 : ', tf.math.argmax(probs, axis=-1).numpy())
결과값
최종 예측 레이블 : [0]
실질적으로 이어지는 문장의 레이블은 0이고 이어지지 않는 문장의 레이블은 1입니다.
이어지지 않는 두개의 문장으로 테스트를해보겠습니다.
prompt = "In Italy, pizza served in formal settings, such as at a restaurant, is presented unsliced."
next_sentence = "The sky is blue due to the shorter wavelength of blue light."
encoding = tokenizer(prompt, next_sentence, return_tensors='tf')
logits = model(encoding['input_ids'], token_type_ids=encoding['token_type_ids'])[0]
softmax = tf.keras.layers.Softmax()
probs = softmax(logits)
print('최종 예측 레이블 : ', tf.math.argmax(probs, axis=-1).numpy())
그러면 최종예측 레이블은 [1]이 나옵니다.
앞뒤가 이어지지 않는 문장이니 당연한 결과라고 볼 수 있겠죠?
한국어 BERT의 NSP
다음 문장 예측모델과 토크나이저
model = TFBertForNextSentencePrediction.from_pretrained('klue/bert-base', from_pt=True)
tokenizer = AutoTokenizer.from_pretrained('klue/bert-base')
사전학습된 모델을 로딩해오려고 합니다.
다음 문장 예측하기
두개의 문장을 작성해보겠습니다.
아래 문장은 이어지는 문장이 있는데 이 문장의 레이블은 어떤것인지 예측해보려고 합니다.
# 이어지는 두 개의 문장
prompt = "2002년 월드컵 축구대회는 일본과 공동으로 개최되었던 세계적인 큰 잔치입니다."
next_sentence = "여행을 가보니 한국의 2002년 월드컵 축구대회의 준비는 완벽했습니다."
encoding = tokenizer(prompt, next_sentence, return_tensors='tf')
logits = model(encoding['input_ids'], token_type_ids=encoding['token_type_ids'])[0]
softmax = tf.keras.layers.Softmax()
probs = softmax(logits)
print('최종 예측 레이블 :', tf.math.argmax(probs, axis=-1).numpy())
최종 예측 레이블은 0이 나왔습니다.
또한 상관 없는 두개의 문장을 한국어로 보자면
# 상관없는 두 개의 문장
prompt = "2002년 월드컵 축구대회는 일본과 공동으로 개최되었던 세계적인 큰 잔치입니다."
next_sentence = "극장가서 로맨스 영화를 보고싶어요"
encoding = tokenizer(prompt, next_sentence, return_tensors='tf')
logits = model(encoding['input_ids'], token_type_ids=encoding['token_type_ids'])[0]
softmax = tf.keras.layers.Softmax()
probs = softmax(logits)
print('최종 예측 레이블 :', tf.math.argmax(probs, axis=-1).numpy())
이것은 최종예측레이블이 1이되는것을 확인할 수 있습니다.
'AI > 자연어처리' 카테고리의 다른 글
GPT (37) (0) | 2025.01.09 |
---|---|
한국어 BERT 를 이용한 네이버 영화 리뷰 분류 (36) (0) | 2025.01.08 |
BERT(Bidirectional Encoder Representations from Transformers)_(34) (0) | 2025.01.06 |
Transformer (33-4 한국어 챗봇 구현하기) (1) | 2025.01.03 |
Transformer (33-3) (1) | 2025.01.02 |