0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

タイ語生成モデルのトークナイザにおいて空白や改行はどう扱うべきか

Last updated at Posted at 2025-08-15

私(安岡孝一)の「camembert-thai-base」のトークナイザを使って、JonusNattapongが「Hanuman」というタイ語生成モデルを公開した。ただ、タイ語生成モデルのトークナイザとしては、ちょっとマズイことになっている。Google Colaboratoryで「Hanuman」を動かしてみよう。

!pip install transformers triton
from transformers import pipeline
nlp=pipeline("text-generation","JonusNattapong/Hanuman",trust_remote_code=True,revision="d9d931b69eae6f336cb5ee6e097990af812fe16e")
print(nlp("เมืองที่ใหญ่เป็นอันดับ 3 ของประเทศไทยคือเมืองใด",max_new_tokens=128))

「เมืองที่ใหญ่เป็นอันดับ 3 ของประเทศไทยคือเมืองใด」の続きを生成させたところ、私の手元では以下の結果が得られた。

[{'generated_text': 'เมืองที่ใหญ่เป็นอันดับ 3 ของประเทศไทยคือเมืองใดในที่าของในกับคําในที่คําการการศาสตร์การโดยในการได้าประเทศในและเป็นการคความในปีในในและความและการสและเป็นของเป็นในสปีจากพศาได้พศการคือและเป็นในการทางมีในาเป็นเป็นมีเป็นลของนคือยของของมีของการการคโดยที่จากการการในภาษาภาษาซึ่งการการที่เป็น'}]

空白も改行も全く生成されない。それもそのはず、「camembert-thai-base」のpre_tokenizerはWhitespace()であり、空白も改行も剝ぎ取られてしまって、言語モデルには渡されない。トークナイザの中身をちょっとみてみよう。

print(nlp.tokenizer.backend_tokenizer)
print(nlp.tokenizer.convert_ids_to_tokens(nlp.tokenizer.convert_tokens_to_ids([" ","\n","▁"])))

トークナイザの中身は、こんな感じ。

Tokenizer(version="1.0", truncation=None, padding=None, added_tokens=[{"id":0, "content":"<s>NOTUSED", "single_word":False, "lstrip":False, "rstrip":False, ...}, {"id":1, "content":"<pad>", "single_word":False, "lstrip":False, "rstrip":False, ...}, {"id":2, "content":"</s>NOTUSED", "single_word":False, "lstrip":False, "rstrip":False, ...}, {"id":3, "content":"<unk>", "single_word":False, "lstrip":False, "rstrip":False, ...}, {"id":5, "content":"<s>", "single_word":False, "lstrip":False, "rstrip":False, ...}, ...], normalizer=Sequence(normalizers=[Nmt(), NFKC(), Lowercase()]), pre_tokenizer=Whitespace(), post_processor=TemplateProcessing(single=[SpecialToken(id="<s>", type_id=0), Sequence(id=A, type_id=0), SpecialToken(id="</s>", type_id=0)], pair=[SpecialToken(id="<s>", type_id=0), Sequence(id=A, type_id=0), SpecialToken(id="</s>", type_id=0), SpecialToken(id="</s>", type_id=0), Sequence(id=B, type_id=0), ...], special_tokens={"</s>":SpecialToken(id="</s>", ids=[6], tokens=["</s>"]), "<s>":SpecialToken(id="<s>", ids=[5], tokens=["<s>"])}), decoder=WordPiece(prefix="", cleanup=True), model=Unigram(unk_id=3, vocab=[("<s>NOTUSED", 0), ("", 0), ("</s>NOTUSED", 0), ("<unk>", 0), ("<unk>NOTUSED", -1200), ...], byte_fallback=False))
['<unk>', '<unk>', '▁']

全体にBERT系トークナイザで、空白も改行もvocabに含まれてないので、無理に渡しても<unk>になってしまう。ただ、metaspace (U+2581)はvocabに含まれているので、pre_tokenizerをMetaspace(prepend_scheme="never")に、decoderをMetaspace()に置き換える手はアリだと思う。でも、その方法でも、改行は空白に化けてしまうので、やはり、もう少しタイ語生成モデル向けにトークナイザを改造した上で、モデルを再トレーニングした方がいいと思う。

from tokenizers import pre_tokenizers,decoders
nlp.tokenizer.backend_tokenizer.pre_tokenizer=pre_tokenizers.Metaspace(prepend_scheme="never")
nlp.tokenizer.backend_tokenizer.decoder=decoders.Metaspace()
nlp.tokenizer.save_pretrained("modified_tokenizer")
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?