Hugging Faceのライブラリを使ってTokenize

#背景
最近、kaggleを始めました。
Tweetから文字列を抽出するコンテストなんですが、数打ちゃ当たるでは？と思い、色んな手法で単語を特徴量変換してみました。
その時に、便利だったToknizerをご紹介します。
※Pythonのライブラリです。

#Tokenizerとは？
機械学習で言葉を学習させるためには、その言葉を数値化（ベクトル化）する必要があります。その変換器のことを、Tokenizerと言います。おそらく。
例えば、
　This -> Tokenizer ->713
のように、数値化します。

#transformers
今回使うライブラリは「Hugging Face, Inc」が開発している「transformers」というライブラリを使います。
自然言語処理だとお馴染みのライブラリ（少なくともkaggleではよく使われてた）で、tokenizerだけでなく、最新の手法によるmodelも実装されています。

#さっそく使ってみましょう
今回は「RoBERTa」を例として使ってみます。
ソースは[ここ](https://github.com/ishikawa-takumi/transformers-sample/blob/master/tokenizer.ipynb)にあります。
このソースはipynb形式なので、Google Colabか、Visual Studio Codeで実行できます。
[Google Colab](https://colab.research.google.com)
[Visual Studio Code](https://dev.classmethod.jp/articles/visual-studio-code-jupyter-notebook/)
または、コードをそれぞれ取り出して、コンソールやpyに移植して試してみてください。

##tokenizerを取得
transformers.AutoTokenizer.from_pretrained(モデル名)でtokenizerを取得します。「モデル名」を変えることで、そのモデルのtokenizerを取得でます。今回はRoBERTaを使うので、「roberta-base」を入力。他のモデルは[ここ](https://huggingface.co/models)にあります。
生成されるまで時間がかかるので、少々お待ちを。

```python
import transformers

tokenizer = transformers.AutoTokenizer.from_pretrained("roberta-base")
```
##適当な文を作成
今回は下記の文を用意。

```python
text = "This is a pen."
text2 = "I am a man"
```
##ベクトル化
作成した文をそれぞれベクトル化します。それには、encode(テキスト)を使います。

```python
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といた手法では、特別な文字を使って学習をしています。文の先頭や文と文の切れ目を表す文字などです。
詳しくは[ここ](https://qiita.com/omiita/items/72998858efc19a368e50)をチェックして見てください。
例えば、RoBERTaではどういう文字が使われているかみてましょう。
special_tokens_mapという変数に詰められています。

```python
tokenizer.special_tokens_map
# output
# {'bos_token': '
',
#  'eos_token': '
',
#  'unk_token': '<unk>',
#  'sep_token': '
',
#  'pad_token': '<pad>',
#  'cls_token': '
',
#  'mask_token': '<mask>'}
```
「トークンの意味: トークンに割り当てられて文字」
というような出力となっています。
例えば、一つ目のbos_tokenには\
という文字が割り当てられています。
また、それぞれの意味としては、
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つの文字リストになっています。

```python
tokenizer.all_special_tokens
# output
# ['<pad>', '
', '<mask>', '<unk>', '
']
tokenizer.all_special_ids
# output
# [1, 0, 50264, 3, 2]
```

##Special Tokenを追加
RoBERTaやBERTではModelで学習、推論する時にSpecial Tokenを追加する必要があります。（今回はパディングはしていません。）
先ほど調べたSpecial Tokenを手動でくっつけてもよいですが、自動で入力した文にSpecial Tokenを追加してくれるAPIが用意されているので、それを使ってみます。

```python
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、テキスト２ID)
を使います。2つ文を入れるいれることができ（1つでもOK）、ちゃんと２文の頭、区切り目、おしりにSpecial Tokenが挿入されていますね。


今後は、実際にModelで処理させてみます。