ナード戦隊データマン

データサイエンスを用いて悪と戦うぞ

tensorflow-hubで超簡単にテキスト分類モデルが作成できる

テキスト分類とは、テキストとそれに対するカテゴリーや極性(ポジティブかネガティブか)があり、カテゴリーをラベルとして解く分類問題です。ここでは、テキスト分類の基本を大雑把に書き、tensorflowによるニューラルネットモデルが超かんたんに作れることを書きます。

2018/06/23: 追記

dataset.csvに"category"というカラムがないようです。おそらく、私がtypeというネーミングがデータ型みたいな感じで嫌でcategoryに変えていたのを忘れていたのだと思います。また、dataset.csvを読み込むときに、もしかしたらencodingをlatin1に指定して読み込む必要があるかもしれません。

テキスト分類の方法とそれぞれの利点

テキスト分類の従来的な方法は、テキストから素性抽出をします。特徴量設計は工夫次第で色々考えられますが、例えば素性には以下のようなものを考えることができます:

  • 特定の単語が出現する回数、またはそれに基づく数値。(tf-idfなど)
  • 品詞。
  • 特定のグループの単語が含まれるか否か。(2値)
  • メタ情報 (著者, URL,など)
  • 固有表現。
  • 構文。

例えば以前、tf-idfとロジスティック回帰を用いて求人テキストから給与予測をしましたが、これはニューラルネットを用いない従来的な方法で行いました。この方法の利点は、係数を見れるので、どの語がどのカテゴリーにどのぐらい影響しているのかを見ることができた点でした。

一方で、End to Endな方法、つまりディープラーニングを用いた方法では、生データ(テキスト)を入力すれば、予測結果が出てくるモデルです。しかし、そのネットワークの内部ではEmbeddingが用いられます。Embeddingとは、テキストや語をベクトルとして表現するものです。word2vecやgloveといったEmbeddingがあります。

ディープラーニングを用いたモデルの利点は、tf-idfを用いるよりも追加訓練などが柔軟にでき、訓練データには存在しなかった語(未知語)にも強く、特徴量設計や特徴量選択を手動で行わなくても良いという点です。

しかし、まだこの分野を学び始めて間もない頃に苦心してtensorflowを使ったことがありましたが、Embeddingを用いても大した精度がでませんでした。(そんなに前の話ではない。)

tensorflow-hubについて

tensorflow-hubは事前訓練されたモデルを使いまわすための(?)モジュール集みたいなものです。画像系タスクや自然言語処理系のタスクで利用できるモジュールが公開されています。

今回使うのは、nnlm-en-dim128です。これは、英語用のトークンベースEmbeddingです。日本語のnnlm-ja-dim128も用意されていますが、文書分類の日本語データを準備するのが面倒なので、ここでは英語で試します。

利用するデータ

BBC newsコーパスを用います。 http://mlg.ucd.ie/datasets/bbc.html

すでに変換済みのデータがgithubに公開されているのでこちらを使います。 https://github.com/suraj-deshmukh/BBC-Dataset-News-Classification/blob/master/dataset/dataset.csv

で、そのコード

import tensorflow as tf
import tensorflow_hub as hub
import numpy as np
import pandas as pd
from sklearn.utils import shuffle

if __name__ == "__main__":
    df = pd.read_csv("dataset.csv", encoding="latin1")
    df['category_id'] = df.type.factorize()[0]
    df = shuffle(df)

    train_input_fn = tf.estimator.inputs.pandas_input_fn(
        df[:1500], df[:1500]["category_id"], num_epochs=None, shuffle=True)

    predict_test_input_fn = tf.estimator.inputs.pandas_input_fn(
        df[1500:], df[1500:]["category_id"], shuffle=False)

    embedded_text_feature_column = hub.text_embedding_column(
        key="news", 
        module_spec="https://tfhub.dev/google/nnlm-en-dim128/1")

    estimator = tf.estimator.DNNClassifier(
        hidden_units=[500, 100],
        feature_columns=[embedded_text_feature_column],
        n_classes=5,
        optimizer=tf.train.AdagradOptimizer(learning_rate=0.003))

    estimator.train(input_fn=train_input_fn, steps=1000);
    test_eval_result = estimator.evaluate(input_fn=predict_test_input_fn)
    print("Test set accuracy: {accuracy}".format(**test_eval_result))

コードの説明

説明がいらないほど単純なコードですが、pandasデータを入力とするためのtf.estimator.inputs.pandas_input_fnがあり、データそのものとラベルを渡します。

hubで指定されているのはtfhubのnnlm-en-dim128のURLで、この実行には数十分時間がかかります。keyで指定されているのは、pandas_input_fnの最初の引数に指定しているpandasデータのキーで、このキーからEmbeddingを作成します。

あとはEmbeddingをDNNClassifierに渡すだけで、学習係数とオプティマイザを指定し、分類するクラス数を指定しています。更に、隠れ層のノード数を指定しています。

trainメソッドで訓練し、1000ステップまで実行をします。evaluateメソッドで指定のテストデータで精度(accuracy)を出力します。

具体的にどの部分が簡単なの?

word2vecのEmbeddingを自力で作成すると、以下の2つの困難があります:

  1. 巨大なデータを使う必要がある。
  2. 訓練に時間がかかる。(ので、プロセッサ数がたくさん必要)

検索すれば、「gensimでword2vecのEmbeddingを訓練したので公開します」みたいなありがたい記事もありますが、特に日本語の場合は公式なものは見当たらなかったような気がします。

tensorflow-hubでこういった「訓練に時間がかかる」ようなモデルを公開してくれると、リソースのない人たちにとってとてもありがたいものだといえます。その点が楽です。

まとめ

tensorflow-hubを活用するとハッピーになれる。

参考

[1] https://www.tensorflow.org/hub/ [2] http://d.hatena.ne.jp/jetbead/20131109/1383968030 [3] http://mlg.ucd.ie/datasets/bbc.html

追記: すみません、tensorflowさん...

いきなりtensorflowが意味不明なエラーを吐くようになりました。

$ python -m tensorflow
Illegal instruction (core dumped)