Deep Learning (TF, Keras, PyTorch)/Natural Language Processing

토큰화(Tokenization)의 유형과 서브워드 토큰화 알고리즘 (Subword tokenization algorithms)

Rfriend 2024. 2. 4. 00:19

이번 포스팅에서는 토큰화의 정의와 유형, 주요 알고리즘과 토크나이저를 구축할 때 주의할 사항과 평가지표에 대해서 소개하겠습니다. 

 

1. 토큰화(Tokenization)이란 무엇인가? 

2. 서브워드 토큰화 알고리즘 (Subword Tokenization Algorithms)에는 무엇이 있나? 

3. 토크나이저 구축 시 주의할 점은 무엇인가?  

4. 토크나이저의 성능을 평가하는 지표에는 무엇이 있나? 

5. Hugging Face의 Tokenizers 모듈로 BPE tokenizer 구현해보기

 

 

1. 토큰화(Tokenization)이란 무엇인가? 

 

NLP(자연어 처리)에서 토큰화(Tokenization)는 텍스트를 더 작은 단위로 나누는 과정을 의미합니다. 이 작은 단위들을 '토큰(token)'이라고 부릅니다. 토큰은 단어, 문자, 구, 문장, 서브워드(Subword) 등 다양한 기준으로 나눌 수 있으며, 토큰화의 목적은 주로 텍스트 데이터를 분석하기 용이하게 전처리하는 것입니다.  

주어진 문장 "토큰화는 자연어처리를 하는데 있어 핵심적인 작업입니다"에 대한 다양한 토큰화 예시는 다음과 같습니다.  

