🐍 Python & library/HuggingFace

[HuggingFace] Tokenizer의 역할과 기능, Token ID, Input ID, Token type ID, Attention Mask

복만 2022. 6. 3. 15:45

HuggingFace의 Tokenizer을 사용하면 Token (Input) ID, Attention Mask를 포함한 BatchEncoding을 출력으로 받게 된다.

이 글에서는 이러한 HuggingFace의 Model input에 대해 정리해 보고자 한다.

 

Tokenizer class에 대한 게시물은 여기에서 확인할 수 있다.

 

참고: Official Docs

 

Glossary

Fine-tune for downstream tasks

huggingface.co

 

Tokenizer

HuggingFace의 Tokenizer을 다음과 같이 우선 정의한다. 본 예제에서는 BertTokenizer을 사용한다.

from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-cased")

sequence = "A Titan RTX has 24GB of VRAM"

 

 

🔖 Tokenize

tokenize method를 이용하면, input sequence를 tokenizer vocabulary에 있는 token (word or subword)들로 쪼개어 준다.

tokenized_sequence = tokenizer.tokenize(sequence)
print(tokenized_sequence)
>> ['A', 'Titan', 'R', '##T', '##X', 'has', '24', '##GB', 'of', 'V', '##RA', '##M']

하나의 문장이 각 단어들로 쪼개진 것을 확인할 수 있다.

 

 

👉 Encode

Tokenizer에 sequence를 입력으로 주면 model에 들어갈 input encoding을 생성할 수 있다.

inputs = tokenizer(sequence)

이때 inputs는 model에 필요한 Input ID, Token type ID, Attention mask 등을 포함한 dictionary로 구성되어 있다.

 

 

Input ID

encoded_sequence = inputs["input_ids"]
print(encoded_sequence)
>> [101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102]

"input_ids"는 각 token의 ID에 해당한다. 그런데 자세히 보면 tokenize method로 얻은 tokenized_sequence의 길이와 encoded_sequence의 길이가 다른 것을 확인할 수 있다.

그 이유는 Tokenizer가 자동으로 "special tokens"를 앞뒤로 추가했기 때문이다.

 

 

 👈 Decode

decode method를 이용하면 encoding 된 token ID를 다시 sequence로 변환할 수 있다.

decoded_sequence = tokenizer.decode(encoded_sequence)
print(decoded_sequence)
>> [CLS] A Titan RTX has 24GB of VRAM [SEP]

이를 통해 확인해보면, encoding 과정에서 앞뒤로 [CLS] token과 [SEP] token이 추가된 것을 볼 수 있다.

 

 

Token Type IDs

일부 model의 경우, 두 문장이 이어지는 문장인지 아닌지를 판단하는 task를 수행하기도 한다.

이 경우 input의 형식은 다음과 같게 된다.

# [CLS] SEQUENCE_A [SEP] SEQUENCE_B [SEP]

 

이 경우 첫 번째 sequence (SEQUENCE_A)와 두 번째 sequence (SEQUENCE_B)에 서로 다른 ID를 부여해주는 것이 바로 Token type ID이다.

from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
sequence_a = "HuggingFace is based in NYC"
sequence_b = "Where is HuggingFace based?"

encoded_dict = tokenizer(sequence_a, sequence_b)

print(encoded_dict["token_type_ids"])
>> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]

 

 

Attention mask

Attention mask는 optional한 output으로, Tokenizer 호출 시 return 여부를 함께 argument로 줄 수 있다.

 

Attention mask는 model이 어떤 token에 집중 (attend)해야 할 지를 알려준다.

 

서로 다른 길이의 두 문장의 encoding의 길이를 맞춰주기 위해 다음과 같이 padding을 이용한다.

from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-cased")

sequence_a = "This is a short sequence."
sequence_b = "This is a rather long sequence. It is at least longer than the sequence A."

padded_sequences = tokenizer([sequence_a, sequence_b], padding=True)
print(padded_sequences["input_ids"])
>> [[101, 1188, 1110, 170, 1603, 4954, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 1188, 1110, 170, 1897, 1263, 4954, 119, 1135, 1110, 1120, 1655, 2039, 1190, 1103, 4954, 138, 119, 102]]

 

이 때 padding 된 token과 그렇지 않은 token을 알려주는 것이 attention mask이다.

Input에서 padding된 부분은 0으로, 그렇지 않은 부분을 1로 하는 mask를 return한다.

padded_sequences["attention_mask"]
>> [[1, 1, 1, 1, 1, 1, 1, 1, 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]]
반응형