深層学習の実用例: LSTM に基づく、映画レビューの感情分類予測のための 4 つの方法 (完全なコード付き)

シーケンス分類は、いくつかの入力シーケンスがあり、タスクはシーケンスのクラスを予測することである予測モデリングの問題です。

シーケンスの長さが異なり、入力シンボルの非常に大きなボキャブラリが含まれている可能性があり、モデルが入力シーケンス内のシンボル間の長期的なコンテキストまたは依存関係を学習する必要があるため、この問題は困難です。

この記事では、Keras ディープ ラーニング ライブラリを使用して、シーケンス分類問題用の LSTM 再帰型ニューラル ネットワーク モデルを Python で開発する方法を学習します。
この記事を読むと、次のことがわかります。

  • シーケンス分類問題の LSTM モデルを開発する方法
  • ドロップアウトを使用して LSTM モデルのオーバーフィッティングを減らす方法
  • 空間関係の学習に優れた畳み込みニューラル ネットワークと LSTM モデルを組み合わせる方法

技術のアップグレード

テクノロジーは共有とコミュニケーションを学ぶ必要があり、密室で作業することはお勧めできません。人は速く行くことができ、人々のグループはより遠くに行くことができます.

完全なコード、データ、および技術交換の改善はすべて、Knowledge Planet 交換グループに参加することで取得できます. グループには 2,000 人以上のメンバーがいます. 追加するときは、次の点に注意してください: ソース + 興味の方向, これは志を同じくする友人を見つけるのに便利です. .

方法①、WeChatアカウント追加:pythoner666、備考:CSDNから+動画レビュー
方法②、WeChat検索公式アカウント:Python学習とデータマイニング、バックグラウンド返信:情報

問題の説明

Keras は、IMDB データセットへの組み込みアクセスを提供します。imdb.load_data()関数を使用すると、ニューラル ネットワークおよび深層学習モデルに使用できる形式でデータセットを読み込むことができます。

単語は、データセット内の各単語の順序付けられた頻度を表す整数に置き換えられています。したがって、各レビューの文は一連の整数で構成されます。

単語の埋め込み

各映画のレビューを実際のベクトル ドメインにマッピングします。これは、単語の埋め込みと呼ばれる、テキストを操作する際の一般的な手法です。これは、高次元空間で単語を実数値ベクトルとしてエンコードする手法であり、単語間の意味の類似性がベクトル空間での近接性に変換されます。

Keras は、埋め込みレイヤーを介して単語の正の整数表現を単語埋め込みに変換する便利な方法を提供します。

各単語を長さ 32 の実数値ベクトルにマップします。また、モデル化する単語の総数を最も一般的な 5000 単語に制限し、残りをゼロにします。最後に、各レビューはシーケンスの長さ (単語数) が異なるため、各レビューを 500 単語に制限し、長いレビューを切り捨て、短いレビューにはゼロの値を埋め込みます。

問題を定義し、データを準備してモデル化する方法を定義したので、映画レビューの感情を分類する LSTM モデルを開発する準備が整いました。

シーケンス分類のための単純な LSTM

IMDB の問題で小さな LSTM をすばやく開発し、優れた精度を得ることができます。

このモデルに必要なクラスと関数をインポートし、結果を簡単に再現できるように乱数ジェネレーターを定数値に初期化することから始めましょう。

import tensorflow as tf
from tensorflow.keras.datasets import imdb
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import LSTM
from tensorflow.keras.layers import Embedding
from tensorflow.keras.preprocessing import sequence

IMDB データセットをロードする必要があります。データセットを最初の 5,000 語に制限します。また、データセットをトレーニング セット (50%) とテスト セット (50%) に分割します。

# load the dataset but only keep the top n words, zero the rest
top_words = 5000
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words)

