LSTMとかの深層学習モデルで自然言語を扱うとき、
語彙数が増えると計算量やGPUメモリサイズが爆発的に増えてしまうことが多い。
予め低頻度語をBPEでサブワード化することで語彙サイズを減らそうというエントリー。
サブワード化ってなんだ。
あまり出現しない単語を、文字や部分文字(サブワード)に分割しようということ。
これにより、語彙サイズが圧縮できる。
極端な話、英単語を文字に分割すれば語彙数は英語アルファベットの52種(大文字+小文字)に圧縮可能。
BPEって何だ。
BPE(Byte Pair Encoding)は元々圧縮に使われていた技術。
共通な2バイトを新しい1バイトに置き換えることで圧縮していく。
例えば、aabbaac
のaa
をA
に置き換えると、AbbAc
と圧縮できる。
この処理を語彙圧縮に適用したのが、
Neural Machine Translation of Rare Words with Subword Units。
事前にコーパスの語彙に対してBPEを適用することで、サブワードを学習する。
subword-nmtのインストール
subword-nmtを使えば、簡単にBPEを使用したサブワードの学習とサブワード化ができる。
Pythonで書かれているのでpipでインストールする。
pip install subword-nmt
データ準備と前処理
サブワードの学習にはコーパスが必要。
今回は、吾輩は猫であるを用意した。
吾輩わがはいは猫である。名前はまだ無い。
どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。
日本語からサブワードを学習する場合は、文章はあらかじめ単語単位に分割されている必要がある。
今回はMeCabを使って、分かち書きしたwakati_wagahai.txt
を用意した。
mecab -b 100000 -Owakati wagahai.txt -o wakati_wagahai.txt
吾輩 わがはい は 猫 で ある 。 名前 は まだ 無い 。
どこ で 生れ た か とんと 見当 けん とう が つか ぬ 。 何 でも 薄暗い じめじめ し た 所 で ニャーニャー 泣い て いた事 だけ は 記憶 し て いる 。 吾輩 は ここ で 始め て 人間 という もの を 見 た 。
いざサブワードの学習
以下のコマンドでwakati_wagahai.txt
からサブワードを学習する。
subword-nmt learn-bpe -s 3000 < wakati_wagahai.txt > codes.txt
-s
は共通文字置き換え回数を指定している。
小さいほどサブワードは文字単位になる。(0だと完全に文字になるはず。)
codes.txt
の中身はこんな感じ。
吾 輩</w>
ま す</w>
さ ん</w>
じ ゃ</w>
な っ</w>
こ れ</w>
と こ
で も</w>
吾 輩</w>
は、単語内に我
と輩</w>
が出現したら我輩</w>
に結合するよ。という意味。
さっきのBPEの例で行くとaa
をA
にするよ。と同意。
(</w>
は元の単語の末尾であることを表してます。 )
サブワード化する。
学習したcodes.txt
を用いて以下のコマンドでwakati_wagahai.txt
をサブワード化してみる。
subword-nmt apply-bpe -c codes.txt < wakati_wagahai.txt > subword_wagahai.txt
subword_wagahai.txt
はこんな感じ。
吾輩 わが@@ はい は 猫 で ある 。 名前 は まだ 無い 。
どこ で 生れ た か とんと 見当 けん とう が つか ぬ 。 何 でも 薄@@ 暗い じ@@ め@@ じめ し た 所 で ニャ@@ ー@@ ニャ@@ ー 泣い て いた@@ 事 だけ は 記憶 し て いる 。 吾輩 は ここ で 始め て 人間 という もの を 見 た 。
わが@@
ははい
と元々1単語であったことを示している。
低頻度語は解体できたのか
以下の簡単なPythonスクリプトで語彙数を確認してみる。
import sys
for arg in sys.argv[1:]:
print("Input : {}".format(arg))
with open(arg, "r") as f:
text = f.read()
tokens = text.split()
print("Vocab : {}".format(len(set(tokens))))
$ python3 counter.py wakati_wagahai.txt subword_wagahai.txt
Input : wakati_wagahai.txt
Vocab : 15717
Input : subword_wagahai.txt
Vocab : 7515
無事語彙数が15717
から7515
に減ったことがわかる。