web-dev-qa-db-ja.com

LSTMが可変長シーケンスを処理する方法

Pythonを使用したディープラーニング の第7章のセクション1に次のようなコードが見つかりました:

from keras.models import Model
from keras import layers
from keras import Input

text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size = 500

# Our text input is a variable-length sequence of integers.
# Note that we can optionally name our inputs!
text_input = Input(shape=(None,), dtype='int32', name='text')

# Which we embed into a sequence of vectors of size 64
embedded_text = layers.Embedding(64, text_vocabulary_size)(text_input)

# Which we encoded in a single vector via a LSTM
encoded_text = layers.LSTM(32)(embedded_text)

# Same process (with different layer instances) for the question
question_input = Input(shape=(None,), dtype='int32', name='question')
embedded_question = layers.Embedding(32, question_vocabulary_size)(question_input)
encoded_question = layers.LSTM(16)(embedded_question)

# We then concatenate the encoded question and encoded text
concatenated = layers.concatenate([encoded_text, encoded_question], axis=-1)

# And we add a softmax classifier on top
answer = layers.Dense(answer_vocabulary_size, activation='softmax')(concatenated)

# At model instantiation, we specify the two inputs and the output:
model = Model([text_input, question_input], answer)
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['acc'])

ご覧のとおり、このモデルの入力には生データの形状情報がありません。埋め込みレイヤーの後、LSTMの入力または埋め込みの出力は可変長のシーケンスになります。

model_summary

だから私は知りたい:

  • このモデルでは、ケラがLSTMレイヤーのlstm_unitの数を決定する方法
  • 可変長シーケンスの処理方法

追加情報:lstm_unitが何であるかを説明するために(私はそれを呼び出す方法がわからないので、画像を表示するだけです):

lstm_unit

6
Rosand Liu

提供された反復レイヤーは、基本実装_keras.layers.Recurrent_から継承します。これには、オプション_return_sequences_が含まれ、デフォルトはFalseです。これが意味するのは、デフォルトでは、反復レイヤーは可変長の入力を消費し、最終的には最後の順次ステップでレイヤーの出力のみを生成するということです。

その結果、Noneを使用して可変長の入力シーケンスの次元を指定することに問題はありません。

ただし、レイヤーが出力の完全なシーケンス、つまり入力シーケンスの各ステップの出力のテンソルを返すようにしたい場合は、その出力の可変サイズをさらに処理する必要があります。

これを行うには、次のレイヤーでさらに可変サイズの入力を受け入れ、ネットワーク内で後で問題をパントして、最終的に可変長のものから損失関数を計算するか、固定長のものを計算する必要があります。モデルに応じて、後のレイヤーに進む前の長さの表現。

または、固定長のシーケンスを要求することでそれを行うことができます。おそらく、シーケンスの最後に、長さをパディングするためだけに空のシーケンス項目を示すだけの特別な番兵値をパディングします。

これとは別に、Embeddingレイヤーは、可変長入力も処理するように構築された非常に特殊なレイヤーです。出力形状は、入力シーケンスのトークンごとに異なる埋め込みベクトルを持つため、形状は(バッチサイズ、シーケンス長、埋め込み次元)になります。次の層はLSTMであるため、これは問題ありません...可変長シーケンスも問題なく消費されます。

しかし、Embeddingのドキュメントに記載されているように:

_input_length: Length of input sequences, when it is constant.
      This argument is required if you are going to connect
      `Flatten` then `Dense` layers upstream
      (without it, the shape of the dense outputs cannot be computed).
_

Embeddingから非可変長の表現に直接移動する場合は、レイヤーの一部として固定シーケンス長を指定する必要があります。

最後に、LSTM(32)などのLSTMレイヤーの次元を表現するときは、そのレイヤーの出力空間の次元を記述していることに注意してください。

_# example sequence of input, e.g. batch size is 1.
[
 [34], 
 [27], 
 ...
] 
--> # feed into embedding layer

[
  [64-d representation of token 34 ...],
  [64-d representation of token 27 ...],
  ...
] 
--> # feed into LSTM layer

[32-d output vector of the final sequence step of LSTM]
_

バッチサイズ1の非効率性を回避するための1つの戦術は、入力トレーニングデータを各例のシーケンス長で並べ替えてから、カスタムKeras DataGeneratorなどを使用して、一般的なシーケンス長に基づいてバッチにグループ化することです。

これには、特にモデルにバッチ正規化などが必要な場合やGPUを多用するトレーニングが含まれる場合に、バッチ更新の勾配の推定のノイズが少ないという利点がある場合でも、大きなバッチサイズを許可できるという利点があります。ただし、例ごとにバッチ長が異なる入力トレーニングデータセットで作業することはできます。

さらに重要なのは、入力で共通のシーケンス長を確保するためにパディングを管理する必要がないという大きな利点もあります。

7
ely

ユニットはどのように処理されますか?

単位は長さに完全に依存しないため、特別なことは何も行われていません。

長さは「反復ステップ」を増やすだけですが、反復ステップは常に同じセルを何度も使用します。

セルの数はユーザーによって固定および定義されます。

  • 最初のLSTMには32個のセル/ユニットがあります
  • 2番目のLSTMには16個のセル/ユニットがあります

可変長の扱い方は?

  • アプローチ1:1つのシーケンスの個別のバッチを作成し、各バッチに独自の長さを設定します。各バッチをモデルに個別にフィードします。手動ループ内のメソッドtrain_on_batchおよびpredict_on_batchが最も簡単な形式です。
    • 理想的には、長さごとに別々のバッチで、各バッチは同じ長さのすべてのシーケンスを収集します
  • アプローチ2:固定長のバッチを作成し、各シーケンスの未使用のテール長を0で埋め、埋め込みレイヤーでパラメーターmask_zero=Trueを使用します。
    • 埋め込みの入力で実際の単語または意味のあるデータとして0を使用しないように注意してください。
2
Daniel Möller