次に、モデリングのためにすべて同じ長さになるように、入力シーケンスを切り捨ててパディングする必要があります。モデルは、ゼロ値には情報がないことを学習します。内容的には、シーケンスの長さは異なりますが、Keras で計算を実行するには、同じ長さのベクトルが必要です。

# truncate and pad input sequences
max_review_length = 500
X_train = sequence.pad_sequences(X_train, maxlen=max_review_length)
X_test = sequence.pad_sequences(X_test, maxlen=max_review_length)

LSTM モデルを定義、コンパイル、適合できるようになりました。

最初の層は埋め込み層で、長さ 32 のベクトルを使用して各単語を表します。次の層は、100 個のメモリ ユニット (スマート ニューロン) を持つ LSTM 層です。最後に、これは分類問題であるため、1 つのニューロンとシグモイド活性化関数を含む高密度出力層を使用して、問題の 2 つのクラス (良いものと悪いもの) に対して 0 または 1 の予測を行います。

これはバイナリ分類問題であるため、ログ損失が損失関数として使用されます ( Keras のbinary_crossentropy )。効率的な ADAM 最適化アルゴリズムを使用します。モデルはすぐに問題に過適合するため、2 つのエポックにのみ適しています。間隔の重みの更新には、64 件のレビューの大規模なバッチが使用されます。

# create the model
embedding_vecor_length = 32
model = Sequential()
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=64)

フィッティングが完了すると、モデルが目に見えないレビューでどのように機能するかを見積もることができます。

# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

この例を実行すると、次の出力が生成されます。

Epoch 1/3
391/391 [==============================] - 124s 316ms/step - loss: 0.4525 - accuracy: 0.7794
Epoch 2/3
391/391 [==============================] - 124s 318ms/step - loss: 0.3117 - accuracy: 0.8706
Epoch 3/3
391/391 [==============================] - 126s 323ms/step - loss: 0.2526 - accuracy: 0.9003
Accuracy: 86.83%

ほとんど調整されていないこの単純な LSTM が、IMDB 問題でほぼ最先端の結果を達成していることがわかります。重要なことに、これは、LSTM ネットワークを独自のシーケンス分類問題に適用するために使用できるテンプレートです。

ここで、この単純なモデルのいくつかの拡張を見てみましょう。これは、独自の問題にも使用できます。

ドロップアウトを伴うシーケンス分類のための LSTM

LSTM のような再帰型ニューラル ネットワークは、一般にオーバーフィッティングの影響を受けます。

ドロップアウトは、Dropout Keras レイヤーを使用してレイヤー間に適用できます。これは、Embedding レイヤーと LSTM レイヤーの間、および LSTM と Dense 出力レイヤーの間に新しいドロップアウト レイヤーを追加することで簡単に実行できます。

例えば:

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length, input_length=max_review_length))
model.add(Dropout(0.2))
model.add(LSTM(100))
model.add(Dropout(0.2))
model.add(Dense(1, activation='sigmoid'))

この例を実行すると、次の出力が得られます。

Epoch 1/3
391/391 [==============================] - 117s 297ms/step - loss: 0.4721 - accuracy: 0.7664
Epoch 2/3
391/391 [==============================] - 125s 319ms/step - loss: 0.2840 - accuracy: 0.8864
Epoch 3/3
391/391 [==============================] - 135s 346ms/step - loss: 0.3022 - accuracy: 0.8772
Accuracy: 85.66%

ドロップアウトがトレーニングに期待される効果をもたらし、収束がわずかに遅くなる傾向があることがわかります。この場合、最終的な精度は低くなります。モデルはより多くのトレーニング エポックを使用し、より高いスキルを獲得する可能性があります (試してみてください)。

あるいは、ドロップアウトは、メモリ セルの LSTM への入力接続および再帰接続のみに正確に適用できます。

Keras は LSTM レイヤーのパラメーターを通じてこの機能を提供し、dropout は入力ドロップアウトを構成するために使用されrecurrent_dropout は反復ドロップアウトを構成するために使用されます。

