Path: blob/master/site/ja/hub/tutorials/tf2_text_classification.ipynb
25118 views
Copyright 2019 The TensorFlow Hub Authors.
Apache License, Version 2.0(以下「ライセンス」)によるライセンス契約;
映画レビューを使ったテキスト分類
このノートブックでは、映画レビューのテキストを使用して、それが肯定的であるか否定的であるかに分類します。これは二項分類の例で、機械学習問題では重要な分類法として広く適用されます。
Internet Movie Database より、50,000 件の映画レビューテキストが含まれる IMDB データセットを使用します。これは、トレーニング用の 25,000 件のレビューとテスト用の 25,000 件のレビューに分割されます。トレーニングセットとテストセットは均衡が保たれており、肯定的評価と否定的評価が同じ割合で含まれます。
このノートブックでは、TensorFlow でモデルを構築してトレーニングするための tf.keras という高レベル API と、転移学習用のライブラリ兼プラットフォームである TensorFlow Hub を使用します。tf.keras
を使用した、より高度なテキスト分類チュートリアルについては、MLCC Text Classification Guide をご覧ください。
その他のモデル
テキスト埋め込みの生成に使用できる、より表現豊かなモデルや効率性の高いモデルをこちらでご覧ください。
MNIST モデルをビルドする
IMDB データセットをダウンロードする
IMDB データセットは、TensorFlow データセットで提供されています。次のコードを使って、IMDB データセットをマシン(または Colab ランタイム)にダウンロードしてください。
データの観察
データの形式を確認してみましょう。各サンプルは、映画レビューを表す文章と対応するラベルです。文章はまったく事前処理されていません。ラベルは 0 または 1 の整数値で、0 は否定的なレビューで 1 は肯定的なレビューを示します。
最初の 10 個のサンプルを出力しましょう。
最初の 10 個のラベルも出力しましょう。
モデルを構築する
ニューラルネットワークは、レイヤーのスタックによって作成されています。これには、次の 3 つのアーキテクチャ上の決定が必要です。
どのようにテキストを表現するか。
モデルにはいくつのレイヤーを使用するか。
各レイヤーにはいくつの非表示ユニットを使用するか。
この例では、入力データは文章で構成されています。予測するラベルは、0 または 1 です。
テキストの表現方法としては、文章を埋め込みベクトルに変換する方法があります。トレーニング済みのテキスト埋め込みを最初のレイヤーとして使用することで、次のような 2 つのメリットを得ることができます。
テキストの事前処理を心配する必要がない。
転移学習を利用できる。
この例では、TensorFlow Hub のモデルである「google/nnlm-en-dim50/2」を使います。
このチュートリアルのためにテストできるモデルが、ほかに 2 つあります。
google/nnlm-en-dim50-with-normalization/2 - google/nnlm-en-dim50/2 と同じものですが、句読点を削除するためのテキスト正規化が含まれています。このため、入力テキストのトークンに使用する語彙内埋め込みのカバレッジを改善することができます。
google/nnlm-en-dim128-with-normalization/2 - 50 次元未満でなく、128 の埋め込み次元を備えたより大規模なモデルです。
では始めに、TensorFlow Hub モデル を使用して文章を埋め込む Keras レイヤーを作成し、いくつかの入力サンプルで試してみましょう。生成される埋め込みの出力形状は、(num_examples, embedding_dimension)
であるところに注意してください。
今度は、完全なモデルを構築しましょう。
これらのレイヤーは、分類器を構成するため一列に積み重ねられます。
最初のレイヤーは、TensorFlow Hub レイヤーです。このレイヤーは文章から埋め込みベクトルにマッピングする事前トレーニング済みの SavedModel を使用します。使用しているモデル (google/nnlm-en-dim50/2) は文章とトークンに分割し、各トークンを埋め込んで、埋め込みを組み合わせます。その結果、次元は
(num_examples, embedding_dimension)
となります。この固定長の出力ベクトルは、16 個の非表示ユニットを持つ全結合(
Dense
)レイヤーに受け渡されます。最後のレイヤーは単一の出力ノードで密に接続されます。これは、ロジットを出力します。モデルに応じた、真のクラスの対数オッズです。
非表示ユニット
上記のモデルには、入力と出力の間に 2 つの中間または「非表示」レイヤーがあります。出力数(ユニット数、ノード数、またはニューロン数)はレイヤーの表現空間の次元で、言い換えると、内部表現を学習する際にネットワークが許可された自由の量と言えます。
モデルの非表示ユニット数やレイヤー数が増えるほど(より高次元の表現空間)、ネットワークはより複雑な表現を学習できますが、ネットワークの計算がより高価となり、トレーニングデータでのパフォーマンスを改善してもテストデータでのパフォーマンスは改善されない不要なパターンが学習されることになります。この現象を過適合と呼び、これについては後の方で説明します。
損失関数とオプティマイザ
モデルをトレーニングするには、損失関数とオプティマイザが必要です。これは二項分類問題であり、モデルは確率(シグモイドアクティベーションを持つ単一ユニットレイヤー)を出力するため、binary_crossentropy
損失関数を使用します。
これは、損失関数の唯一の選択肢ではありません。たとえば、mean_squared_error
を使用することもできます。ただし、一般的には、確率を扱うには binary_crossentropy
の方が適しているといえます。これは、確率分布間、またはこのケースではグランドトゥルース分布と予測間の「距離」を測定するためです。
後の方で、回帰問題(家の価格を予測するなど)を考察する際に、平均二乗誤差と呼ばれる別の損失関数の使用方法を確認します。
では、オプティマイザと損失関数を使用するようにモデルを構成します。
検証セットを作成する
トレーニングの際、モデルが遭遇したことのないデータでモデルの精度を確認したいと思います。そこで、元のトレーニングデータから 10,000 個のサンプルを取り出して検証セットを作成します(ここでテストセットを使用しないのは、トレーニングデータのみを使用してモデルの構築と調整を行った上で、テストデータを一度だけ使用して精度を評価することを目標としているからです)。
モデルのトレーニング
モデルを 512 サンプルのミニバッチで 40 エポック、トレーニングします。これは、x_train
と y_train
テンソルのすべてのサンプルを 40 回イテレーションします。トレーニング中、検証セットの 10,000 個のサンプルで、モデルの損失と精度を監視します。
モデルを評価する
モデルのパフォーマンスを見てみましょう。2 つの値が返されます。損失(誤差、値が低いほど良)と正確率です。
このかなり単純なアプローチで、約 87% の正解率が達成されます。より高度なアプローチを使えば、95% に近づくでしょう。
経時的な精度と損失のグラフを作成する
model.fit()
は、トレーニング中に発生したすべての情報を詰まったディクショナリを含む History
オブジェクトを返します。
トレーニングと検証中に監視されている各メトリックに対して 1 つずつ、計 4 つのエントリがあります。このエントリを使用して、トレーニングと検証の損失とトレーニングと検証の精度を比較したグラフを作成することができます。
このグラフでは、点はトレーニングの損失と正解度を表し、実線は検証の損失と正解度を表します。
トレーニングの損失がエポックごとに下降し、トレーニングの正解度がエポックごとに上昇していることに注目してください。これは、勾配下降最適化を使用しているときに見られる現象で、イテレーションごとに希望する量を最小化します。
これは検証の損失と精度には当てはまりません。20 エポック当たりでピークに達しているようです。これが過適合の例で、モデルが、遭遇したことのないデータよりもトレーニングデータで優れたパフォーマンスを発揮する現象です。この後、モデルは過度に最適化し、テストデータに一般化しないトレーニングデータ特有の表現を学習します。
このような特定のケースについては、約 20 エポック以降のトレーニングを単に停止することで、過適合を回避することができます。この処理をコールバックによって自動的に行う方法については、別の記事で説明します。