Skip to content

Instantly share code, notes, and snippets.

@lovit
Last active January 8, 2024 20:43
Show Gist options
  • Save lovit/259bc1d236d78a77f044d638d0df300c to your computer and use it in GitHub Desktop.
Save lovit/259bc1d236d78a77f044d638d0df300c to your computer and use it in GitHub Desktop.
huggingface + KoNLPy

Huggingface

  • NLP 관련 다양한 패키지를 제공하고 있으며, 특히 언어 모델 (language models) 을 학습하기 위하여 세 가지 패키지가 유용
package note
transformers Transformer 기반 (masked) language models 알고리즘, 기학습된 모델을 제공
tokenizers transformers 에서 사용할 수 있는 토크나이저들을 학습/사용할 수 있는 기능 제공. transformers 와 분리된 패키지로 제공
nlp 데이터셋 및 평가 척도 (evaluation metrics) 을 제공

Huggingface tokenizers

dictionary-based vs subword tokenizers

토크나이저 토큰 단위 미등록단어 가정 vocab size
사전 기반 알려진 단어/형태소 사전에 등록된 단어/형태소의 결합이라 가정, 필요시 형태소 분석 (형태 변형 가능) unlimited
subword 알려진 subwords (substring) subwords 의 조합이라 가정, str split 만을 이용 limited

(코로나 뉴스 70,963 문장 + BertTokenizer)

sent = '신종 코로나바이러스 감염증(코로나19) 사태가 심각합니다'
bert_tokenizer.tokenize(sent)
# '신종 코로나바이러스 감염증 ( 코로나19 ) 사태 ##가 심 ##각 ##합니다'

komoran.morphs(sent)
# 신종 코로나바이러스 감염증 ( 코로나 19 ) 사태 가 심각 하 ㅂ니다
input eojeol Mecab Komoran Bert + Covid news
코로나가 코 로 나가 코로나 가 코로나 ##가
코로나는 코로나 는 코로나 는 코로나 ##는
코로나를 코로나 를 코로나 를 코로나 ##를
코로나의 코로 나의 코로나 의 코로나 ##의
  • 사전 기반 토크나이저는 미등록단어를 맥락에 따라 잘못 분해할 가능성이 존재
  • subword 토크나이저는 학습데이터에 자주 등장하는 substring 이라면 단어로 보존될 가능성이 높음
input eojeol Mecab Komoran Bert + Covid news
심각합니다 심각 합니다 심각 하 ᄇ니다 심 ##각 ##합니다
심각했다 심각 했 다 심각 하 었 다 심 ##각 ##했다
심각하다고 심각 하 다고 심각 하 다고 심 ##각 ##하다 ##고
심각하며 심각 하 며 심각 하 며 심 ##각 ##하며
  • 반대로 학습데이터에 자주 등장하지 않은 단어 심각 은 잘 인식되지 않음
    • 반드시 단어로 보존하고 싶은 단어가 있다면 따로 등록이 필요
  • 활용된 용언 하다가 다양한 형태로 표현
    • 합니다, 했다, 하다 + 고, 하며
    • 반드시 원형으로 처리해야 하는 것은 아니나, 이를 원할 경우 선택할 수 없음

tokenizers 구성

  • 0.9.0.dev0 버그가 있어서 0.8.1 기준으로 진
  • BaseTokenizer 를 상속하는 네 가지 토크나이저를 제공
  • Rust 로 구현된 코드를 Python 에서 이용할 수 있도록 도와주는 기능을 제공
    • Python 에서 기능을 추가하기 어려움
  • base 방식에 따라 WordpieceTrainer, BpeTrainer 를 이용