- 문장 단위 토큰화 (Sentence tokenization):  ["토큰화는 자연어처리를 하는데 있어 핵심적인 작업입니다"]  
- 단어 단위 토큰화 (Word tokenization):  ["토큰화는", "자연어처리를", "하는데", "있어", "핵심적인", "작업입니다"]  
- 서브워드 단위 토근화 (Subword tokenization):  [["토큰", "화는", "자연어", "처리를", "하는데", "있어", "핵심", "적인", "작업", "입니다"]  
- 문자 단위 토큰화 (Character Tokenization): 토", "콘", "화", "는", " ", "자", "연", "어", "처", "리", "를", " ", "하", "는", "데", " ", "있", "어", " ", "핵", "심", "적", "인", " ", "작", "업", "입", "니", "다"]  


특히, Subword 토큰화는 텍스트를 더 작은 의미 단위로 나누는 방법에 초점을 맞추며, 이는 언어의 모호성을 줄이고, 모르는 단어(out-of-vocabulary, OOV) 문제를 해결하며, 언어 모델의 크기를 줄이는 데 도움이 됩니다. 

 

 

2. 서브워드 토큰화 알고리즘 (Subword Tokenization Algorithms)에는 무엇이 있나?  


주요 Subword 토큰화 알고리즘으로는 BPE, WordPiece, SentencePiece, Unigram Language Model 이 있습니다.  

 

토큰화 알고리즘

* 이미지 출처: https://blog.floydhub.com/tokenization-nlp/

 

 


(1) Byte Pair Encoding (BPE): BPE는 데이터 압축 알고리즘에서 유래되었으며, 가장 빈번하게 등장하는 바이트 쌍(most frequent pair of bytes)을 반복적으로 병합하여 텍스트를 토큰화합니다. NLP에서는 문자열 쌍을 병합하여 사용되며, 이 과정을 통해 공통적으로 나타나는 문자열 패턴을 효율적으로 인코딩할 수 있습니다. 

(2) WordPiece: WordPiece는 BPE와 유사하지만, 병합 과정에서 언어 모델의 가능성(likelihood)을 최대화하는 쌍을 선택합니다. 이는 주로 Google의 BERT 모델에서 사용됩니다.  

(3) SentencePiece: SentencePiece는 언어에 구애받지 않고 원시 텍스트를 직접 토큰화할 수 있게 해주는 알고리즘으로, 미리 정의된 언어나 문법 규칙에 의존하지 않습니다. 이는 BPE나 WordPiece와 같은 알고리즘을 포함하여, 텍스트를 바이트 레벨(Byte-level)에서 처리함으로써 언어의 다양성에 대응할 수 있습니다. 

(4) Unigram Language Model: Unigram 언어 모델은 가능한 모든 서브워드 토큰의 집합에서 시작하여, 각 토큰을 제거하는 것이 언어 모델의 확률(Probability)을 최소한으로 감소시키는 방식으로 토큰을 선택합니다. 이 방법은 토큰의 확률 분포를 기반으로 하며, 최종적으로 가장 유용한 서브워드 집합을 결정합니다. 

이러한 Subword 토큰화 방법들은 특히 다양한 언어와 도메인에 걸쳐 효율적인 자연어 이해를 가능하게 하는 데 중요한 역할을 합니다. 각각의 방법은 특정 상황이나 요구에 맞게 선택되며, NLP 모델의 성능과 효율성을 크게 향상시킬 수 있습니다. 

 

 

 

3. 토크나이저 구축 시 주의할 점은 무엇인가?  

 

토크나이저의 구축(Build a Tokenizer)은 자연어 처리(NLP)에서 텍스트 데이터를 사전 정의된 단위(토큰)로 분리하는 프로그램이나 알고리즘을 개발하는 과정을 의미합니다. 이러한 토큰은 단어, 문자, 문장 또는 서브워드(subword) 등이 될 수 있으며, 토큰화 과정은 텍스트 분석, 기계 번역, 감정 분석 등 다양한 NLP 작업의 기초를 형성합니다.  

토크나이저 구축 시 주의할 점으로는 다음과 같은 것들이 있습니다.  

(1) 언어의 특성 이해: 처리하려는 언어의 구문적, 의미적 특성을 이해하는 것이 중요합니다. 예를 들어, 공백으로 단어를 구분하는 언어(예: 영어)와 달리, 공백 없이 문자가 연속되는 언어(예: 중국어)는 다른 접근 방식을 요구합니다.  

(2) 도메인 특성 고려: 텍스트 데이터가 속한 도메인(예: 의료, 법률, 일상 대화)에 따라 사용되는 언어가 다를 수 있습니다. 전문 용어나 구어체 표현을 적절히 처리할 수 있는 토크나이저를 구축해야 합니다.  

(3) 성능과 정확도: 토크나이저의 성능과 정확도는 다운스트림 NLP 작업의 결과에 직접적인 영향을 미칩니다. 높은 정확도로 토큰을 식별하면서도, 처리 시간이 너무 길지 않도록 효율성을 고려해야 합니다.  

(4) 확장성과 유연성: 언어는 시간이 지남에 따라 변하고, 새로운 단어나 표현이 등장합니다. 따라서, 토크나이저는 새로운 데이터나 도메인에 쉽게 적용할 수 있도록 확장 가능하고 유연해야 합니다.  

(5) 다양한 토큰화 기법 고려: 단어, 문장, 문자, 서브워드 토큰화 등 다양한 토큰화 기법 중에서 목적에 가장 적합한 방법을 선택해야 합니다. 때로는 여러 기법을 조합하여 사용하는 것이 더 효과적일 수 있습니다.  

(6) 사전 및 사후 처리: 토큰화 과정에서 발생할 수 있는 문제(예: 구두점 처리, 대소문자 구분, 불용어 제거 등)를 해결하기 위해 적절한 사전 처리(pre-processing) 및 사후 처리(post-processing) 단계를 고려해야 합니다.  

(7) 평가 및 테스트: 개발한 토크나이저의 성능을 정확히 평가하기 위해 다양한 데이터 세트와 시나리오에서 테스트를 수행해야 합니다. 이를 통해 토크나이저의 강점과 약점을 파악하고 개선할 수 있습니다.  

토크나이저를 구축할 때 이러한 주의 사항을 고려하면, 다양한 언어와 도메인에 걸쳐 효과적으로 작동하는 강력하고 유연한 토크나이저를 개발할 수 있습니다.  

 

 

4. 토크나이저의 성능을 평가하는 지표에는 무엇이 있나? 

 

토크나이저 성능을 측정하는 데 있어서 "subword fertility (서브워드 다산성)", "proportion of continued words (연속된 단어의 비율)", 그리고 "coverage (커버리지)" 지표 등이 있습니다.  


(1) 서브워드 다산성(Subword Fertility): 이 지표는 하나의 고유 단어가 몇 개의 서브워드로 분해되는지를 나타냅니다. 예를 들어, 토크나이저가 단어를 너무 많은 작은 조각으로 나눈다면, 다산성이 높다고 할 수 있습니다. 이는 특정 언어나 도메인에서 토크나이저가 얼마나 세밀하게 단어를 분해하는지를 보여주는 지표로, 너무 높은 다산성은 처리해야 할 토큰의 수가 증가하여 성능 저하를 일으킬 수 있습니다.  

(2) 연속된 단어의 비율(Proportion of Continued Words): 이는 원본 텍스트에서 단어가 서브워드로 분해될 때, 연속적으로 나타나는 서브워드 조각들의 비율을 나타냅니다. 예를 들어, 하나의 단어가 여러 서브워드로 나뉘어 처리될 경우, 이러한 서브워드들이 원본 단어의 의미를 얼마나 잘 유지하고 있는지를 평가할 수 있습니다. 높은 비율은 토크나이저가 단어의 구조를 잘 보존하고 있다는 것을 의미할 수 있습니다.  

(3) 커버리지(Coverage): 커버리지는 토크나이저가 주어진 텍스트 데이터셋 내의 단어나 표현을 얼마나 잘 포착하는지를 나타내는 지표입니다. 높은 커버리지는 토크나이저가 대부분의 단어나 표현을 정확하게 인식하고 처리할 수 있음을 의미하며, 이는 특히 다양한 언어나 도메인에 걸쳐 토크나이저의 범용성을 평가하는 데 유용합니다. 커버리지가 낮다면, 토크나이저가 일부 단어나 표현을 놓치거나 잘못 처리할 가능성이 있음을 나타냅니다.  

이러한 지표들은 토크나이저의 성능을 다각도로 평가하고, 특정 언어나 도메인에 대한 토크나이저의 적합성을 결정하는 데 도움을 줍니다. 

이러한 지표들로 토크나이저 성능을 평가할 때, 트레이드오프를 균형 있게 고려하는 것이 중요합니다.   

예를 들어 서브워드 다산성(Subword fertility)와 계속되는 단어의 비율이 높은 토크나이저는 보이지 않거나 드문 단어들을 인식 가능한 서브워드로 분해함으로써 효과적으로 처리할 수 있을지도 모릅니다. 그러나, 이는 처리 과정의 비효율성으로 이어질 수 있고, 모델이 원래 단어의 전체 맥락이나 의미를 포착하는 능력을 저해할 수도 있습니다.  

높은 커버리지(Coverage)는 일반적으로 바람직하며, 이는 토크나이저가 입력 텍스트를 자신의 어휘로 효과적으로 표현할 수 있음을 의미합니다. 그러나, 매우 높은 커버리지를 달성하기 위해서는 큰 어휘 크기가 필요할 수 있으며, 이는 모델의 복잡성과 계산 요구사항을 증가시킬 수 있습니다.  

요약하자면, 토크나이저의 선택과 그 매개변수의 최적화는 애플리케이션의 특정 요구사항, 처리되는 언어(들)의 특성, 그리고 계산 제약 조건을 고려하여 결정해야 합니다. 이러한 지표들을 균형 있게 고려함으로써, Downstream NLP 작업을 효율적으로 지원하는 토크나이저를 개발하는 데 도움이 될 수 있습니다.  

 

 

 

5. Hugging Face의 Tokenizers 모듈로 BPE tokenizer 구현해보기

 

먼저, 터미널에서 pip install로 Hugging Face의 tokenizers 모듈을 설치합니다. 

 

! pip install -q tokenizers

 

 

 

- tokenizers 모듈의 Tokenizer, BepTrainer 메소드로 BPE tokenizer 훈련하기

 

매개변수로 unk_token (Unknown token), special_tokens 를 등록해줍니다. 

 

## Train the BPE tokenizer
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace

# Initialize a tokenizer with BPE model
tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
tokenizer.pre_tokenizer = Whitespace()

# Initializer a trainer for the BPE model
trainer = BpeTrainer(special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"])

# Sample corpus for training the tokenizer
corpus = [
    "This is an example of how BPE tokenization works.", 
    "BPE is an algorithm for subword tokenization", 
    "BPE tokenization works by repeatedly merging the most frequent pair of characters.", 
]

# Train the tokenizer
tokenizer.train_from_iterator(corpus, trainer)

# tokenizer.train(files=["your_dataset.txt"], trainer=trainer) # for files


tokenizer
# <tokenizers.Tokenizer at 0x1d153181b70>

 

 

일단 tokenizer의 학습이 완료되면, 아래처럼 학습된 tokenizer의 속성값에 접근할 수 있습니다. 

 

 

- BPE tokenizer의 vocab_size 접근해서 가져오기: get_vocab_size()

 

# Accessing the vocabulary size of the tokenizer
vocab_size = tokenizer.get_vocab_size()
print("Vocabulary size:", vocab_size)

# Vocabulary size: 111

 

 

- 학습된 tokenizer의 Vocaburary 에 접근해서 가져오기: get_vocab()

 

# Accessing the vocaburary
vocab = tokenizer.get_vocab()

# The 'vocab' variable is a dictionary where keys are tokens and values are token ids
print(vocab)

# {'z': 33, 'atio': 45, 'ar': 62, 'edl': 69, 'P': 8, 'oken': 42, 'p': 24, 'ken': 
# 41, 'characters': 109, 'Th': 57, 'B': 6, 'E': 7, 'tokenization': 49, 'am': 61, '.': 
# 5, 'ter': 86, 'peat': 81, 'BPE': 46, 'pair': 105, '[UNK]': 0, 'k': 19, 'frequent': 110, 
# 'e': 14, 'y': 32, 'works': 56, 'or': 34, 'repeat': 88, 'fre': 71, 'ample': 93, '[MASK]': 4, 
# 'th': 55, 'aracter': 94, 'example': 97, 'ex': 67, 'most': 103, 'l': 20, 'ks': 52, 'an': 50, 
# 'r': 26, 'h': 17, 'io': 38, 'iz': 40, 'for': 70, 'subword': 106, 'repeatedly': 107, 'b': 11, 
# 'is': 39, 'tokenizatio': 48, 'o': 23, 'u': 29, 'frequ': 99, 'mo': 77, 'wor': 44, 'gi': 72, 
# 'character': 96, 'izatio': 47, 'f': 15, 'w': 30, 'm': 21, 'ai': 59, 'ent': 87, 'er': 51, 
# '[PAD]': 3, 'ithm': 102, 'ho': 74, 'n': 22, 'qu': 83, 'edly': 98, 'merging': 104, 'en': 36, 
# 'algorithm': 108, 'pai': 80, 're': 54, 'ac': 58, 'token': 43, 'BP': 37, 'how': 101, 's': 27, 
# 'bwor': 64, 'le': 76, 'by': 63, 'd': 13, 'al': 60, 'ng': 79, 'acter': 91, 'gor': 73, 't': 28, 
# 'at': 35, 'su': 85, 'T': 9, 'st': 84, 'x': 31, 'of': 53, 'q': 25, '[SEP]': 2, 'eat': 68, 
# 'dl': 66, 'This': 90, 'algor': 92, 'bword': 95, 'the': 89, 'ith': 75, '[CLS]': 1, 'ch': 65, 
# 'i': 18, 'a': 10, 'ple': 82, 'c': 12, 'mer': 78, 'ging': 100, 'g': 16}

 

 

- tokenizer의 {token_id: token} 쌍 가져오기: vocab.items() 를 역변환

 

# You can get "token_id: token" pairs by inverting the vocab dictionary
id_to_token = {id: token for token, id in vocab.items()}

print(id_to_token)
# {33: 'z', 45: 'atio', 62: 'ar', 69: 'edl', 8: 'P', 42: 'oken', 24: 'p', 41: 'ken', 
# 109: 'characters', 57: 'Th', 6: 'B', 7: 'E', 49: 'tokenization', 61: 'am', 5: '.', 
# 86: 'ter', 81: 'peat', 46: 'BPE', 105: 'pair', 0: '[UNK]', 19: 'k', 110: 'frequent', 
# 14: 'e', 32: 'y', 56: 'works', 34: 'or', 88: 'repeat', 71: 'fre', 93: 'ample', 4: '[MASK]', 
# 55: 'th', 94: 'aracter', 97: 'example', 67: 'ex', 103: 'most', 20: 'l', 52: 'ks', 50: 'an', 
# 26: 'r', 17: 'h', 38: 'io', 40: 'iz', 70: 'for', 106: 'subword', 107: 'repeatedly', 11: 'b', 
# 39: 'is', 48: 'tokenizatio', 23: 'o', 29: 'u', 99: 'frequ', 77: 'mo', 44: 'wor', 72: 'gi', 
# 96: 'character', 47: 'izatio', 15: 'f', 30: 'w', 21: 'm', 59: 'ai', 87: 'ent', 51: 'er', 
# 3: '[PAD]', 102: 'ithm', 74: 'ho', 22: 'n', 83: 'qu', 98: 'edly', 104: 'merging', 36: 'en', 
# 108: 'algorithm', 80: 'pai', 54: 're', 58: 'ac', 43: 'token', 37: 'BP', 101: 'how', 27: 's', 
# 64: 'bwor', 76: 'le', 63: 'by', 13: 'd', 60: 'al', 79: 'ng', 91: 'acter', 73: 'gor', 28: 't', 
# 35: 'at', 85: 'su', 9: 'T', 84: 'st', 31: 'x', 53: 'of', 25: 'q', 2: '[SEP]', 68: 'eat', 
# 66: 'dl', 90: 'This', 92: 'algor', 95: 'bword', 89: 'the', 75: 'ith', 1: '[CLS]', 65: 'ch', 
# 18: 'i', 10: 'a', 82: 'ple', 12: 'c', 78: 'mer', 100: 'ging', 16: 'g'}

 


- {token_id: token} 쌍을 token_id 기준으로 오름차순 정렬해서 보기

 

# Sort id_to_token dictionary by IDs
print(sorted(id_to_token.items(), key=lambda x: x[0]))

# [(0, '[UNK]'), (1, '[CLS]'), (2, '[SEP]'), (3, '[PAD]'), (4, '[MASK]'), (5, '.'), (6, 'B'), 
# (7, 'E'), (8, 'P'), (9, 'T'), (10, 'a'), (11, 'b'), (12, 'c'), (13, 'd'), (14, 'e'), (15, 'f'), 
# (16, 'g'), (17, 'h'), (18, 'i'), (19, 'k'), (20, 'l'), (21, 'm'), (22, 'n'), (23, 'o'), 
# (24, 'p'), (25, 'q'), (26, 'r'), (27, 's'), (28, 't'), (29, 'u'), (30, 'w'), (31, 'x'), 
# (32, 'y'), (33, 'z'), (34, 'or'), (35, 'at'), (36, 'en'), (37, 'BP'), (38, 'io'), (39, 'is'), 
# (40, 'iz'), (41, 'ken'), (42, 'oken'), (43, 'token'), (44, 'wor'), (45, 'atio'), (46, 'BPE'), 
# (47, 'izatio'), (48, 'tokenizatio'), (49, 'tokenization'), (50, 'an'), (51, 'er'), (52, 'ks'), 
# (53, 'of'), (54, 're'), (55, 'th'), (56, 'works'), (57, 'Th'), (58, 'ac'), (59, 'ai'), 
# (60, 'al'), (61, 'am'), (62, 'ar'), (63, 'by'), (64, 'bwor'), (65, 'ch'), (66, 'dl'), 
# (67, 'ex'), (68, 'eat'), (69, 'edl'), (70, 'for'), (71, 'fre'), (72, 'gi'), (73, 'gor'), 
# (74, 'ho'), (75, 'ith'), (76, 'le'), (77, 'mo'), (78, 'mer'), (79, 'ng'), (80, 'pai'), 
# (81, 'peat'), (82, 'ple'), (83, 'qu'), (84, 'st'), (85, 'su'), (86, 'ter'), (87, 'ent'), 
# (88, 'repeat'), (89, 'the'), (90, 'This'), (91, 'acter'), (92, 'algor'), (93, 'ample'), 
# (94, 'aracter'), (95, 'bword'), (96, 'character'), (97, 'example'), (98, 'edly'), 
# (99, 'frequ'), (100, 'ging'), (101, 'how'), (102, 'ithm'), (103, 'most'), (104, 'merging'), 
# (105, 'pair'), (106, 'subword'), (107, 'repeatedly'), (108, 'algorithm'), (109, 'characters'), 
# (110, 'frequent')]

 

 

- 토큰이 Vocabulary 에 들어있는지 확인하기: tokenizer.token_to_id(token)

 

# Checking if a token is in the vocabulary
token_id = tokenizer.token_to_id("BPE")

if token_id is not None:
    print("Token 'BPE' is in the vocabulary with ID:", token_id)
else:
    print("Token 'BPE' is not in the vocabulary")
    
# Token 'BPE' is in the vocabulary with ID: 46    


id_to_token[46]
# 'BPE'

 

 

- Sepcial Tokens 와 ID 확인하기

: special_tokens = ["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"]

 

# Accessing Special Tokens and their IDs
# Assuming the tokenizer has been trained or loaded with special tokens
special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"]

for special_token in special_tokens:
    special_token_id = tokenizer.token_to_id(special_token)
    print(f"{special_token} token ID: {special_token_id}")
    
# [UNK] token ID: 0
# [CLS] token ID: 1
# [SEP] token ID: 2
# [PAD] token ID: 3
# [MASK] token ID: 4

 

 

- 새로운 텍스트 토큰화하기: tokenizer.encode(new text)

 

# Tokenize a new text
output = tokenizer.encode("This is a new example to showcase BPE tokenization.")

# Print the tokens and their IDs
print("Tokens:", output.tokens)
print("Token IDs:", output.ids)

# Tokens: ['This', 'is', 'a', 'n', 'e', 'w', 'example', 't', 'o', 's', 'how', 'c', 'a', 's', 'e', 'BPE', 'tokenization', '.']
# Token IDs: [90, 39, 10, 22, 14, 30, 97, 28, 23, 27, 101, 12, 10, 27, 14, 46, 49, 5]

 

 

- 토큰 IDs를 디코딩하기: tokenizer.decode(token_ids)

 

# Decode token IDs reversely
tokenizer.decode(output.ids)

# 'This is a n e w example t o s how c a s e BPE tokenization .'

 

 

- 새로운 토큰을 토크나이저에 추가하기: tokenizer.add_tokens(new_tokens)

 

# Adding new tokens to a tokenizer
# To add new tokens to a tokenizer using the tokenizers library by Hugging Face, you can use the add_tokens method if you're working with a tokenizer that supports dynamic vocabulary modifications. This feature is particularly useful when you have out-of-vocabulary (OOV) tokens that you want to include in your tokenizer's vocabulary for better model performance on specific tasks or domains.

# 1. Install the Tokenizers Library: First, ensure that the tokenizers library is installed. You can install it using pip if you haven't already.
# 2. Load or Initialize Your Tokenizer: Load the tokenizer you wish to modify. This could be a pre-trained tokenizer or a custom one you've created.
# 3. Add New Tokens: Use the add_tokens method to add your new tokens to the tokenizer's vocabulary. The method typically requires a list of new tokens to be added.


# [case 1] Add new tokens to the trained tokenizer above
new_tokens = ["SentencePiece", "Unigram"]
tokenizer.add_tokens(new_tokens)

# Verify if the new tokens were added
# Tokenize a new text
output = tokenizer.encode("SentencePiece Unigram")

# Print the tokens and their IDs
print("Tokens:", output.tokens)
print("Token IDs:", output.ids)

# Tokens: ['SentencePiece', 'Unigram']
# Token IDs: [111, 112]

 

 

- 새로운 토큰을 Hugging Face Hub에 있는 토크나이저에 추가하기: tokenizer.add_tokens(new_tokens)

 

# [case 2] adding new tokens to pretrained tokenizer and model from Hugging Face Hub
# Let's see how to increase the vocabulary of Bert model and tokenizer
tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased")

num_added_toks = tokenizer.add_tokens(["new_tok1", "my_new-tok2"])
print("We have added", num_added_toks, "tokens")

# Notice: resize_token_embeddings expect to receive the full size of the new vocabulary, i.e., the length of the tokenizer.
model.resize_token_embeddings(len(tokenizer))

 

 

- 토크나이저를 직렬화, 역직렬화 (serialization and deserialization of tokenizer)

 

# Serialization and Deserialization
# Serialize tokenizer to string
tokenizer_str = tokenizer.to_str()

print(tokenizer_str)

# {"version":"1.0",
# "truncation":null,
# "padding":null,
# "added_tokens":[{"id":0,"content":"[UNK]","single_word":false,"lstrip":false,"rstrip":false,"normalized":false,"special":true},
# {"id":1,"content":"[CLS]","single_word":false,"lstrip":false,"rstrip":false,"normalized":false,"special":true},{"id":2,"content":"[SEP]","single_word":false,"lstrip":false,"rstrip":false,"normalized":false,"special":true},{"id":3,"content":"[PAD]","single_word":false,"lstrip":false,"rstrip":false,"normalized":false,"special":true},{"id":4,"content":"[MASK]","single_word":false,"lstrip":false,"rstrip":false,"normalized":false,"special":true}],"normalizer":null,
# "pre_tokenizer":{"type":"Whitespace"},
# "post_processor":null,"decoder":null,
# "model":{"type":"BPE","dropout":null,"unk_token":"[UNK]","continuing_subword_prefix":null,"end_of_word_suffix":null,"fuse_unk":false,
# "vocab":{"[UNK]":0,"[CLS]":1,"[SEP]":2,"[PAD]":3,"[MASK]":4,".":5,"B":6,"E":7,"P":8,"T":9,"a":10,"b":11,"c":12,"d":13,"e":14,"f":15,"g":16,"h":17,"i":18,"k":19,"l":20,"m":21,"n":22,"o":23,"p":24,"q":25,"r":26,"s":27,"t":28,"u":29,"w":30,"x":31,"y":32,"z":33,"or":34,"at":35,"en":36,"BP":37,"io":38,"is":39,"iz":40,"ken":41,"oken":42,"token":43,"wor":44,"atio":45,"BPE":46,"izatio":47,"tokenizatio":48,"tokenization":49,"an":50,"er":51,"ks":52,"of":53,"re":54,"th":55,"works":56,"Th":57,"ac":58,"ai":59,"al":60,"am":61,"ar":62,"by":63,"bwor":64,"ch":65,"dl":66,"ex":67,"eat":68,"edl":69,"for":70,"fre":71,"gi":72,"gor":73,"ho":74,"ith":75,"le":76,"mo":77,"mer":78,"ng":79,"pai":80,"peat":81,"ple":82,"qu":83,"st":84,"su":85,"ter":86,"ent":87,"repeat":88,"the":89,"This":90,"acter":91,"algor":92,"ample":93,"aracter":94,"bword":95,"character":96,"example":97,"edly":98,"frequ":99,"ging":100,"how":101,"ithm":102,"most":103,"merging":104,"pair":105,"subword":106,"repeatedly":107,"algorithm":108,"characters":109,"frequent":110},
# "merges":["o r","a t","e n","B P","i o","i s","i z","k en","o ken","t oken","w or","at io","BP E","iz atio","token izatio","tokenizatio n","a n","e r","k s","o f","r e","t h","wor ks","T h","a c","a i","a l","a m","a r","b y","b wor","c h","d l","e x","e at","e dl","f or","f re","g i","g or","h o","i th","l e","m o","m er","n g","p ai","p eat","p le","q u","s t","s u","t er","en t","re peat","th e","Th is","ac ter","al gor","am ple","ar acter","bwor d","ch aracter","ex ample","edl y","fre qu","gi ng","ho w","ith m","mo st","mer ging","pai r","su bword","repeat edly","algor ithm","character s","frequ ent"]}}

 

 

- 토크나이저를 저장하기 로딩하기: tokenizer.save(), tokenizer.from_file()

 

## Saving and Loading tokenizer

# Save it to a file
tokenizer.save("./tokenizer.json")


import os

print("Current working directory:", os.getcwd())
print("File list at current directory:", os.listdir(os.getcwd()))

# Current working directory: C:\Users\Documents\BPE-Tokenizer
# File list at current directory: ['BPE-subword-tokenization.ipynb', 'tokenizer.json']



# Load the saved Tokenizer JSON file back
tokenizer = tokenizer.from_file("./tokenizer.json")

print("Vocabulary size:", tokenizer.get_vocab_size())

# Vocabulary size: 111

 

 

 

- Hugging Face Hub에서 AutoTokenizer 메소드를 사용해 이미 훈련이 된 모델의 tokenizer 사용하기 

 

# Using Pre-trained tokenization from the Hugging Face Hub
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

# Accessing tokenizer attributes
vocab_size = tokenizer.vocab_size
print("Vocabulary size:", vocab_size)

# Vocabulary size: 30522


# Special tokens
print("PAD token:", tokenizer.pad_token)
print("PAD token ID:", tokenizer.pad_token_id)

# PAD token: [PAD]
# PAD token ID: 0

 

 

[ Reference ]

1. "Tokenizers: How Machines Read" by Cathal Horan: https://blog.floydhub.com/tokenization-nlp/

2. "Summary of the tokenizers" from Hugging Face: 
https://huggingface.co/docs/transformers/tokenizer_summary

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

 

728x90
반응형