Python

Kerasによる文章のベクトル化

投稿者 : OSCA

 本稿では、機械学習ライブラリ Keras に含まれる Tokenizer クラスを利用し、文章(テキスト)をベクトル化する方法について解説します。 ベルトルの表現として「バイナリ表現」「カウント表現」「IF-IDF表現」のそれぞれについても解説します。

本稿で実現したいことは何か?

 本稿で述べる「ベクトル化」とは、与えられた文章の"特徴"を、コンピュータで扱い易いように数値として抽出する事です。(特徴抽出) "特徴"とは、例えば「文章中に特定の単語が出現するか?」「文章中の単語の出現率」などのことで、それを数値として表します。

 下記でじっくり述べますが、"I am a student." のような文章から、 [0. 1. 1. 1. 1. 0. 0. 0. 0. 0.] のようなベクトルを生成するような処理を本稿では解説します。

前提

 本稿を読み進めるにあたり、本稿で利用する例文を定義します。 本稿では、シンプルに以下の2つの文章を利用して文章のベクトル化を解説します。

  • I am a student. He is a student, too.
  • She is not a student.

ソースコード

 解説に先立ち、本稿で解説するソースコード全行を示します。

ライブラリのインポート

 本稿の解説で主役となるのは、Keras ライブラリに含まれる Tokenizer クラスです。 この Tokenizer クラスが、文章のベクトル化を助けてくれます。 まずは Tokenizer をインポートします。

from keras.preprocessing.text import Tokenizer

文章の宣言

 次に Tokenizer に読み込ませたい文章を宣言します。 上記の「前提」の通り、2つの文章をリストで宣言します。

# ベクトル化したい文章をリストで宣言します。
texts = ["I am a student. He is a student, too.", "She is not a student."]

Tokenizer の初期化

 Tokenizer を初期化します。 そして、fit_on_texts() メソッドの引数に、上で宣言した文章のリストを与えます。 fit_on_texts() メソッドに文章を与えることで、文章を解析して集計を行なってくれます。

# Tokenizerをインスタンス化し、上で用意した文章を与えます。
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)

文章数の取得

 fit_on_texts() メソッドを呼び出した事で、document_count 属性から与えられた文章の数を取得できます。 本稿では2つの文章を静的に宣言していますが、実際にはテキストファイルやデータベースなどから文章データを読み込んで処理することが多いでしょうから、いくつの文章を読み込んだのかを知るには、便利な属性です。

# 与えられた文章の数を取得します。
print("与えられた文章の数 : ", tokenizer.document_count)
与えられた文章の数 :  2

文章内の単語ごとの出現回数

 fit_on_text() メソッドの呼び出しにより、word_counts 属性も利用できます。 word_counts 属性は、与えた文章内で各単語がそれぞれ何回登場したのかをカウントした値です。

# 与えられた文章内の単語ごとの出現回数
print("与えられた文章内の単語ごとの出現回数 : ", tokenizer.word_counts)
与えられた文章内の単語ごとの出現回数 :  OrderedDict([('i', 1), ('am', 1), ('a', 3), ('student', 3), ('he', 1), ('is', 2), ('too', 1), ('she', 1), ('not', 1)])

単語ごとに割り当てられたインデックス番号

 fit_on_text() メソッドの呼び出しにより、word_index 属性も利用できます。 word_index 属性は、文章中に登場する単語にインデックス番号を割り当てたものです。 次の例だと「a」は1番, 「student」は2番, 「i」は3番 というように、単語に番号付けをしています。

# 単語ごとに割り当て当てられたインデックス番号
print(tokenizer.word_index)
{'a': 1, 'student': 2, 'is': 3, 'i': 4, 'am': 5, 'he': 6, 'too': 7, 'she': 8, 'not': 9}

ベクトル化

 それでは、ここからが本題の「ベクトル化」です。 ベクトルを取得するには texts_to_matrix() メソッドを利用します。 その際に取得したいベクトル表現を引数で指定することができます。 ここでは「バイナリ表現」「カウント表現」「TF-IDF表現」の3つの表現のベクトルを取得してみたいと思います。

