パスワードを忘れた? アカウント作成
15416907 journal
人工知能

yasuokaの日記: Re: bert-large-japanese-charのトークナイザをBertTokenizerFastで置き換えるには

日記 by yasuoka

昨日の日記の読者から、tokenizers.pre_tokenizers.Split()を御教示いただいた。BertPreTokenizerの代わりに、このSplitをぶち込むことで、未知語も含めてバラバラに文字切りしてしまおう、という算段だ。昨日のmy.char.modelを、Google Colaboratoryで作り直してみよう。

!pip install transformers
from transformers import BertTokenizerFast,AutoModelForMaskedLM
from tokenizers.pre_tokenizers import Sequence,Whitespace,Split
from tokenizers import Regex
tokenizer=BertTokenizerFast.from_pretrained("cl-tohoku/bert-large-japanese-char")
model=AutoModelForMaskedLM.from_pretrained("cl-tohoku/bert-large-japanese-char")
tokenizer.backend_tokenizer.normalizer.handle_chinese_chars=True
tokenizer.backend_tokenizer.normalizer.strip_accents=False
tokenizer.backend_tokenizer.normalizer.lowercase=False
tokenizer.backend_tokenizer.pre_tokenizer=Sequence([Whitespace(),Split(Regex("."),"isolated")])
tokenizer.backend_tokenizer.decoder.prefix=""
tokenizer.backend_tokenizer.model.continuing_subword_prefix=""
tokenizer.backend_tokenizer.model.max_input_chars_per_word=200
tokenizer.save_pretrained("my.char.model")
model.config.tokenizer_class="BertTokenizerFast"
model.save_pretrained("my.char.model")

handle_chinese_charsはFalseでもいい気がするのだが、とりあえず、そのままにしておいた。新しいmy.char.modelを使ってみよう。

import torch
from transformers import AutoTokenizer,AutoModelForMaskedLM
tokenizer=AutoTokenizer.from_pretrained("my.char.model")
model=AutoModelForMaskedLM.from_pretrained("my.char.model")
for r in ["酸素ボンベを充[MASK]する。","スペー[MASK]は♠と♤がある。"]:
  s=tokenizer(r,return_offsets_mapping=True)
  print(s)
  ids=s["input_ids"]
  tokens=tokenizer.convert_ids_to_tokens(ids)
  mask=ids.index(tokenizer.mask_token_id)
  print(tokens,mask)
  inputs=torch.tensor([ids])
  with torch.no_grad():
    outputs=model(inputs)
    pred=outputs[0][0,mask].topk(5)
  for i,t in enumerate(tokenizer.convert_ids_to_tokens(pred.indices)):
    tokens[mask]=t
    print(i+1,tokens)

「酸素ボンベを充[MASK]する。」「スペー[MASK]は♠と♤がある。」を穴埋めさせてみたところ、私(安岡孝一)の手元では以下の結果になった。

{'input_ids': [2, 5343, 4159, 998, 1021, 995, 932, 1294, 4, 875, 925, 829, 3], '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], 'offset_mapping': [(0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 13), (13, 14), (14, 15), (15, 16), (0, 0)]}
['[CLS]', '酸', '素', 'ボ', 'ン', 'ベ', 'を', '充', '[MASK]', 'す', 'る', '。', '[SEP]'] 8
1 ['[CLS]', '酸', '素', 'ボ', 'ン', 'ベ', 'を', '充', '填', 'す', 'る', '。', '[SEP]']
2 ['[CLS]', '酸', '素', 'ボ', 'ン', 'ベ', 'を', '充', '電', 'す', 'る', '。', '[SEP]']
3 ['[CLS]', '酸', '素', 'ボ', 'ン', 'ベ', 'を', '充', '充', 'す', 'る', '。', '[SEP]']
4 ['[CLS]', '酸', '素', 'ボ', 'ン', 'ベ', 'を', '充', '給', 'す', 'る', '。', '[SEP]']
5 ['[CLS]', '酸', '素', 'ボ', 'ン', 'ベ', 'を', '充', '実', 'す', 'る', '。', '[SEP]']
{'input_ids': [2, 963, 996, 1026, 4, 897, 816, 890, 1, 862, 852, 925, 829, 3], 'token_type_ids': [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], 'offset_mapping': [(0, 0), (0, 1), (1, 2), (2, 3), (3, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17), (0, 0)]}
['[CLS]', 'ス', 'ペ', 'ー', '[MASK]', 'は', '♠', 'と', '[UNK]', 'が', 'あ', 'る', '。', '[SEP]'] 4
1 ['[CLS]', 'ス', 'ペ', 'ー', 'ド', 'は', '♠', 'と', '[UNK]', 'が', 'あ', 'る', '。', '[SEP]']
2 ['[CLS]', 'ス', 'ペ', 'ー', 'に', 'は', '♠', 'と', '[UNK]', 'が', 'あ', 'る', '。', '[SEP]']
3 ['[CLS]', 'ス', 'ペ', 'ー', 'ス', 'は', '♠', 'と', '[UNK]', 'が', 'あ', 'る', '。', '[SEP]']
4 ['[CLS]', 'ス', 'ペ', 'ー', 'ト', 'は', '♠', 'と', '[UNK]', 'が', 'あ', 'る', '。', '[SEP]']
5 ['[CLS]', 'ス', 'ペ', 'ー', 'プ', 'は', '♠', 'と', '[UNK]', 'が', 'あ', 'る', '。', '[SEP]']

よし、未知語「♤」に引きずられずに、うまく文字切りできているようだ。KoichiYasuoka/bert-large-japanese-char-extendedKoichiYasuoka/bert-base-japanese-char-extendedのトークナイザも、新しいBertTokenizerFastに入れ替えておいたので、こちらも試してみてほしい。

この議論は、yasuoka (21275)によって「 ログインユーザだけ」として作成されている。 ログインしてから来てね。
typodupeerror

あと、僕は馬鹿なことをするのは嫌いですよ (わざとやるとき以外は)。-- Larry Wall

読み込み中...