万物皆可LSTM

大家好,我是XFXZ,咱今天吃顿好的(抢一下B站碳水教父徐大骚的台词),不过,咱今天,是在我的博客里吃顿好的。猪蹄镇楼。
在这里插入图片描述
这里我先声明我这篇博客的定位,属于应用篇,理论不是重点,我要全,而追求精的童鞋们可以去查其他人的博客。

什么是LSTM?

全名为长短时记忆网络,英文是Long short term memory,属于循环神经网络中非常常用和重要的一类循环层。(在我的上一篇博客上有讲过层的概念,之所以是循环层,因为神经元会在时间轴上有次序连接,而非无序无连接的全连接层神经元)
循环层
循环层
全连接层
全连接层

LSTM在深度学习中的地位?

在最近十年,大部分AI都是关于长期短期记忆(LSTM)的神经网络。世界本质上是序列性的(这其实不对,世界本质没有时间的,为了能理解这个世界,时间才存在的),而LSTM彻底改变了序列数据处理,例如语音识别、机器翻译、视频识别,联机手写识别、机器人、视频游戏、时间序列预测、聊天机器人、医疗保健应用等。到2019年,LSTM每年获得的引用量超过过去一千年间任何其他计算机科学论文。(引自:LSTM之父,深度学习元老,Jürgen Schmidhuber:2010-2020,我眼中的深度学习十年简史,https://mp.weixin.qq.com/s/vK87vUUGfjPs4Ys6V-shWw)

LSTM的应用?

遍栏众多博客与学术论文,我发现LSTM层,简直就是万金油!

1.回归,用一群结构化数据回归出一个或者多个数。

1.分类,用一群结构化数据输入,最后一层加softmax或者全连接层做分类。
3.数据特征压缩重构。自动编码机也可以用全连接层,更可以用LSTM层,形成序列自动编码机。
4.编码/解码作用。有做过自然语言处理NLP的小伙伴,肯定熟悉seq2seq结构,其可以全部为LSTM层,对输入词向量做编码和再解码,直接用途就是不同语言翻译。

LSTM的机理分析?

在这里插入图片描述
如上图,LSTM 单元是组成LSTM的基本单元,包括遗忘门,输入门,输出门。像她们一样时序串联接就可以组成LSTM层
一、我们可以从本质上分析,一个LSTM网络视为如下所示的复合函数,y是输出,x为输入,T就是你输入数据的时序长度。括号内的就是广义的记忆,有时间属性,本质上是多维时间序列数据(2维张量)。一般什么交通事故数据,没有动态性,这是单纯记录一个事故的发生地点、人数、伤亡程度等变量属性。没有任何时序信息,是不能用LSTM处理的哦。在这里插入图片描述
注意Jürgen Schmidhuber提出LSTM的目的是为了解决一个问题:LSTM以前的神经网络没有记忆,无法根据之前的输入来预测出输出。那怎么给神经网络加上记忆?记忆就是过去发生的事情,那么如果神经网络现在的输出受到过去输入的影响,是不是就可以说神经网络拥有了记忆于是就有了这样的神经网络,而普通RNN没有门式结构,容易发生梯度爆炸或梯度弥散问题。
二、从输入到输出:
在这里插入图片描述
有5种模式,这里以多对一为例。
X:数据维度[batchsize,time_step,input_dim]
Y:数据维度[batchsize,1] #return_sequences为false
batchsize就是你在输入LSTM训练每次用几个样本,time_step就是你的T,考虑的序列长度(时间轴数据点数量),input_dim就是你用的数据有几个变量。可以多对一就是把一个维度time_stepinput_dim的数据—变为一个数值。一般神经网络是把input_dim的数据(1维张量)—变为一个数值。
注意:如果你想变样本batchsize的大小输入,可以将其设为None,但此时不能直接用fit方法训练。
return_sequences为True,是一个LSTM层就会返回[batchsize,time_step,output_dim]的3维张量数据,也就是用在你想堆叠多个LSTM层的时候(如我的代码),这个参数要设为True。层函数调用时必须指定的units参数就是out_dim,一般是8,16,32,64,128,256等正整数,其实50 60 20都行。*
在这里插入图片描述
其实从应用层面,看到这里就可以了。
三、如果你还要了解具体原理,就继续看吧。
在三个门式结构中,数据流ct, ft ,it ,Ot ,ht,都是单元内张量。输入后会按照这样方式进行运算。
在这里插入图片描述
注意我图中hidden state(短期记忆ht,蓝线)和cell state(长期记忆,黄长线)的信息传递,以及最终CLEE输出其实就是ht(需要
x*t-1参与运算,和历史的Ct-1等,而Ct-1又和Ct-2等有关)在传递到下一个CELL,直到输出。图例的乘号*应该表示向量逐点乘法pointwise multiplication。当你把return_sequences设为True,你就得到了很多ht,ht-1,ht-2,ht-3…;否则只有ht。

LSTM/RNN的变种?

1.双向LSTM

本质就是堆叠两层LSTM,但是这两层LSTM的数据流分析是相反的,这样可以进一步挖掘时间依赖。尽管似乎违背记忆的概念,用未来推断过去。

2.栅格LSTM

直接接受栅格数据(图片等)的升级版LSTM。

3.GRU

就像二哈和狼,我们可以说LSTM和GRU是近亲啦。它也是循环神经网络层,参数更少,只有重置门和更新门。

4.卷积LSTM网络

卷积操作强化的LSTM,同时具备挖掘空间依赖的能力,不过多介绍

LSTM的代码实例与API调用?

这些是我写我论文时候编写的,你们可以参考(库和模型部分),基于TENSORFLOW backend 的KERAS框架。

#导入有关库
import numpy as np
import pandas as pd
import time
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties #解决中文字体无法显示
import math

import tensorflow as tf
from keras.models import Sequential,Model
from keras.layers import Dense, LSTM,TimeDistributed
import keras.backend as K
from keras.optimizers import Adam
import keras.callbacks
from keras import metrics
from keras.utils import plot_model
from keras.layers.core import Dense, Activation, Dropout
from keras.layers.normalization import BatchNormalization
#标准化、归一化
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn import model_selection
#有关参数设置
TIME_STEPS = 20
BATCH_SIZE = 500 #其实没有用到
INPUT_SIZE = 3  #
OUTPUT_SIZE = 1
CELL_SIZE = 64
LR = 0.001  

#搭建1层的LSTM的RNN网络,目前已经加深
model = Sequential()
#NOW build a multilwayer LSTM-RNN    
model.add(LSTM(activation='relu',
         batch_input_shape=(None,TIME_STEPS,INPUT_SIZE),
         output_dim=CELL_SIZE,
     return_sequences=True# True: output at all steps. False: output as last step.
          # True: the final state of batch1 is feed into the initial state of batch2
        ))
#return_sequences=True
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(LSTM(units=CELL_SIZE,activation='tanh', input_shape=(TIME_STEPS,INPUT_SIZE),return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=CELL_SIZE,activation='relu', input_shape=(TIME_STEPS,INPUT_SIZE),return_sequences=True))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(LSTM(units=OUTPUT_SIZE,activation='relu', input_shape=(TIME_STEPS,INPUT_SIZE),return_sequences=False))
#stateful=False!!!!!此时batch之间无联系要设置statefu参数l=False
# add output layer
model.add((Dense(OUTPUT_SIZE)))  #如果设置多状态输出,加TimeDistributed(Dense(OUTPUT_SIZE))
adam = Adam(LR)  #这就是把adam优化器对象实例化,万物皆可**红油**(不不不,是对象)
model.compile(optimizer=adam,loss='mae',metrics=['mse'])
sumcost=0
losthis=np.zeros([lstmx_trainrange.shape[0],3])

#绘制结构模型图
#plot_model(model,to_file='XFXZ'Slstm.png',show_shapes=False,show_layer_names=True)
#进行LSTM模型训练
losthis=np.zeros([lstmx_trainrange.shape[0],3])

##进行模型训练,使用model train on batch 方法
for each in range(lstmx_trainrange.shape[0]):   #1     
   X_batch, Y_batch,currentbatchsize = getonebatchdata(current=each,batchsize=500,
                           slicedatax=lstmx_trainrange) #这里的batchsize其实是变化的,都比500大
   cost = model.train_on_batch(X_batch, Y_batch) #目前每个batch值设置了一次,
   sumcost+=cost[0]
   if each==0:
       averagecost=cost
   else:
        averagecost=sumcost/(each*1)   #求得平均损失          
        pred = model.predict(X_batch, currentbatchsize) #预测比对
   if each % 1 == 0: #连续输出
       print('now train cost is: ', cost,'train average cost: ',(averagecost))

API参数(官方文档,可能看起来需要理解挺久,也枯燥)
通用参数
LSTM它是RNN对象的子类,RNN是它的基类。
keras.layers.RNN(cell, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False)
cell: 一个 RNN 单元实例。RNN 单元是一个具有以下几项的类:
一个 call(input_at_t, states_at_t) 方法, 它返回 (output_at_t, states_at_t_plus_1)。 单元的调用方法也可以采引入可选参数 constants, 详见下面的小节「关于给 RNN 传递外部常量的说明」。
一个 state_size 属性。这可以是单个整数(单个状态), 在这种情况下,它是循环层状态的大小(应该与单元输出的大小相同)。 这也可以是整数表示的列表/元组(每个状态一个大小)。
一个 output_size 属性。 这可以是单个整数或者是一个 TensorShape, 它表示输出的尺寸。出于向后兼容的原因,如果此属性对于当前单元不可用, 则该值将由 state_size 的第一个元素推断。
cell 也可能是 RNN 单元实例的列表,在这种情况下,RNN 的单元将堆叠在另一个单元上,实现高效的堆叠 RNN。

return_sequences: 布尔值。是返回输出序列中的最后一个输出,还是全部序列。

return_state: 布尔值。除了输出之外是否返回最后一个状态。
go_backwards: 布尔值 (默认 False)。 如果为 True,则向后处理输入序列并返回相反的序列。
stateful: 布尔值 (默认 False)。 如果为 True,则批次中索引 i 处的每个样品的最后状态将用作下一批次中索引 i 样品的初始状态。
unroll: 布尔值 (默认 False)。 如果为 True,则网络将展开,否则将使用符号循环。 展开可以加速 RNN,但它往往会占用更多的内存。 展开只适用于短序列。
input_dim: 输入的维度(整数)。 将此层用作模型中的第一层时,此参数(或者,关键字参数 input_shape)是必需的。
input_length: 输入序列的长度,在恒定时指定。 如果你要在上游连接 Flatten 和 Dense 层, 则需要此参数(如果没有它,无法计算全连接输出的尺寸)。 请注意,如果循环神经网络层不是模型中的第一层, 则需要在第一层的层级指定输入长度(例如,通过 input_shape 参数)。
输入尺寸

3D 张量,尺寸为 (batch_size, timesteps, input_dim)。

输出尺寸

如果 return_state:返回张量列表。 第一个张量为输出。剩余的张量为最后的状态, 每个张量的尺寸为 (batch_size, units)。
如果 return_sequences:返回 3D 张量, 尺寸为 (batch_size, timesteps, units)。
否则,返回尺寸为 (batch_size, units) 的 2D 张量。

特有参数
keras.layers.LSTM(units, activation=‘tanh’, recurrent_activation=‘hard_sigmoid’, use_bias=True, kernel_initializer=‘glorot_uniform’, recurrent_initializer=‘orthogonal’, bias_initializer=‘zeros’, unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False)
特有参数:
units: 正整数,输出空间的维度。
activation: 要使用的激活函数 (详见 activations)。 如果传入 None,则不使用激活函数 (即 线性激活:a(x) = x)。
recurrent_activation: 用于循环时间步的激活函数 (详见 activations)。 默认:分段线性近似 sigmoid (hard_sigmoid)。 如果传入 None,则不使用激活函数 (即 线性激活:a(x) = x)。
use_bias: 布尔值,该层是否使用偏置向量。
kernel_initializer: kernel 权值矩阵的初始化器, 用于输入的线性转换 (详见 initializers)。
recurrent_initializer: recurrent_kernel 权值矩阵 的初始化器,用于循环层状态的线性转换 (详见 initializers)。
bias_initializer:偏置向量的初始化器 (详见initializers).
unit_forget_bias: 布尔值。 如果为 True,初始化时,将忘记门的偏置加 1。 将其设置为 True 同时还会强制 bias_initializer=“zeros”。 这个建议来自 Jozefowicz et al.。
kernel_regularizer: 运用到 kernel 权值矩阵的正则化函数 (详见 regularizer)。
recurrent_regularizer: 运用到 recurrent_kernel 权值矩阵的正则化函数 (详见 regularizer)。
bias_regularizer: 运用到偏置向量的正则化函数 (详见 regularizer)。
activity_regularizer: 运用到层输出(它的激活值)的正则化函数 (详见 regularizer)。
kernel_constraint: 运用到 kernel 权值矩阵的约束函数 (详见 constraints)。
recurrent_constraint: 运用到 recurrent_kernel 权值矩阵的约束函数 (详见 constraints)。
bias_constraint: 运用到偏置向量的约束函数 (详见 constraints)。
dropout: 在 0 和 1 之间的浮点数。 单元的丢弃比例,用于输入的线性转换。
recurrent_dropout: 在 0 和 1 之间的浮点数。 单元的丢弃比例,用于循环层状态的线性转换。
implementation: 实现模式,1 或 2。 模式 1 将把它的操作结构化为更多的小的点积和加法操作, 而模式 2 将把它们分批到更少,更大的操作中。 这些模式在不同的硬件和不同的应用中具有不同的性能配置文件。
return_sequences: 布尔值。是返回输出序列中的最后一个输出,还是全部序列。
return_state: 布尔值。除了输出之外是否返回最后一个状态。
go_backwards: 布尔值 (默认 False)。 如果为 True,则向后处理输入序列并返回相反的序列。
stateful: 布尔值 (默认 False)。 如果为 True,则批次中索引 i 处的每个样品的最后状态 将用作下一批次中索引 i 样品的初始状态。
unroll: 布尔值 (默认 False)。 如果为 True,则网络将展开,否则将使用符号循环。 展开可以加速 RNN,但它往往会占用更多的内存。 展开只适用于短序列
引自 https://keras.io/zh/layers/recurrent/

LSTM的使用难点和缺点?

1.参数体量大,与同类的神经网络,如果处理一样的数据,网络深度的相同。LSTM的超参数炒鸡多,会随着隐层神经元数量爆炸性增长。相比之下GRU参数少,但是可能效果略差。

LSTM(3层)

=================================================================
input_3 (InputLayer) (None, 40, 8) 0


lstm_5 (LSTM) (None, 16) 1600


repeat_vector_3 (RepeatVecto (None, 40, 16) 0


=================================================================
Total params: 2,400
Trainable params: 2,400
Non-trainable params: 0
所以是2400/3 ,平均每层=800 个超参数

隐层神经元有16变为64个后
Layer (type) Output Shape Param #

input_3 (InputLayer) (None, 40, 8) 0


lstm_1 (LSTM) (None, 40, 64) 18688


lstm_2 (LSTM) (None, 16) 5184


repeat_vector_3 (RepeatVecto (None, 40, 16) 0


=================================================================
Total params: 24,672
Trainable params: 24,672
Non-trainable params: 0
所以平均每层=8000参数

2.理解它的张量维度转换是难点。还有个难点是timedistributed层,不用过多理解,当你要把LSTM(return_sequences=True时)和全连接层直接相连,你就要插入这个层。不然报错!

LSTM的资料链接?

视频课就看莫凡(我老师朋友的学生,已经毕业去TENCENT)的吧,讲得很好。
1.https://morvanzhou.github.io/tutorials/machine-learning/keras/2-5-RNN-LSTM-Regressor/
2.https://keras.io/zh/ 第90页左右

LSTM的学术用途与进阶展望分析?

往往现实中有很多自回归/回归问题,属于时间序列分析范畴就可以用LSTM来解决。比如股价预测,场站客流预测,交通流预测,经济产值预测;图片分类(比CNN差点)。在车辆控制,交通诱导的深度强化学习领域还有人用它进行车辆智能体的试错学习的记忆强化,优化训练过程,在DDPG的critic network和actor network范畴。

敲下黑板,我们在用LSTM的同时,更需要辩证的理解它,适合自己的才是最好。不能因为它比ARIMA HMM模型 移动平均法 新 高大上 就用,LSTM是难以解释的(不过已经有方法了。)

这一块欢迎同学留言,我就附上一些论文链接:
1.https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFDLAST2019&filename=DLDY201905024&v=MTY0NDk5ak1xbzlIWUlSOGVYMUx1eFlTN0RoMVQzcVRyV00xRnJDVVI3cWZaZVJyRnlqbFdydklJU0hQZDdHNEg=
2.https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFDLAST2019&filename=JSJK201909011&v=MTc5ODBGckNVUjdxZlplUnJGeWpsVzc3S0x6N0JaYkc0SDlqTXBvOUVaWVI4ZVgxTHV4WVM3RGgxVDNxVHJXTTE=
3.https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CMFD&dbname=CMFD201902&filename=1019099446.nh&v=MDU1NTExVDNxVHJXTTFGckNVUjdxZlplUnJGeWpsVzczTlZGMjZGN094RjlYSXFaRWJQSVI4ZVgxTHV4WVM3RGg=
4.https://www.sciencedirect.com/science/article/pii/S187705091930969X
5.https://www.sciencedirect.com/science/article/pii/S0968090X1830158X
在这里插入图片描述
参考博客链接:
https://blog.csdn.net/Geek_of_CSDN/article/details/86559464?ops_request_misc=%7B%22request_id%22%3A%22158242563619724846404799%22%2C%22scm%22%3A%2220140713.130056874…%22%7D&request_id=158242563619724846404799&biz_id=0&utm_source=distribute.pc_search_result.none-task

https://blog.csdn.net/destiny_block/article/details/89153617?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/owenfy/article/details/80022586
版权声明:本文为CSDN博主「TJXFXZ」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

发布了5 篇原创文章 · 获赞 13 · 访问量 2044

猜你喜欢

转载自blog.csdn.net/qq_34027291/article/details/104472319