前回の記事の続きで、 Keras の Tokenizer の話です。
Tokenizerのインスタンスを作成する時、前回紹介した引数の filters / lower/ split /char_level のほか、
num_wordsと、oov_token という二つの引数を設定することができます。
これが少し癖があるので確認しておきましょう。
まず、num_wordsですが、こちらは学習する単語の種類数を指定するものです。
ここで注意しないといけないのは、インデックス0がどの単語にも割り当てられないインデックスとして予約されてしまっているので、
Tokenizerが学習してくれる単語は、num_wordsで指定したのよりも一つ少なくなります。
(普通は数千とかの値を渡すのですが動きを確認しやすくするために、)試しにnum_words=7 を渡してみましょう。
なお、前回の記事同様に、 変数 text_data に、テキストデータが入ってるものとします。
# num_words で、学習する語彙数を指定できる。
keras_tokenizer_7 = Tokenizer(
num_words=7
)
# 文字列から学習する
keras_tokenizer_7.fit_on_texts(text_data)
# 学習した単語とそのindex
print(keras_tokenizer_7.word_index)
# {'the': 1, 'of': 2, 'to': 3, 'and': 4, 'a': 5, 'in': 6, 'is': 7, 'i': 8, 'that': 9, 'it': 10, 'for': 11, 'this': 12,...
まず、戸惑うところは、word_indexには大量の単語が含まれている点です。でも、実際にトークン化できる単語は頻度が高い7-1=6個だけになります。
試しに高頻度の単語を並べたテキストをトークン化してみましょう。
print(keras_tokenizer_7.texts_to_sequences(["the of to and a in is i that it for"]))
# [[1, 2, 3, 4, 5, 6]]
ちょっとわかりにくいですが、 the から in までの 6単語が変換され、 is 以降は無視されました。
次に、 oov_token です。 これは元々のテキストに含まれていなかったり、num_wordsで指定した上限値によって溢れてしまった単語を、
oov_token で渡した文字列に変換するものです。
それだけなら単純ですが、注意しないといけないのは、oov_tokenがインデックス1を使ってしまうので、
oov_tokenに何か値を指定すると、学習してくれる単語が一つ減ります。
num_words を先ほどと同じように7にしておくと、 the, of, to, and, a, の5単語しか変換しないことがわかります。
keras_tokenizer_oov = Tokenizer(
num_words=7,
oov_token="未知語"
)
# 文字列から学習する
keras_tokenizer_oov.fit_on_texts(text_data)
# 学習した単語とそのindex
print(keras_tokenizer_oov.word_index)
# {'未知語': 1, 'the': 2, 'of': 3, 'to': 4, 'and': 5, 'a': 6, 'in': 7, 'is': 8, 'i': 9, 'that': 10, 'it': 11,...
print(keras_tokenizer_oov.texts_to_sequences(["the of to and a in is i that it for"]))
# [[2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1]]
oov_token を使うと、元の単語列と、変換後の数列の要素数が維持されますし、
未学習だった単語がどれだけ含まれているのかもわかるのでとても便利ですが、
使える単語が一個減ることなどは注意しないといけませんね。
ちなみに、 oov_token に、 学習対象のドキュメントにある単語を使うと、その単語のインデックスがoov_tokenとして使われ、
1が使われなくなります。
ちょっとややこしいのでできるだけ避けましょう。