tokenizer (class name) unit base normalizer boundary symbol output
Byte-level BPE (ByteLevelBPETokenizer) byte BPE [Unicode, Lowercase] 어절 앞 Ġ 부착 vocab.json, merges.txt
Character-level BPE (CharBPETokenizer)^1 char BPE [Unicode, BertNormalizer, Lowercase] 어절 뒤 </w> 부착 vocab.json, merges.txt
Sentencepiece BPE (SentencePieceBPETokenizer)^2 char BPE 어절 앞 부착 vocab.json, merges.txt
Bert wordpiece (BertWordPieceTokenizer) char WordPiece BertNormalizer 어절 중간 subword 앞에 ## 부착 vocab.txt
  • ^1: split_on_whitespace_only 기능 제공. 이를 이용하면 pre-tokenized 된 텍스트를 이용하여 학습하기에 용이
  • ^2: add_prefix_space 기능 제공

tokenizers.BaseTokenizer

  • 네 가지 토크나이저가 모두 상속, 대표적인 기능
    • get_vocab()
    • add_tokens()
    • add_special_tokens()
    • normalize()
    • encode() / encode_batch()
    • decode() / decode_batch()
    • save() vs save_model()
  • tokenize() 기능이 없고, encode() 의 결과를 이용해야 함
  • 네 가지 토크나이저들 모두 위의 기능을 상속하니, 각 토크나이저의 특징을 살펴보며 위의 기능들을 알아보자

tokenizers.BertWordPieceTokenizer

(very_small_corpus.txt)

ABCDE ABC AC ABD
DE AB ABC AF

(training)

bert_wordpiece_tokenizer = BertWordPieceTokenizer()
bert_wordpiece_tokenizer.train(
    files = [small_corpus],
    vocab_size = 10,
    min_frequency = 1,
    limit_alphabet = 1000,
    initial_alphabet = [],
    special_tokens = ["[PAD]", "[UNK]", "[CLS]", "[SEP]", "[MASK]"],
    show_progress = True,
    wordpieces_prefix = "##",
)

(vocab check)

vocab = bert_wordpiece_tokenizer.get_vocab()
sorted(vocab, key=lambda x: vocab[x])
['[PAD]', '[UNK]', '[CLS]', '[SEP]', '[MASK]', 'a', 'b', 'c', 'd', 'e',
 'f', '##b', '##c', '##d', '##e', '##f']

(tokenization)

encoding = bert_wordpiece_tokenizer.encode('ABCDE')
print(encoding.tokens)  # ['a', '##b', '##c', '##d', '##e']
print(encoding.ids)     # [5, 13, 12, 14, 11]

(vocab size 를 늘리고 initial alphabet 을 추가하면)

bert_wordpiece_tokenizer.train(
    files = [small_corpus],
    vocab_size = 20,
    min_frequency = 1,
    initial_alphabet = ['g'],
)
vocab = bert_wordpiece_tokenizer.get_vocab()
sorted(vocab, key=lambda x: vocab[x])
# ['[PAD]', '[UNK]', '[CLS]', '[SEP]', '[MASK]', 'a', 'b', 'c', 'd', 'e',
#  'f', 'g', '##b', '##c', '##e', '##d', '##f', 'ab', 'abc', 'ac']

(encode_batch 함수)

encodings = bert_wordpiece_tokenizer.encode_batch(['ABCDE', 'abcd'])
encodings[0].tokens  # ['abc', '##d', '##e']

(normalize 함수)

# 0.9.0dev 에서 사라
bert_wordpiece_tokenizer.normalize('ABCDE')  # 'abcde'

(save / load)

bert_wordpiece_tokenizer.save_model(
    directory = './',
    name = 'very_small_bertwordpiece'
)

# './very_small_bertwordpiece-vocab.txt' 에 vocab 생성

bert_wordpiece_tokenizer = BertWordPieceTokenizer(
    vocab_file = './very_small_bertwordpiece-vocab.txt'
)
bert_wordpiece_tokenizer.encode('ABCDE').tokens
# ['[CLS]', 'abc', '##d', '##e', '[SEP]']

(without special tokens)

bert_wordpiece_tokenizer.encode(
    'ABCDE',
     add_special_tokens=False
).tokens
# ['abc', '##d', '##e']

(two sentences pair)

bert_wordpiece_tokenizer.encode(
    sequence = 'abcde',
    pair = 'abcd'
).tokens
# ['[CLS]', 'abc', '##d', '##e', '[SEP]', 'abc', '##d', '[SEP]']

