TensorFlowのチュートリアルをやってよう! テキスト分類編

この記事ではtensorflowの”text classification“というチュートリアルをやります。

このチュートリアルでは映画のレビューの文章を用いてポジティブかネガティブに分類する方法が学べます。

実行環境

anaconda (python3.6), Jupyter Notebook 5.7.4, tensorFlow1.12.0

モジュールのインポート

tensorflowとnumpyとtensorflowをラップした高レベルのAPIのkerasを使います。

データセットのダウンロード

データセットは5万件の映画レビューを含むIMDBデータセットを使います。訓練データ2.5万件、テストデータ2.5万件に分けられます。

バランスを取るためポジティヴレビューとネガテイブレビューは同数存在します。

IMDBはTensorFlowに同梱されています。レビュー(単語の並び)が整数の並びになる様に変換されるよう前処理されています。各整数は辞書内の特定の単語を表します。

扱う文章は英語です。i → 1, use → 12, TensorFlow → 333,の様に単語に番号が振られているとしたら, “I use TensorFlow” という文章が [1, 12, 333]という整数の並びに変換されるイメージです。

次のコードはIMDBをダウンロードして変数にセットしています。num_words=10000とすることで、訓練データの中で最も出現する単語の上位10000単語を保持するように指定しています。

【結果】

データを調べる

データの数とラベルの数を調べます。

【結果】

最初のレビューを表示します。何かの単語に対応する整数のリストになっていることが確認できます。

【結果】

最初と2つ目のレビューの長さを調べると2つの長さが違うことがわかります。ニューラルネットワークでは入力のサイズを同じにする必要があるため、後でこれを解決します。

【結果】

整数を単語に戻す

整数を単語に戻す方法も知っておくと便利です。

【結果】ダウンロードログが表示されます。

最初のレビューを文章で表示してみます。

【結果】

データを準備

整数の配列はニューラルネットワークに入力する前にテンソルに変換する必要があります。今回は整数の配列が全て同じ長さになるように変換します。サイズはmax_length × num_reviewsになります。これを最初の層として使います。

pad_sequense関数を使用して長さを標準化します。その後最初と二番目のレビューの長さを確認すると、同じ長さになっていることが分かります。

【結果】

最初のレビューを表示すると後半が0で埋められていることが確認できます。

【結果】

モデルを構築する

ニューラルネットワークはレイヤーを重ねることによって作成されます。これには、以下の主なアーキテクチャを決めなければいけません。

  • いくつモデルでレイヤーを使うか?
  • それぞれのレイヤーにいくつ”隠れユニット”使用するか?

以下のコードでモデルを作成します。

【結果】

これらのレイヤーを順番に積み重ねて分類器を構築します。

第1レイヤー Embeddingレイヤー

このレイヤーは整数に変換された単語を得て、単語埋め込みベクトルを調べます。これらのベクトルが訓練用モデルとして学習されます。このベクトルは次元を1つ追加した配列を出力します。結果は、(batch, sequence, embedding)です。

第2レイヤー GlobalAveragePooling1Dレイヤー

このレイヤーは、それぞれの次元の平均を取ることで、各例の固定長ベクトルを返します。可能な限り簡単な方法で可変長の入力を処理できます。

第3レイヤ Denseレイヤー

出力された固定長ベクトルは16の”隠れユニット”を持つ完全に接続されたレイヤー(Denseレイヤー)を通してパイプ処理されます。

最後のレイヤー Denseレイヤー

このレイヤーは単一​​の出力ノードと密接に接続されています。シグモイド関数を使用することで、確率または信頼水準を表す0~1の値になります。

隠しユニット

隠しユニットとは上記のモデルの場合、入力と出力の間にある2つの中間層のことです。このユニットが多いほどネットワークは複雑な表現を学習できます。

損失関数とオプティマイザ

モデルには、損失関数と学習用の最適化が必要です。今回は2つに分類する問題であり、モデルは確率を出力するのでbinary_crossentropyという損失関数を使用します。

次のコードはオプティマイザと損失関数を使用するようにモデルを構成します。

検証セットを作成する

訓練データから10000件を検証データとして使用します。

モデルを訓練する

batch_size=512, epochs=40に設定します。x_trainとy_trainにある全てのサンプルで40回反復させます。トレーニング中に検証セットから1万サンプルでモデルの損失と制度をモニタリングします。

【結果】

モデルを評価する

テストデータを使ってモデルを評価します。以下のコードで損失と、正確さが分かります。損失値は値が低い方が良い結果です。

【結果】

正確性は約87%でした。

訓練による正確性と損失のグラフを作成する

model.fit()は Historyオブジェクトを返します。このオブジェクトは訓練中におきたこと全てを含む辞書です。

【結果】

訓練中の正確性と損失、検証中の正確性と損失の計4つです。これらを使用して訓練時の損失と検証時の損失の比較、訓練時の正確性と検証時の正確性の比較ができます。

【結果】
訓練中は訓練を重ねるごとに徐々に損失値が低下していますが、検証するときは25回目前後で最小値になりそれ以降は少し上昇しました。

【結果】

訓練を重ねるごとに正確性は上昇していますが、検証結果による、25回目以降はほぼ横ばい(約0.87)でした。

lossが減少し、Accuracyが増加することに注目してください。これは勾配効果最適化を使用するときに予想されます。反復ごとに必要な量を最小限に抑える必要があります。

約20エポック後にピークに達するため、この損失値と正確性(訓練するごとに正確性が100%に近く)は正しくはありません。これは過剰適合の例です。

この場合は、20回程度の反復の後に訓練を中止することで過剰適合を防ぐことができます。これはコールバックを使って自動的に行う方法があります。

まとめ

映画のレビューをポジティブかネガティブに分類するモデルの作成方法を学べました。

訓練をしながら検証を行うことで、モデルの損失値や正確性の推移を出すことができました。モデルの分析がしやすくなりますね。

反復回数が多かったためモデルが訓練用データに特化する過剰適合という状態になりました。

過剰適合を防ぐための方法は後のチュートリアルで出るそうです。

スポンサーリンク
スポンサーリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です