[Huggingface 🤗 Transformers Tutorial] 3. Preprocess
Updated:
※ 이 글의 원문은 이 곳에서 확인할 수 있습니다. ※ 모든 글의 내용을 포함하지 않으며 새롭게 구성한 내용도 포함되어 있습니다.
tokenizer를 이용해서 주어진 text를 model이 요구하는 형식에 맞게 전처리하는 과정을 간단하게 익혀봅니다.
!pip install transformers
먼저 전처리할 문장 3개를 정의힙나다.
- 해당 문장들은 모두 위키백과-이순신에서 일부 가져왔습니다.
texts = ['이순신은 조선 중기의 무신이었다.', '본관은 덕수, 자는 여해, 시호는 충무였으며, 한성 출신이었다.', '옥포해전은 이순신의 첫 승전을 알리게 된 해전이다.']
Tokenize
tokenization에 필요한 tokenizer를 불러옵니다. 여기서는 ‘bert-base-multilingual-cased’를 사용합니다.
MODEL_NAME = 'bert-base-multilingual-cased'
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
tokenizer를 이용해 tokenization하는 방법은 3가지가 있었습니다.
- tokenizer를 call하는 방식
- tokenize() 메소드
- encode() 메소드
2,3번 방식은 tokenization을 하지만 model이 요구하는 입력 형태로 반환하지 않습니다. 단순히 tokenization과 encoding만 해줄 뿐입니다.
1번 방식을 이용해 model이 요구하는 모든 입력 요소를 반환하겠습니다.
encoded_input = tokenizer(texts[0])
print(encoded_input)
{'input_ids': [101, 9638, 119064, 25387, 10892, 59906, 9694, 46874, 9294, 25387, 58926, 119, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
한 문장이 아니라 여러 문장들을 동시에 tokenization하기 위해서는 입력으로 문장 리스트를 넣어주면 됩니다.
encoded_inputs = tokenizer(texts)
for key in encoded_inputs.keys():
print(f"{key}(길이: {len(encoded_inputs[key])}): {encoded_inputs[key]}")
input_ids(길이: 3): [[101, 9638, 119064, 25387, 10892, 59906, 9694, 46874, 9294, 25387, 58926, 119, 102], [101, 9358, 101958, 9075, 15891, 113, 3789, 4867, 114, 117, 9651, 11018, 9565, 14523, 113, 4886, 7247, 114, 117, 9485, 100543, 9770, 32537, 113, 3803, 4794, 114, 9573, 24098, 117, 9954, 17138, 9768, 25387, 58926, 119, 102], [101, 9581, 55530, 14523, 16617, 10892, 9638, 119064, 87143, 9750, 9484, 54918, 9524, 12692, 14153, 9099, 9960, 16617, 11925, 119, 102]]
token_type_ids(길이: 3): [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
attention_mask(길이: 3): [[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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
text는 총 3개 였습니다. input_ids, token_type_ids, atttention_mask 모두 3개가 만들어진 것을 확인할 수 있습니다.
Pad
모델의 입력으로 사용하기 위해서는 batch로 들어오는 모든 sequence의 길이가 동일해야합니다. padding token을 추가하여 sequence의 길이를 동일하게 맞출 수 있습니다.
# pad token id
print(tokenizer.vocab['[PAD]'])
0
encoded_inputs = tokenizer(texts, padding=True)
for key in encoded_inputs.keys():
print(key,":")
for data in encoded_inputs[key]:
print(data)
input_ids :
[101, 9638, 119064, 25387, 10892, 59906, 9694, 46874, 9294, 25387, 58926, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[101, 9358, 101958, 9075, 15891, 113, 3789, 4867, 114, 117, 9651, 11018, 9565, 14523, 113, 4886, 7247, 114, 117, 9485, 100543, 9770, 32537, 113, 3803, 4794, 114, 9573, 24098, 117, 9954, 17138, 9768, 25387, 58926, 119, 102]
[101, 9581, 55530, 14523, 16617, 10892, 9638, 119064, 87143, 9750, 9484, 54918, 9524, 12692, 14153, 9099, 9960, 16617, 11925, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
token_type_ids :
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
attention_mask :
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
가장 길이가 긴 2번째 문장을 기준으로 1, 3번째 문장에 padding token이 추가된 것을 확인할 수 있습니다.
Truncation
model이 입력으로 받을 수 있는 sequence의 길이는 정해져있습니다. 너무 긴 길이는 다루지 못할 수 있습니다.
truncation=True parameter를 이용하여 maximum length보다 길 경우 초과한 만큼 길이를 잘라냅니다.
보통 max_length parameter도 같이 사용하기도 합니다. max_length를 이용하여 maximum length를 통제할 수 있습니다.
print(tokenizer(texts, padding=True, truncation=True))
{'input_ids': [[101, 9638, 119064, 25387, 10892, 59906, 9694, 46874, 9294, 25387, 58926, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 9358, 101958, 9075, 15891, 113, 3789, 4867, 114, 117, 9651, 11018, 9565, 14523, 113, 4886, 7247, 114, 117, 9485, 100543, 9770, 32537, 113, 3803, 4794, 114, 9573, 24098, 117, 9954, 17138, 9768, 25387, 58926, 119, 102], [101, 9581, 55530, 14523, 16617, 10892, 9638, 119064, 87143, 9750, 9484, 54918, 9524, 12692, 14153, 9099, 9960, 16617, 11925, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}
주어진 text는 BERT가 다룰 수 있는 maximum length보다 length가 작기 때문에 truncation이 되지 않은 것을 확인할 수 있습니다.
encoded_inputs = tokenizer(texts, max_length=12)
for key in encoded_inputs.keys():
print(key,":")
for data in encoded_inputs[key]:
print(data)
input_ids :
[101, 9638, 119064, 25387, 10892, 59906, 9694, 46874, 9294, 25387, 58926, 102]
[101, 9358, 101958, 9075, 15891, 113, 3789, 4867, 114, 117, 9651, 102]
[101, 9581, 55530, 14523, 16617, 10892, 9638, 119064, 87143, 9750, 9484, 102]
token_type_ids :
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
attention_mask :
[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]
max_length를 이용하면 maximum length를 조절할 수 있음을 확인할 수 있습니다.
Build tensors
return_tensors parameter를 이용하여 원하는 형태의 tensor로 반환할 수 있습니다.
- return_tensors=’pt’: PyTorch
- return_tensors=’tf’: TensorFlow
encoded_inputs = tokenizer(texts, padding=True, truncation=True, max_length=15, return_tensors='pt')
print(encoded_inputs)
{'input_ids': tensor([[ 101, 9638, 119064, 25387, 10892, 59906, 9694, 46874, 9294,
25387, 58926, 119, 102, 0, 0],
[ 101, 9358, 101958, 9075, 15891, 113, 3789, 4867, 114,
117, 9651, 11018, 9565, 14523, 102],
[ 101, 9581, 55530, 14523, 16617, 10892, 9638, 119064, 87143,
9750, 9484, 54918, 9524, 12692, 102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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]])}
Leave a comment