(add_tokens 함수)

bert_wordpiece_tokenizer.add_tokens(['lovit'])
vocab = bert_wordpiece_tokenizer.get_vocab()
sorted(vocab, key=lambda x: vocab[x])
# ['[PAD]', '[UNK]', '[CLS]', '[SEP]', '[MASK]', 'a', 'b', 'c', 'd', 'e',
#  'f', 'g', '##b', '##c', '##e', '##d', '##f', 'ab', 'abc', 'ac',
#  'lovit']

# 그러나 추가한 단어가 함께 저장되지는 않음. `vocab.txt` 에 직접 추가해도 
bert_wordpiece_tokenizer.save('./', './very_small_bertwordpiece')

tokenizers.SentencePieceBPETokenizer

(train)

sentencepiece_tokenizer = SentencePieceBPETokenizer(
    add_prefix_space = True,
    replacement = '▁'
)
sentencepiece_tokenizer.train(
    files = [small_corpus],
    vocab_size = 20,
    min_frequency = 1,
    special_tokens = ['<unk>'],
)
vocab = sentencepiece_tokenizer.get_vocab()
sorted(vocab, key=lambda x: vocab[x])
# ['<unk>', 'A', 'B', 'C', 'D', 'E', 'F', '▁', '▁A', '▁AB',
#  '▁ABC', 'DE', '▁DE', '▁AC', '▁AF', '▁ABD', '▁ABCDE']
  • 0.8.1 -> 0.9.0dev 에서 '\n' 이 글자로 들어옴

(without add_prefix_space)

sentencepiece_tokenizer = SentencePieceBPETokenizer(
    add_prefix_space = False
)
sentencepiece_tokenizer.train(
    files = [small_corpus],
    vocab_size = 20,
    min_frequency = 1,
    special_tokens = ['<unk>'],
)
vocab = sentencepiece_tokenizer.get_vocab()
sorted(vocab, key=lambda x: vocab[x])
# ['<unk>', 'A', 'B', 'C', 'D', 'E', 'F', '▁', '▁A', '▁AB',
#  'DE', '▁ABC', 'AB', 'CDE', '▁AC', '▁AF', '▁ABD', 'ABCDE']
  • add_prefix_space=True 는 문장의 첫글자가 공백이 아닐 경우 공백 추
  • 위에서는 ▁ABCDE 가, 아래에서는 ABCDE 가 unit 으로 학습됨.

(save / load)

sentencepiece_tokenizer.save_model('./', 'very_small_sentencepiece')
# ['./very_small_sentencepiece-vocab.json',
#  './very_small_sentencepiece-merges.txt']

sentencepiece_tokenizer = SentencePieceBPETokenizer(
    vocab_file = './very_small_sentencepiece-vocab.json',
    merges_file = './very_small_sentencepiece-merges.txt'
)
sentencepiece_tokenizer.encode('ABCDE').tokens
# ['▁ABC', 'DE']
  • BPE 계열은 merges.txt, vocab.json 두 개의 파일
  • 0.9.0devmerges.txt 파일 저장 과정 중 버그가 있음

tokenizers.CharBPETokenizer

(use BertPreTokenizer)

charbpe_tokenizer = CharBPETokenizer(suffix='</w>')
charbpe_tokenizer.train(
    files = [small_corpus],
    vocab_size = 15,
    min_frequency = 1
)
charbpe_tokenizer.encode('ABCDE.ABC').tokens
# ['AB', 'C', 'DE</w>', 'ABC</w>']
  • BertPreTokenizer 는 space, punctuation 에서 분리

(use WhitespacePreTokenizer)

charbpe_tokenizer = CharBPETokenizer(
    suffix='</w>',
    split_on_whitespace_only = True
)
charbpe_tokenizer.encode('ABCDE.ABC').tokens
# ['AB', 'C', 'D', 'E', 'ABC</w>']
  • 공백 기준으로만 어절을 분리

(미등록단어 제거하여 return)

charbpe_tokenizer.encode('ABCDEFGH').tokens
# ['AB', 'C', 'D', 'E', 'F']

