2016-12-21 15 views
1

テンソルフローRNNの非常に簡単な例を試しています。 その例では、動的なrnnを使用します。コードは次のとおりです。テンソルフローの動的テンソル形状RNN

data = tf.placeholder(tf.float32, [None, 10,1]) #Number of examples, number of input, dimension of each input 
target = tf.placeholder(tf.float32, [None, 11]) 
num_hidden = 24 
cell = tf.nn.rnn_cell.LSTMCell(num_hidden,state_is_tuple=True) 
val, _ = tf.nn.dynamic_rnn(cell, data, dtype=tf.float32) 
val = tf.transpose(val, [1, 0, 2]) 
last = tf.gather(val, int(val.get_shape()[0]) - 1) 
weight = tf.Variable(tf.truncated_normal([num_hidden, int(target.get_shape()[1])])) 
bias = tf.Variable(tf.constant(0.1, shape=[target.get_shape()[1]])) 
prediction = tf.nn.softmax(tf.matmul(last, weight) + bias) 
cross_entropy = -tf.reduce_sum(target * tf.log(tf.clip_by_value(prediction,1e-10,1.0))) 
optimizer = tf.train.AdamOptimizer() 
minimize = optimizer.minimize(cross_entropy) 
mistakes = tf.not_equal(tf.argmax(target, 1), tf.argmax(prediction, 1)) 
error = tf.reduce_mean(tf.cast(mistakes, tf.float32)) 

実際には、このコードはtutorialから取得されています。 このRNNネットワークへの入力は、2進数のシーケンスです。各番号は配列に入れられます。たとえば、seuquenceの形式は次のとおりです。
[[1],[0],[0],[1],[1],[0],[1],[1],[1],[0]] 入力の形状は、バッチサイズ、シーケンスサイズ、埋め込みサイズの[なし、10,1]です。動的RNNは、可変入力形状を受け入れることができるので、次のように今、私は、コードを変更:

data = tf.placeholder(tf.float32, [None, None,1]) 

基本的に、私は可変長配列を使用する(同じバッチ内のすべての配列についてのコースと同じ長さが、間で異なりますバッチ)。私は2番目の次元がget_shape()[0]で使用することはできませんNone、であることを理解し

Traceback (most recent call last): 
    File "rnn-lstm-variable-length.py", line 48, in <module> 
    last = tf.gather(val, int(val.get_shape()[0]) - 1) 
TypeError: __int__ returned non-int (type NoneType) 

:しかし、それはエラーがスローされます。しかし、RNNは一般的に可変のlenth入力を受け入れるため、これを克服する方法が必要であると私は信じています。 どうすればいいですか?

+0

この[ブログ](https://danijar.com/variable-sequence-lengths-in-tensorflow/)の記事をチェックしてください。 – TheM00s3

+0

あなたはそれが正しいと確信していますか? 'sequence = tf.placeholder(tf.float32、[None、max_length、frame_size])'を使用します。これは、シーケンス長が固定であることを意味します。 – lenhhoxung

+1

なんらかの理由で、私は実際には動的な長さではなく、埋め込まれているという印象を持っています。 –

答えて

0

tf.gatherはテンソルを想定しているため、valの形状の場合、tf.shape(val)を使用すると、実行時に計算されるテンソルを得ることができます。 tf.gather(val, tf.shape(val)[0] - 1)

3

tl; drtf.batch(..., dynamic_pad=True)を使用してデータをバッチしてみてください。


@chris_andersonさんのコメントは正しくありません。最終的に、あなたのネットワークがで動作するように数字の密行列を必要としhyperrectanglesに可変長データを変換するための戦略のカップルがあります:固定サイズのすべてのバッチが(例えば言って500項目の最大長さを想定し

  1. パッド各バッチの各項目は500にパディングされています)。この戦略については何も動的ではありません。
  2. バッチ内の最長アイテムの長さ(動的パディング)にパッディングごとのバッチを適用します。
  3. 長さに基づいてバケットを入力し、バッチごとにパディングを適用します。これは#2と同じですが、全体的なパディングが少なくなっています。

あなたも使用できるother strategiesがあります。このバッチ処理を行うには

、あなたが使用します。

  1. tf.train.batch - デフォルトでは、パディングしません、あなたはそれを自分で実装する必要があります。
  2. tf.contrib.training.bucket_by_sequence_length

  • tf.train.batch(..., dynamic_pad=True)
  • は、私はあなたにも tf.nn.dynamic_rnnの使用で混乱している疑いがあります。 dynamicdynamic_rnnであることは、TensorFlowがネットワークの反復部分を展開する方法を指していることに注意することが重要です。 tf.nn.rnnでは、グラフ内で静的に繰り返しが実行されます(内部ループはなく、グラフ作成時に展開されます)。ただし、 dynamic_rnnでは、TensorFlowは実行時にグラフ内で反復処理するために tf.while_loopを使用します。動的パディングを使用するには、動的アンローリングを使用する必要がありますが、自動的には行いません。

    +1

    私の問題は異なります。実際には、バッチ内のすべてのアイテムのシーケンス長は同じです。ただし、その長さは不明であり、バッチ間では異なります。したがって、入力データのプレースホルダーの形状を割り当てることはできません。後で 'tf.gather(val、int(val.get_shape()[0]) - 1)'の中の[batch_size、None、None]を使うと、エラー 'TypeError:__int__が返されます。 ) ' – lenhhoxung

    +1

    ああ、' tf.gather'はテンソルを予期しているので、実行時に計算されたテンソルを 'val'の形で得るには' tf.shape(val) 'を使うことができます。 'tf.gather(val、tf.shape(val)[0] - 1)'である。 –

    +0

    正解、私は試しただけで動作します。このコメントで答えを置き換えると、私はそれを受け入れます。どうもありがとう。 – lenhhoxung

    関連する問題