[NLP] Data Preprocessing

Bobae·2023년 10월 12일
0

Model을 훈련하려면 dataset를 모델에 맞는 입력 형식(Tensor)으로 전처리 해야합니다. 우리의 데이터가 텍스트, 이미지, 오디오이던 간에, 모든 데이터는 Tensor batch 형태로 변환되어야 합니다.

HuggingFace의 Transformers는 데이터를 전처리하기 위한 클래스 및 함수를 제공합니다. NLP에서는, 데이터 전처리를 위해 Tokenizer를 사용해서 텍스트를 Token sequence(tokens)로 변환하고, tokens들을 모델의 input이 되는 숫자Tensor로 변환합니다.

만약 우리가 pretrained 모델을 사용한다면, pretrained된 토크나이저를 사용해야합니다. 이렇게 하면 텍스트가 사전 학습 코퍼스와 동일한 방식으로 분할되고, 사전 학습 중에 동일한 해당 토큰-인덱스(일반적으로 vocab)를 사용합니다.

Tokenizer Load

pretrained 토크나이저는 AutoTokenizer.from_pretrained() 메소드를 통해 로드할 수 있습니다. 이는 모델의 pretrained vocab를 다운로드합니다.

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("roberta-base")

Text Encoding

그리고 우리의 테스트 텍스트를 토크나이저에 통과시켜봅시다. tokenizer(text) 메소드를 통해 통과시킬 수 있습니다.

encoded_input = tokenizer("This is the study of natural language processing")
encoded_input
#output
{'input_ids': [0, 713, 16, 5, 892, 9, 1632, 2777, 5774, 2], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

토크나이저는 최대 3개의 dictionary 아이템들을 리턴합니다.

  • input_ids: 토큰화된 input에서 각 토큰에 상응하는 index들의 값
  • attention_mask: 토큰화된 input에서 해당 토큰에 attention할것인지 아닐것인지 나타내는 값
  • token_type_ids: 위의 예시에서는 없지만, 둘 이상의 시퀀스가 있는 경우 토큰이 속한 시퀀스를 식별합니다.

Text Decoding

input_ids를 디코딩해서 input을 다시 확인해봅시다. tokenizer.decode(input_ids) 메소드를 통해 디코딩할 수 있습니다.

tokenizer.decode(encoded_input["input_ids"])
#output
'<s>This is the study of natural language processing</s>'

Special Token

스페셜 토큰이란 Transformer 모델에서 사용되는 특수 토큰입니다. 주로 tokenizer는 자동으로 스페셜 토크들을 추가해줍니다.

위의 예시에서보면 우리의 토크나이저는 스페셜 토큰 s를 문장 앞뒤로 추가한 것을 볼 수 있습니다. 이들은 토크나이저를 통해, 토큰들을 인코딩할 때 추가되는 특별한 토큰입니다. RoBERTa 토크나이저는 오직 <s>(BOS token)</s>(SEP token)만 가지고 있습니다.

스페셜 토큰은 여러가지 종류가 있습니다.

  • bos_token: 문장의 시작부분을 나타내는 토큰입니다.
  • eos_token: 문장의 끝을 나타내는 토큰입니다.
  • sep_token: 문장과 문장의 구분을 나타내는 토큰입니다. 주로 두 문장을 하나로 결합할 때 사용됩니다.
  • cls_token: 주로 classification 문제에서 사용되는 토큰으로, 문장의 시작에 추가되며, 이를 통해 모델은 입력문장에 대한 분류를 수행할 수 있습니다.
  • mask_token: 언어 모델 학습과 같은 곳에서 사용됩니다. 모델이 문장에서 어떤 부분을 예측하도록 만들기 위해 랜덤하게 선택된 토큰들을 가려주는데 사용됩니다.
    - I ate [mask] apple.
    • [mask]: red, delicious

Padding

Padding은 주로 시퀀스의 길이를 맞추기 위해 사용됩니다. 모든 시퀀스를 동일한 길이로 만들기 위해 짧은 시퀀스에 패딩을 추가할 때 사용됩니다.
만약 모델이 100개의 토큰을 필요로 한다면 80개의 토큰이 있는 시퀀스에 나머지 20개를 채우기 위해 pad_token이 사용됩니다. padding=True 설정을 통해 패딩을 설정할 수 있습니다.

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]

encoded_input = tokenizer(batch_sentences, padding=True)
print(encoded_input)
#output
{'input_ids': [[0, 1708, 99, 59, 200, 7080, 116, 2, 1, 1, 1, 1, 1], 
			   [0, 6766, 75, 206, 37, 2215, 59, 200, 7080, 6, 30533, 4, 2], 
               [0, 2264, 59, 19353, 29, 918, 116, 2, 1, 1, 1, 1, 1]], 
'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0]]}

첫문장과 마지막 문장의 input_ids를 보면 나머지 부분이 1로 채워진 것을 볼 수 있습니다.

Truncation

반대의 케이스로 만약 시퀀스의 길이가 너무 길면 어떨까요? 모든 시퀀스를 동일한 길이로 맞추기 위해 긴 시퀀스를 잘라냅니다. truncation=True 설정을 통해 잘라낼 수 있습니다.

batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]

encoded_input = tokenizer(batch_sentences, padding=True, truncation=True)
print(encoded_input)
#output
{'input_ids': [[0, 1708, 99, 59, 200, 7080, 116, 2, 1, 1, 1, 1, 1], 
			  [0, 6766, 75, 206, 37, 2215, 59, 200, 7080, 6, 30533, 4, 2], 
              [0, 2264, 59, 19353, 29, 918, 116, 2, 1, 1, 1, 1, 1]], 
'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0]]}

tensor로 만들기

마지막 작업은 input을 텐서로 변환해주어야 합니다. return_tensors=설정을 통해 설정 할 수 있습니다.

encoded_input = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="pt")
print(encoded_input)
#output
{'input_ids': tensor([[0, 1708,    99,    59,   200,  7080,   116, 2, 1, 1, 1, 1, 1],
        			  [0, 6766, 75, 206, 37,  2215, 59, 200, 7080, 6, 30533, 4, 2],
        			  [0, 2264, 59, 19353, 29, 918, 116, 2, 1, 1, 1, 1, 1]]), 
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0]])}

profile
현재 머신러닝, 딥러닝을 공부하고 있습니다.

0개의 댓글

관련 채용 정보