#背景
最近、kaggleを始めました。
Tweetから文字列を抽出するコンテストなんですが、数打ちゃ当たるでは?と思い、色んな手法で単語を特徴量変換してみました。
その時に、便利だったToknizerをご紹介します。
※Pythonのライブラリです。
#Tokenizerとは?
機械学習で言葉を学習させるためには、その言葉を数値化(ベクトル化)する必要があります。その変換器のことを、Tokenizerと言います。おそらく。
例えば、
This -> Tokenizer ->713
のように、数値化します。
#transformers
今回使うライブラリは「Hugging Face, Inc」が開発している「transformers」というライブラリを使います。
自然言語処理だとお馴染みのライブラリ(少なくともkaggleではよく使われてた)で、tokenizerだけでなく、最新の手法によるmodelも実装されています。
#さっそく使ってみましょう
今回は「RoBERTa」を例として使ってみます。
ソースはここにあります。
このソースはipynb形式なので、Google Colabか、Visual Studio Codeで実行できます。
Google Colab
Visual Studio Code
または、コードをそれぞれ取り出して、コンソールやpyに移植して試してみてください。
##tokenizerを取得
transformers.AutoTokenizer.from_pretrained(モデル名)でtokenizerを取得します。「モデル名」を変えることで、そのモデルのtokenizerを取得でます。今回はRoBERTaを使うので、「roberta-base」を入力。他のモデルはここにあります。
生成されるまで時間がかかるので、少々お待ちを。
import transformers
tokenizer = transformers.AutoTokenizer.from_pretrained("roberta-base")
##適当な文を作成
今回は下記の文を用意。
text = "This is a pen."
text2 = "I am a man"
##ベクトル化
作成した文をそれぞれベクトル化します。それには、encode(テキスト)を使います。
ids = tokenizer.encode(text)
# output
# [713, 16, 10, 7670, 4]
ids2 = tokenizer.encode(text2)
# output
# [100, 524, 10, 313]
これでやりたかった言葉の数値ができましたね。
一文目をみてみると、
this -> 713
is -> 16
a -> 10
pen -> 7670
. -> 4
に変換されました!!!
##Special Token
###Special Tokenとは?
さらに、BERTやRoBERTaといた手法では、特別な文字を使って学習をしています。文の先頭や文と文の切れ目を表す文字などです。
詳しくはここをチェックして見てください。
例えば、RoBERTaではどういう文字が使われているかみてましょう。
special_tokens_mapという変数に詰められています。
tokenizer.special_tokens_map
# output
# {'bos_token': '<s>',
# 'eos_token': '</s>',
# 'unk_token': '<unk>',
# 'sep_token': '</s>',
# 'pad_token': '<pad>',
# 'cls_token': '<s>',
# 'mask_token': '<mask>'}
「トークンの意味: トークンに割り当てられて文字」
というような出力となっています。
例えば、一つ目のbos_tokenには<s>という文字が割り当てられています。
また、それぞれの意味としては、
bos_token: 文の先頭(Begin of sequence token)
eos_token: 文のおしり(End of Sequence token)
unk_token: IDに変換できない文字(Unknown token)
sep_token: 文と文を区切り目(The separator token)
pad_token: パッディング(The token used for padding)
cls_token: 分類用(cls_token)
mask_token: マスク(The token used for masking values)
です。詳しい説明は先ほど挙げたURLで確認してみてください。
###Special TokenのIDチェック
all_special_tokensはSpecial Tokenに割り当てられた文字リスト、all_special_idsには先程のSpecial Tokenに対応するIDが詰められています。all_special_tokensと同じ順で並んでいます。
先程7つのSpecial Tokenがあげられましたが、割り当てられた文字が重複しているものもあるので、all_special_tokensは5つの文字リストになっています。
tokenizer.all_special_tokens
# output
# ['<pad>', '<s>', '<mask>', '<unk>', '</s>']
tokenizer.all_special_ids
# output
# [1, 0, 50264, 3, 2]
##Special Tokenを追加
RoBERTaやBERTではModelで学習、推論する時にSpecial Tokenを追加する必要があります。(今回はパディングはしていません。)
先ほど調べたSpecial Tokenを手動でくっつけてもよいですが、自動で入力した文にSpecial Tokenを追加してくれるAPIが用意されているので、それを使ってみます。
ids_with_special_token = tokenizer.build_inputs_with_special_tokens(ids, ids2)
# output(ids_with_special_token)
# [0, 713, 16, 10, 7670, 4, 2, 2, 100, 524, 10, 313, 2]
mask = tokenizer.get_special_tokens_mask(ids, ids2)
# output(mask)
# [1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1]
Special Tokenの追加には、
tokenizer.build_inputs_with_special_tokens(テキストID、テキスト2ID)
を使います。2つ文を入れるいれることができ(1つでもOK)、ちゃんと2文の頭、区切り目、おしりにSpecial Tokenが挿入されていますね。
今後は、実際にModelで処理させてみます。