普通的DNN和CNN容易学,但是在LSTM的学习上花了几天时间也没搞懂,今天的学习懂了一点点用法。
测试了:
- LSTM处理MNIST数据集
- 股票价格预测方法1:基于昨天的最高价
- 股票价格预测方法2:基于今天的多指标参数
下面的rnn来自(static_rnn要用到):
fromtensorflow.contribimportrnn
最难理解的是shape问题。
首先是输出输入的Placeholder
Input_size和output_size是指输出和输出数据的维度,比如我们的PPG问题,希望用原始信号的9各特征量(from ACC & PPG)计算出1个结果(HR),,则Input_size和output_size分别为9和1。
我觉得最最难理解的一个参数是 time_step,它表示我们一次喂给LSTM模型的时间步数。比如time_step设置为10,则在前述PPG问题中:求第10s的心率,我们要使用第1~10s共10s的数据作为输入;求第11s的心率,我们要使用第2~11s共10s的数据作为输入。数据数据的尺寸为Bacth_size * time_step * input_size。
然后看BasicLSTMCell
layers是指BasicLSTMcell的重复数量,越多模型越复杂。
BasicLSTMCell中,我们要设置的主要参数只有一个num_units。源代码说明为num_units:int,ThenumberofunitsintheLSTMcell。这个参数应该表征模型的复杂度,可以随便设置,具体含义有待进一步理解。
x的准备
见到了两种方法
Unstacktogetalistof'time_step'tensorsofshape(batch_size,input_size)
直接unstack方法,原来的shape为(bacth_size , time_step,input_size);
输出shape为(time_step, batch_size,input_size)
这种方法后面跟的是rnn.static_rnn(….)
第二种方法如下
这种方法后面跟的是tf.nn.dynamic_rnn(…)
理解之前,先看看权重
(图中rnn_unit就是前面说的num_units)
1. 在reshape一步,(bacth_size , time_step, input_size)的X被转化为input,其shape为(bacth_size * time_step , input_size)
2. matmul一步,算得input_rnn的shape为(bacth_size * time_step ,num_units)
3. 最后reshape一步,尺寸变为(bacth_size, time_step,num_units)
可见两种方法结果不一样,这是不是与static_rnn和dynamic_rnn有关,有待进一步理解。经测试,果然与这个静态和动态有关,下面将详述。
再补充:第二种方法关键理解它的shape,其实前面预处理阶段的那个w_in和biase_in的作用是增加了一个普通层而已,将input_size转换成了num_units.
建模中模型的输出
前面也说了,有两种方法
结论吧:
1. 对static_rnn,输入为time_step长度的‘list',总shape为
(time_step, batch_size,input_size)。
输出shape为(time_step,batch_size,num_units)
states的shape为(2,batch_size, num_units)
1. 对dynamic_rnn,输入shape为(bacth_size, time_step,num_units)
输出shape为(bacth_size,time_step,num_units)
States的shape为(2,bacth_size,num_units)
输出
静态rnn
输出logits的shape为(batch_size,output_size)
动态rnn
则pred的shape为(bacth_size*time_step, output_size)
评价loss
静态相当于只考虑每一串time_step的最后一点,这个更符合我的直观感觉。
动态则是对整串time_step都要管,因此需要对trian_y进行折叠预处理。
评价一下:
看例子被绕得晕晕呼呼的,原因就是这个动态和静态rnn存在很多不同的地方。我觉得把shape搞懂了,就等于基本搞懂用法了。
我们回头再取读这篇博客,就能理解了。
这里还讲了:
对dynamic_rnn,所以我们需要tf.transpose(outputs, [1, 0, 2]),这样就可以取到最后一步的output。
所以loss的评价也可以像static_rnn那样了。
再看看这篇博客,它讲了dynamic_rnn的一个优点,我还没有搞懂。
更正前面的一个错误:
对static_rnn,输入的shape为(time_step, batch_size, anything);
dynamic_rnn,输入shape为(batch_size,time_step, anything)。
前面误导了,其实最后一个维度可以是任何东西。
还有一个有趣的话题。
就是
cell = rnn.BasicLSTMCell(num_units = num_hidden, forget_bias=1.0)
# cells = rnn.MultiRNNCell([cell] * 2) # 这样写时,必须input_size == num_hidden # method 1
cells = rnn.MultiRNNCell([rnn.BasicLSTMCell(num_hidden),rnn.BasicLSTMCell(num_hidden)]) # method 2
如注释,method1时,必须满足 输入数据的最后一个维度 == num_hidden
method2则没有这个要求。
还有即使满足了相等要求时,两种方式也是不一样的,具体请用tensorboard画图测试吧