tokenizers.ByteLevelBPETokenizer

# OpenAI GPT2 tokenizer
bytebpe_tokenizer = ByteLevelBPETokenizer(
    add_prefix_space = False,
    lowercase = False,
)
bytebpe_tokenizer.train(
    files = [small_corpus],
    vocab_size = 1000,
    min_frequency = 1
)
vocab = bytebpe_tokenizer.get_vocab()
sorted(vocab, key=lambda x: vocab[x])
['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4',
 '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\',
 ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '¡', '¢', '£', '¤', '¥', '¦',
 '§', '¨', '©', 'ª', '«', '¬', '®', '¯', '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»',
 '¼', '½', '¾', '¿', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã',
 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷',
 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ',
 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ',
 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij',
 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'ĸ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń',
 'ĠA', 'ĠAB', 'DE', 'ĠABC', 'AB', 'CDE', 'ĠAC', 'ĠAF', 'ĠABD', 'ABCDE']
  • 33 - 323 까지 글자를 기본 알파벳으로 가지고 시작
bytebpe_tokenizer.encode('ABCDE ABC').tokens
# ['ABCDE', 'ĠABC']

bytebpe_tokenizer.encode(' ABCDE ABC').tokens
# ['ĠABC', 'DE', 'ĠABC']

tokenizers 에서 학습한 토크나이저를 transformers 에서 이용하기

BertTokenizer 를 확인해보자.

from transformers import BertTokenizer, GPT2Tokenizer

transformers_bert_tokenizer = BertTokenizer(
    vocab_file = './tokenizers/BertWordPieceTokenizer/covid-vocab.txt'
)
sent_ko = '신종 코로나바이러스 감염증(코로나19) 사태가 심각합니다'
print(f'tokenizers  : {bert_wordpiece_tokenizer.encode(sent_ko).tokens}')
print(f'transformers: {transformers_bert_tokenizer.tokenize(sent_ko)}')
tokenizers  : ['신종', '코로나바이러스', '감염증', '(', '코로나19', ')', '사태', '##가', '심', '##각', '##합니다']
transformers: ['신종', '코로나바이러스', '감염증', '(', '코로나19', ')', '사태', '##가', '심', '##각', '##합니다']
  • 토크나이징의 결과가 동일하지만, 초/중/종성이 분해되어 있다.
  • 이는 unicode normalization 때문에 발생한 현상.
from unicodedata import normalize

print(normalize('NFKD', '가감'))       # 가감 ; 출력 시 글자를 재조합해서 보여줌
print(len(normalize('NFKD', '가감')))  # 5
print(normalize('NFKC', normalize('NFKD', '가감')))      # 가감
print(len(normalize('NFKC', normalize('NFKD', '가감')))) # 2
def compose(tokens):
    return [normalize('NFKC', token) for token in tokens]

print(f'tokenizers  : {compose(bert_wordpiece_tokenizer.encode(sent_ko).tokens)}')
print(f'transformers: {compose(transformers_bert_tokenizer.tokenize(sent_ko))}')
tokenizers  : ['신종', '코로나바이러스', '감염증', '(', '코로나19', ')', '사태', '##가', '심', '##각', '##합니다']
transformers: ['신종', '코로나바이러스', '감염증', '(', '코로나19', ')', '사태', '##가', '심', '##각', '##합니다']

GPT2Tokenizer 를 확인해보자.