バイナリ表現のベクトル取得

 まずはバイナリ表現のベクトルの取得です。 バイナリ表現とは、特定の単語が文章中に登場するか否かを「0」「1」の2つの数値で表したベクトルです。 単語の出現回数は問わず、文章中に登場すれば「1」となります。text_to_matrix() メソッドの第二引数に "binary" を指定します。

matrix = tokenizer.texts_to_matrix(texts, "binary")
print(matrix)
[[0. 1. 1. 1. 1. 1. 1. 1. 0. 0.]
 [0. 1. 1. 1. 0. 0. 0. 0. 1. 1.]]

 「I am a student. He is a student, too.」と「She is not a student.」の2つの文章をベクトル化したのが、上の結果です。 「0」と「1」の数字が現れています。 数字の並びは上記の word_index 属性で取得できた並びの順です。 インデックス番号「0」には単語が割り当てられていないので、常に「0」である点に注意してください。

カウント表現のベクトル取得

 次にカウント表現のベクトルの取得です。 カウント表現は、単語の出現数をベクトルに反映する表現です。 text_to_matrix() メソッドの第二引数に "count" を指定します。

matrix = tokenizer.texts_to_matrix(texts, "count")
print(matrix)
[[0. 2. 2. 1. 1. 1. 1. 1. 0. 0.]
 [0. 1. 1. 1. 0. 0. 0. 0. 1. 1.]]

 1つ目の文章ベクトルの、インデックス番号 1 (a) と 2 (student) が「2」になっているのがわかります。 単語の出現回数が反映されています。

TF-IDF表現のベクトル取得

 次に TF-IDF 表現です。 TF-IDF (Term Frequency - Inverse Document Frequency) は「文章に含まれる単語の重要度」を数値化したもので、出現頻度が高く、更にいくつもの文章で出現しない単語ほど高い数字になるという特徴があります。 text_to_matrix() メソッドの第二引数に "tfidf" を指定することで取得できます。

matrix = tokenizer.texts_to_matrix(texts, "tfidf")
print(matrix)
[[0.         0.86490296 0.86490296 0.51082562 0.69314718 0.69314718
  0.69314718 0.69314718 0.         0.        ]
 [0.         0.51082562 0.51082562 0.51082562 0.         0.
  0.         0.         0.69314718 0.69314718]]

ベクトルの特徴

 ここまででベクトルの作り方について解説してきました。 最後に、生成されたベクトルの特徴について整理したいと思います。

 上で示した結果では、それぞれのベクトルの次元数は「10」でした。これは、2つの文章に登場する単語の種類が10個だったからです。 言い換えれば「文章に登場する単語の種類数が、ベクトルの次元数になる」ということです。 ベクトルの次元数が増えれば増えるほど、コンピュータでの処理は大変になってきますので、長文かつ単語数の多い文章を処理したい場合は処理が重くなる点は知っておくべき点です。

日本語文章のベクトル化

 本稿では2つの英文を例に、文章のベクトル化について解説しました。 日本語文章をベクトル化したい場合は、与える文章に一工夫必要です。 英語の文章はスペースで単語が区切られているので単語を分解しやすい特徴がありますが、日本語の文章は単語ごとに区切りがありません。 そのため、日本語を処理する際には、単語をスペースで区切る、いわゆる「わかち書き」になるようにしておく必要があります。 日本語文章から単語を抽出するには、Mecab を利用することが多いです。 気になる方は Mecab をインターネットで検索してみてください。

まとめ

 本稿では Keras の Tokenizer を利用して、文章をベクトル化する方法について解説しました。 自力で実装するにはとても手間がかかる処理ですので、ぜひ知っておくと良いでしょう。

著者 : OSCA

OSCA

Java, PHP 系のWEBエンジニア。 WEBエンジニア向けコミュニティ「WEBエンジニア勉強会」を主催。
個人として何か一つでも世の中の多くの人に使ってもらえるものを作ろうと日々奮闘中。
@engineer_osca