たとえば、最初の例を次のように変更して、入力接続と再帰接続にドロップアウトを追加できます。

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length)
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))

この例を実行すると、次の出力が得られます。

Epoch 1/3
391/391 [==============================] - 220s 560ms/step - loss: 0.4605 - accuracy: 0.7784
Epoch 2/3
391/391 [==============================] - 219s 560ms/step - loss: 0.3158 - accuracy: 0.8773
Epoch 3/3
391/391 [==============================] - 219s 559ms/step - loss: 0.2734 - accuracy: 0.8930
Accuracy: 86.78%

LSTM 固有のドロップアウトは、レイヤー単位のドロップアウトよりもネットワークの収束に大きな影響を与えることがわかります。上記のように、エポックの数は一定のままであり、モデルのスキルをさらに改善できるかどうかを確認するために増やすことができます。

ドロップアウトは、LSTM モデルのオーバーフィッティングに対処するための強力な手法であり、両方を試すことをお勧めします。ただし、Keras で利用可能なゲート固有のドロップアウトを使用すると、より良い結果が得られる場合があります。

シーケンス分類のための双方向 LSTM

逆の順序でシーケンスを使用する方がよい場合もあります。このような場合、Python 構文 x[::-1] を使用して単純にベクトルを反転し、それを使用して LSTM ネットワークをトレーニングできます。

順順も逆順も完全に機能しない場合がありますが、それらを組み合わせることでより良い結果が得られます。この場合、双方向の LSTM ネットワークが必要になります。

双方向 LSTM ネットワークは、単純に 2 つの独立した LSTM ネットワークであり、一方は順方向に供給され、もう一方は逆方向に供給されます。2 つの LSTM ネットワークの出力は、ネットワークの後続のレイヤーに供給される前に連結されます。

Keras では、Bidirectional() 前方後方入力用の LSTM レイヤーのクローンを作成し、それらの出力を連結できます。例えば、

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length)
model.add(Bidirectional(LSTM(100, dropout=0.2, recurrent_dropout=0.2)))
model.add(Dense(1, activation='sigmoid'))

それぞれ 100 ユニットの LSTM を 1 つではなく 2 つ作成したため、ネットワークのトレーニングには 2 倍の時間がかかります。問題によっては、この追加費用が正当化される場合があります。

この例を実行すると、次の出力が得られます。

Epoch 1/3
391/391 [==============================] - 405s 1s/step - loss: 0.4960 - accuracy: 0.7532
Epoch 2/3
391/391 [==============================] - 439s 1s/step - loss: 0.3075 - accuracy: 0.8744
Epoch 3/3
391/391 [==============================] - 430s 1s/step - loss: 0.2551 - accuracy: 0.9014
Accuracy: 87.69%

わずかな改善しか得られないように見えますが、トレーニング時間ははるかに長くなります。

シーケンス分類のための LSTM と畳み込みニューラル ネットワーク

たとえば、次のようにモデルを作成できます。

model = Sequential()
model.add(Embedding(top_words, embedding_vecor_length))
model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))

完全を期すために、CNN 層と LSTM 層を含む完全なコード リストを以下に示します。

この例を実行すると、次の出力が得られます。

Epoch 1/3
391/391 [==============================] - 65s 163ms/step - loss: 0.4213 - accuracy: 0.7950
Epoch 2/3
391/391 [==============================] - 66s 168ms/step - loss: 0.2490 - accuracy: 0.9026
Epoch 3/3
391/391 [==============================] - 73s 188ms/step - loss: 0.1979 - accuracy: 0.9261
Accuracy: 88.45%

重みが少なく、トレーニング時間が短いにもかかわらず、最初の例よりもわずかに良い結果が得られていることがわかります。
この例をさらに拡張してドロップアウトを使用すると、より良い結果が期待できます。

おすすめ

転載: blog.csdn.net/weixin_38037405/article/details/130463966