私はこの同じ問題を処理しました。あなたが対処する必要がある2つの問題があります。最初は、バッチサイズとステップサイズを1に調整しています。入力シーケンスのバッチと長さのディメンションをnoneに設定すると、簡単に行うことができます。つまり、128文字は128文字のASCII文字を表します(ただし、おそらく文字のサブセットのみが必要なため、おそらく文字数は少なくて済むかもしれません)。
最初の状態を扱うのが最もトリッキーです。これは、session.run()の呼び出しの間に保存する必要があるためです。あなたのnum_stepsは1であるため、各ステップの初めに0に初期化されます。私がお勧めするのは、初期状態をプレースホルダとして渡し、session.run()から返すことです。この方法で、モデルのユーザーはバッチ間で現在の状態を継続できます。これを行う最も簡単な方法は、使用しているすべてのRNNに対してstate_is_tupelがFalseに設定されていることを確認することです。そして、ダイナミックRNN関数から最終状態のテンソルを取得するだけです。
個人的にはstate_is_tupelをFalseに設定するのは嫌いです。私は自分のコードを書いて状態タプルを平坦化しました。次のコードは、サウンドを生成する私のプロジェクトからです。
batch_size = tf.shape(self.input_sound)[0]
rnn = tf.nn.rnn_cell.MultiRNNCell([tf.nn.rnn_cell.LSTMCell(self.hidden_size) for _ in range(self.n_hidden)])
zero_state = pack_state_tupel(rnn.zero_state(batch_size, tf.float32))
self.input_state = tf.placeholder_with_default(zero_state, None)
state = unpack_state_tupel(self.input_state, rnn.state_size)
rnn_input_seq = tf.cond(self.is_training, lambda: self.input_sound[:, :-1], lambda: self.input_sound)
output, final_state = tf.nn.dynamic_rnn(rnn, rnn_input_seq, initial_state = state)
with tf.variable_scope('output_layer'):
output = tf.reshape(output, (-1, self.hidden_size))
W = tf.get_variable('W', (self.hidden_size, self.sample_length))
b = tf.get_variable('b', (self.sample_length,))
output = tf.matmul(output, W) + b
output = tf.reshape(output, (batch_size, -1, self.sample_length))
self.output_state = pack_state_tupel(final_state)
self.output_sound = output
これは、このモデルでのみテストしましたが、どのタイプのRNNでも機能する次の2つの機能を使用します。私の生成機能で最後に
def pack_state_tupel(state_tupel):
if isinstance(state_tupel, tf.Tensor) or not hasattr(state_tupel, '__iter__'):
return state_tupel
else:
return tf.concat(1, [pack_state_tupel(item) for item in state_tupel])
def unpack_state_tupel(state_tensor, sizes):
def _unpack_state_tupel(state_tensor_, sizes_, offset_):
if isinstance(sizes_, tf.Tensor) or not hasattr(sizes_, '__iter__'):
return tf.reshape(state_tensor_[:, offset_ : offset_ + sizes_], (-1, sizes_)), offset_ + sizes_
else:
result = []
for size in sizes_:
s, offset_ = _unpack_state_tupel(state_tensor_, size, offset_)
result.append(s)
if isinstance(sizes_, tf.nn.rnn_cell.LSTMStateTuple):
return tf.nn.rnn_cell.LSTMStateTuple(*result), offset_
else:
return tuple(result), offset_
return _unpack_state_tupel(state_tensor, sizes, 0)[0]
私は隠された状態s
を管理する方法を参照してください。
def generate(self, seed, steps):
def _step(x, s = None):
feed_dict = {self.input_sound: np.reshape(x, (1, -1, self.sample_length))}
if s is not None:
feed_dict[self.input_state] = s
return self.session.run([self.output_sound, self.output_state], feed_dict)
seed_pad = self.sample_length - len(seed) % self.sample_length
if seed_pad: seed = np.pad(seed, (seed_pad, 0), 'constant')
y, s = _step(seed)
y = y[:, -1:]
result = [seed, y.flatten()]
for _ in range(steps):
y, s = _step(y, s)
result.append(y.flatten())
return np.concatenate(result)