transformers_gpt2_tokenizer = GPT2Tokenizer(
    vocab_file = './tokenizers/ByteLevelBPETokenizer/covid-vocab.json',
    merges_file = './tokenizers/ByteLevelBPETokenizer/covid-merges.txt'
)
print(f'tokenizers  : {byte_level_bpe_tokenizer.encode(sent_ko).tokens}')
print(f'transformers: {transformers_gpt2_tokenizer.tokenize(sent_ko)}')
tokenizers  : ['ìĭłì¢ħ', 'Ġì½Ķë¡ľëĤĺë°ĶìĿ´ëŁ¬ìĬ¤', 'Ġê°IJìĹ¼ì¦Ŀ', '(', 'ì½Ķë¡ľëĤĺ', '19', ')', 'ĠìĤ¬íĥľ', 'ê°Ģ', 'Ġìĭ¬', 'ê°ģ', 'íķ©ëĭĪëĭ¤']
transformers: ['ìĭłì¢ħ', 'Ġì½Ķë¡ľëĤĺë°ĶìĿ´ëŁ¬ìĬ¤', 'Ġê°IJìĹ¼ì¦Ŀ', '(', 'ì½Ķë¡ľëĤĺ', '19', ')', 'ĠìĤ¬íĥľ', 'ê°Ģ', 'Ġìĭ¬', 'ê°ģ', 'íķ©ëĭĪëĭ¤']

Customizing tokenizers

compose(transformers_bert_tokenizer.tokenize('lovit 이란 이름은 인식을 안합니다'))
# ['l', '##o', '##v', '##i', '##t', '이라', '##ᆫ', '이', '##름', '##은', '인', '##식을', '안', '##합니다']
  • 데이터에 충분히 등장하지 않았더라도 특정 단어를 보존하고 싶다.
  • 기형태소 분석기와 혼합하여 BertTokenizer 를 이용하고 싶다.

KoNLPy 형태소 분석기를 preprocessor 로 이용하기 tokenizers 학습하기

방법 1. Normalizer 나 PreTokenizer 로 만들기 (실패)

  • Normalizer 와 PreTokenizer 는 Rust 코드를 Python 에서 이용할 수 있도록 도와주는 클래스로 상속이 되지 않음
from tokenizers.normalizers import Normalizer
class KomoranNormalizer(Normalizer):
    def __init__(self):
        print('success')
"type 'tokenizers.normalizers.Normalizer' is not an acceptable base type"
from tokenizers.pre_tokenizers import PreTokenizer
class KomoranPreTokenizer(PreTokenizer):
    def __init__(self):
        print('success')
"type 'tokenizers.pre_tokenizers.PreTokenizer' is not an acceptable base type"

방법 2. 학습데이터를 KoNLPy 로 미리 분해하여 tokenizers 학습

from konlpy.tag import Komoran, Mecab, Okt

class KoNLPyPreTokenizer:
    def __init__(self, base_tokenizer):
        self.base_tokenizer = base_tokenizer
    def __call__(self, sentence):
        return self.pre_tokenize(sentence)
    def pre_tokenize(self, sentence):
        return ' '.join(self.base_tokenizer.morphs(sentence))

konlpy_pretok = KoNLPyPreTokenizer(Komoran())
print(konlpy_pretok(sent_ko))
# 신종 코로나바이러스 감염증 ( 코로나 19 ) 사태 가 심각 하 ㅂ니다
def prepare_pretokenized_corpus(raw_path, pretokenized_path, pretok):
    with open(raw_path, encoding='utf-8') as f:
        lines = [line.strip() for line in f]
    with open(pretokenized_path, 'w', encoding='utf-8') as f:
        for line in lines:
            f.write(f'{pretok(line)}\n')

prepare_pretokenized_corpus(
    '../data/2020-07-29_covid_news_sents.txt',
    '../data/2020-07-29_covid_news_sents.komoran.txt',
    KoNLPyPreTokenizer(Komoran()))

bert_wordpiece_tokenizer = BertWordPieceTokenizer()
bert_wordpiece_tokenizer.train(
    files = ['../data/2020-07-29_covid_news_sents.komoran.txt'],
    vocab_size = 3000)
bert_wordpiece_tokenizer.save_model(
    directory='./tokenizers/KomoranBertWordPieceTokenizer/',
    name='covid')
for vocab, idx in bert_wordpiece_tokenizer.get_vocab().items():
    if normalize('NFKD', '니다') in vocab:
        print(vocab, idx)
ㅂ니다 1106
습니다 977
##니다 909

custom 기능은 제공되지 않는가?

  • 올해 4월 examples 에 custom_pre_tokenizer 가 업로드 됨. 링크
  • 하지만 정상적으로 작동하지 않음을 확인.
  • 계속 버전업 중이니 이 기능을 제공해줄 것으로 기대 중
