tensorflow代码学习:lstm数据格式

RNN是什么样子呢?网上一大堆我就不重复了,我这里大致画了一个展开形式的
这里写图片描述
那输入是什么样子呢?比如一句话有趣的灵魂重两百斤,计算机不认识字的,只认识数字。我们将每个字按照字典的位置编码,假如字典有1000个字,这个字再字典的第100个位置,在字典的第107个位置,依次类推,我们可以将这句话编码成(我瞎写的)

[100,107,109,111,245,345,567,789,999]

这样就相当于一个样本。假如有很多这样的话,长短不一,我们就可以得到很多个这样的编码

[1,101,9]
[7,77,777,177,377]
[100,107,109,111,245,345,567,789,999]

如果我们是以单个字输入,每一个输入就是一个数字 n _ i n p u t = 1 n\_input=1 n_input=1相当于输入神经只有一个,我们也可以对单个字进行one-hot编码,每个字都对应了一个1000维的向量,这个向量上相应的位置为1,例如,“我”在字典的第1个位置,“你”在字典的第2个位置,那么

-> [1,0,0,0,0,other is zero]-> [0,1,0,0,0,other is zero]

以此类推,这样输入就是一个向量 n _ i n p u t = 1000 n\_input=1000 n_input=1000,输入就有1000个神经元。
如果我们以一句话为一个样本,**“有趣的灵魂重两百斤”这句话有8个字,依次输入这8个字,即8个1000维的向量依次输入RNN中,此时 n _ s t e p s = 8 n\_steps=8 n_steps=8“我爱你”**这句话只有3个字,这个样本输入只需要循环3次,即 n _ s t e p s = 3 n\_steps=3 n_steps=3,如果用的是同一个字典 n _ i n p u t = 1000 n\_input=1000 n_input=1000
这些一个个样本和在一起我们可以作为一个batch,当然样本的输入神经元肯定需要一致的,即使单个字都要编码成相同的长度,不能一个样本的字是1000维,另一个样本的字编码成500维,这样输入就对不上了。但是样本的长度肯定是会有长短不一的,这个时候就需要在短的样本后面补一些PAD,使其和长的一样长。下面给出了batch的大致样子。

这里写图片描述

那么训练的时候数据是怎么输进去的呢?

这里写图片描述
每次输入数据的大小为 s h a p e = ( b a t c h , n _ i n p u t ) shape=(batch,n\_input) shape=(batch,n_input),总共需要输入 n _ s t e p s n\_steps n_steps次。写个伪代码

x_input = [batch,n_steps,n_input] #先将数据解压成输入格式
tmp = []
for i in range(x_input.shape[1]): #x_input.shape[1]=n_steps
	tmp.append(x_input[:,i,:])
#tmp -> [[batch,n_input],[batch,n_input]...] -> len(tmp)=n_steps
#tmp.shape -> [n_steps, batch, n_input]
outputs = [] #保存每次的输出结果
state = cell.zero_state()
for x in tmp: # x -> [batch,n_input],循环n_steps次
	output,state = cell(x,state)
	outputs.append(output) #outputs -> [y_1,y_2,...y_steps]
return outputs,state

上面这段伪代码,其实就是两个步骤,解压数据,输入rnn,tensorflow已经帮我们写好了

x_input = [batch,n_steps,n_input]
x_input = tf.unstack(x_input,n_steps,axis=1) #解压数据
outputs,state = tf.nn.static_rnn(cell,x_input) #输入rnn

下面这个是数据解压函数

tf.unstack(
    value,
    num=None,
    axis=0,
    name='unstack'
)

Unpacks num tensors from value by chipping it along the axis dimension. If num is not specified (the default), it is inferred from value’s shape. If value.shape[axis] is not known, ValueError is raised.

For example, given a tensor of shape (A, B, C, D);

  • **If axis == 0 then the i’th tensor in output is the slice value[i, :, :, :] and each tensor in output will have shape (B, C, D). **
  • **If axis == 1 then the i’th tensor in output is the slice value[:, i, :, :] and each tensor in output will have shape (A, C, D). **

rnn的输入函数

tf.nn.static_rnn(
    cell,
    inputs,
    initial_state=None,
    dtype=None,
    sequence_length=None,
    scope=None
)
  • cell: An instance of RNNCell.
  • inputs: A length T list of inputs, each a Tensor of shape [batch_size, input_size], or a nested tuple of such elements.
  • initial_state: (optional) An initial state for the RNN. If cell.state_size is an integer, this must be a Tensor of appropriate type and shape [batch_size, cell.state_size]. If cell.state_size is a tuple, this should be a tuple of tensors having shapes [batch_size, s] for s in cell.state_size.
  • dtype: (optional) The data type for the initial state and expected output. Required if initial_state is not provided or RNN state has a heterogeneous dtype.
  • sequence_length: Specifies the length of each sequence in inputs. An int32 or int64 vector (tensor) size [batch_size], values in [0, T).
  • scope: VariableScope for the created subgraph; defaults to “rnn”.

对我们来说主要就是输入,可以看到要求输入是一个list,list中的每个元素的shape是 [ b a t c h _ s i z e , i n p u t _ s i z e ] [batch\_size,input\_size] [batch_size,input_size],这个list的长度其实就是 n _ s t e p s n\_steps n_steps,即
x _ i n p u t . s h a p e = ( n _ s t e p s , b a t c h , n _ i n p u t ) y _ o u t p u t . s h a p e = ( n _ s t e p s , b a t c h , n _ h i d d e n ) x\_input.shape=(n\_steps,batch,n\_input)\\ y\_output.shape=(n\_steps,batch,n\_hidden) x_input.shape=(n_steps,batch,n_input)y_output.shape=(n_steps,batch,n_hidden)

实际中,尤其是自然语言,我们输入的句子很多时候是长短不一的,也就是 n _ s t e p s n\_steps n_steps是不一样的,这可怎么办呢?
标准的rnn会创建一个指定长度的静态的计算图,如果我们的 n _ s t e p s n\_steps n_steps是固定长度200,那么就会创建一个长度为200的静态RNN,你想输入大于200的序列就不行,tensorflow提供了dynamic_rnn。下面是一个引用解释为何会不同

在每一个train step,传入model的是一个batch的数据(这一个batch的数据forward得到predictions,计算loss,backpropagation更新参数),这一个batch内的数据一定是padding成相同长度的。那么,如果可以只在一个batch内部进行padding,例如一个batch中数据长度均在6-10这个范围内,就可以让这个batch中所有数据pad到固定长度10,而整个dataset上的数据最大长度很可能是100,这样就不需要让这些数据也pad到100那么长,白白浪费空间。所以dynamic_rnn实现的功能就是可以让不同迭代传入的batch可以是长度不同数据,但同一次迭代一个batch内部的所有数据长度仍然是固定的。例如,第一时刻传入的数据shape=[batch_size, 10],第二时刻传入的数据shape=[batch_size, 12],第三时刻传入的数据shape=[batch_size, 8]等等。但是rnn不能这样,它要求每一时刻传入的batch数据的[batch_size, max_seq],在每次迭代过程中都保持不变。这样不就必须要求全部数据都要pad到统一的max_seq长度了吗?是的,但也有个折中办法。——将数据集的sequence length做个初步统计,看会落在哪几个区间段内。然后根据区间段将数据进行归类,也就是所谓的放在不同buckets中。最后用rnn为每一个buckets都创建一个sub graph。训练的时候,根据当前batch data所归属的bucket id,找到它对应的sub graph,进行参数更新(虽然是不同的sub graph,但参数是共享的。至少tensorflow中是这么实现的(≧▽≦)/王买买提

上面是对dynamic_rnn的一个解释吧,我们主要还是看数据如何输入输出。
x _ s h a p e = ( b a t c h , n _ s t e p s , n _ i n p u t ) y _ s h a p e = ( n _ s t e p s , b a t c h , n _ h i d d e n ) x\_shape=(batch,n\_steps,n\_input)\\ y\_shape=(n\_steps,batch,n\_hidden) x_shape=(batch,n_steps,n_input)y_shape=(n_steps,batch,n_hidden)
所以我们需要 t f . t r a n s p o s e ( o u t p u t s , [ 1 , 0 , 2 ] ) tf.transpose(outputs, [1, 0, 2]) tf.transpose(outputs,[1,0,2]),这样就可以取到最后一步的output


学会区分 RNN 的 output 和 state

  • 37
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值