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)
4
如何使用tf的重用 .
class Model():
def __init__(self,batch_size,reuse)
self.batch_size = batch_size
self.reuse = reuse
self.input_x = tf.placeholder(.....)
self.input_y = tf.placeholder(.....)
def inference(self)
with tf.variable_scope('xxx',reuse=self.reuse)
...
cell = tf.contrib.rnn.LSTMCell(xxx,reuse=self.reuse)
init_state = cell.zero_state(self.batch_size, dtype=tf.float32)
...
def train_op(self):
....
if __name__ == '__main__':
train_model = model(batch=128,reuse=False)
test_model = model(batch=1,reuse=True)
with tf.Session() as sess:
sess.run(train_model.train_op,feed_dict={...})
sess.run(test_model.prediction,feed_dict={...})
3 回答
我已经解决了同样的问题 . 您需要处理两个问题 . 第一种方法是将批量大小和步长调整为1.您可以通过将输入序列中的批次和长度尺寸设置为无来轻松完成此操作 . 即[无,无,128],128代表128个ascii字符(尽管你可能使用较少,因为你可能只需要一个字符的子集 . )
处理初始状态是最棘手的 . 这是因为您需要在对session.run()的调用之间保存它 . 由于num_steps为1,因此在每个步骤开始时将其初始化为零 . 我建议做的是允许初始状态作为占位符传递并从session.run()返回 . 这样,模型的用户可以在批次之间继续当前状态 . 最简单的方法是确保对于您使用的每个RNN,state_is_tupel都设置为False,您只需从动态RNN函数中获取最终状态张量 .
我个人不喜欢将state_is_tupel设置为False,因为它已被弃用,所以我编写了自己的代码来展平状态tupel . 以下代码来自我的项目以生成声音 .
它使用以下两个功能,这些功能应该适用于任何类型的RNN,尽管我只使用此模型进行了测试 .
最后在我的生成函数中,看看我如何管理隐藏状态
s
.如何使用tf的重用 .
当然,它看起来像在tf图中定义2分支,并且可能看起来不是很好 . 但是如果你不想传递RNN Cell的init_state,那就是一种方式 .
如 chasep255 解决方案中所述,两个棘手的部分是:
initial_state
和batch_size
&sequence lenght
.First tricky part:
如果我们将
batch_size
和sequence len
设置为None
,我们可以在推理期间更改它 . 我们的第一步是将输入形状定义为[None, None]
:Second tricky part:
下一步是定义动态
initial_state
. 对于这部分,如 chasep255 解决方案中所述,我们可以使用placeholder
,其中我们自己将zero_state
传递给 RNN . 为此,我使用tf.shape API根据输入序列获取不同的batch size
(在我的情况下:self.inp
):现在在训练中,我跑两次
sess.run()
. First ,用零值填充initial_state . 为此,我使用了一个大小为[training_batch_size * hidden_lstm_size]
的数组,其值为零,以将其传递给placeholder
. Second ,我用placeholder
再次使用传递状态到下一个时间步:在推理中,我们可以做同样的事情 . 这次我们填充
initial_state
,其值为零[1 * 1]
. 我们的推理部分是:查看完整代码here .