from tokenizers import pre_tokenizers

class GoodCustom:
    def pre_tokenize(self, sentence):
        return sentence.split(" ")

    def decode(self, tokens):
        return ", ".join(tokens)

good_custom = GoodCustom()
good_pretok = pre_tokenizers.PreTokenizer.custom(good_custom)

tokenizers 와 transformers.PretrainedTokenizer 에 KoNLPy 형태소 분석기를 preprocessor 넣기

  • 학습이 끝났다면 tokenizers.BertTokenizer 의 encode, encode_batch 함수만 수정하면 된다.
class KoNLPyBertWordPieceTokenizer(BertWordPieceTokenizer):
    def __init__(
        self,
        konlpy_pretok,
        vocab_file: Optional[str] = None,
        ...):
        super().__init__(...)
        self.konlpy_pretok = konlpy_pretok

    def encode(self, sequence, pair=None, ...):
        if sequence is None:
            raise ValueError("encode: `sequence` can't be `None`")

        sequence = self.konlpy_pretok(sequence)  # <-- 추가
        return self._tokenizer.encode(sequence, pair, is_pretokenized, add_special_tokens)

    def encode_batch(self, inputs, ...):
        if inputs is None:
            raise ValueError("encode_batch: `inputs` can't be `None`")

        # <-- 추가
        input_iterator = tqdm(inputs, desc='konlpy pretok', total=len(inputs))
        konlpy_pretok_inputs = [self.konlpy_pretok(sequence) for sequence in input_iterator]
        # -->
        return self._tokenizer.encode_batch(konlpy_pretok_inputs, is_pretokenized, add_special_tokens)

konlpy_bert_wordpiece_tokenizer = KoNLPyBertWordPieceTokenizer(
    konlpy_pretok,
    vocab_file = './tokenizers/KomoranBertWordPieceTokenizer/covid-vocab.txt')
class KoNLPyBertTokenizer(BertTokenizer):
    def __init__(
        self,
        konlpy_pretok,
        vocab_file,
        ...):
        super().__init__(...)
        self.konlpy_pretok = konlpy_pretok

    def _tokenize(self, text):
        text = self.konlpy_pretok(text)  # <-- 추가
        split_tokens = []
        if self.do_basic_tokenize:
            for token in self.basic_tokenizer.tokenize(text, never_split=self.all_special_tokens):

                # If the token is part of the never_split set
                if token in self.basic_tokenizer.never_split:
                    split_tokens.append(token)
                else:
                    split_tokens += self.wordpiece_tokenizer.tokenize(token)
        else:
            split_tokens = self.wordpiece_tokenizer.tokenize(text)
        return split_tokens

konlpy_bert_tokenizer = KoNLPyBertTokenizer(
    konlpy_pretok, './tokenizers/KomoranBertWordPieceTokenizer/covid-vocab.txt')
compose(bert_wordpiece_tokenizer.encode(sent_ko).tokens)
# ['신종', '코로나바이러스', '감염증', '(', '코로나', '##1', '##9', ')', '사태', '##가', '심각', '##합', '##니다']

compose(konlpy_bert_wordpiece_tokenizer.encode(sent_ko, add_special_tokens=False).tokens)
# ['신종', '코로나바이러스', '감염증', '(', '코로나', '19', ')', '사태', '가', '심각', '하', 'ᄇ니다']

compose(konlpy_bert_tokenizer.tokenize(sent_ko))
# ['신종', '코로나바이러스', '감염증', '(', '코로나', '19', ')', '사태', '가', '심각', '하', 'ᄇ니다']
@sansanai
Copy link

sansanai commented Oct 7, 2020

질문 있습니다. BertWordPieceTokenizer.encode()의 반환되는 값의 attributes 중에 overflowing 이라는 것이 있던데., 이것은 무엇을 의미하는 건가요? 보통 값은 비워있는 리스트가 반환되는데, 용도가 무엇인지 궁금합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment