Main Content

本页的翻译已过时。点击此处可查看最新英文版本。

长短期记忆网络

本主题说明如何使用长短期记忆 (LSTM) 网络处理分类和回归任务的序列和时序数据。有关如何使用 LSTM 网络对序列数据进行分类的示例,请参阅使用深度学习进行序列分类

LSTM 网络是一种循环神经网络 (RNN),可以学习序列数据的时间步之间的长期依存关系。

LSTM 网络架构

LSTM 网络的核心组件是序列输入层和 LSTM 层。序列输入层将序列或时序数据输入网络中。LSTM 层学习序列数据的时间步之间的长期相关性。

下图说明用于分类的简单 LSTM 网络的架构。该网络从一个序列输入层开始,后跟一个 LSTM 层。为了预测类标签,该网络的末尾是一个全连接层、一个 softmax 层和一个分类输出层。

下图说明用于回归的简单 LSTM 网络的架构。该网络从一个序列输入层开始,后跟一个 LSTM 层。该网络的末尾是一个全连接层和一个回归输出层。

下图说明用于视频分类的网络的架构。要将图像序列输入到网络,请使用序列输入层。要使用卷积层来提取特征,也就是说,要将卷积运算独立地应用于视频的每帧,请使用一个序列折叠层,后跟一个卷积层,然后是一个序列展开层。要使用 LSTM 层从向量序列中学习,请使用一个扁平化层,后跟 LSTM 层和输出层。

分类 LSTM 网络

要创建针对“序列到标签”分类的 LSTM 网络,请创建一个层数组,其中包含一个序列输入层、一个 LSTM 层、一个全连接层、一个 softmax 层和一个分类输出层。

将序列输入层的大小设置为输入数据的特征数量。将全连接层的大小设置为类的数量。您不需要指定序列长度。

对于 LSTM 层,指定隐含单元的数量和输出模式 'last'

numFeatures = 12;
numHiddenUnits = 100;
numClasses = 9;
layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,'OutputMode','last')
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

有关说明如何针对“序列到标签”分类训练 LSTM 网络和对新数据进行分类的示例,请参阅使用深度学习进行序列分类

要针对“序列到序列”分类创建一个 LSTM 网络,请使用与“序列到标签”分类相同的架构,但将 LSTM 层的输出模式设置为 'sequence'

numFeatures = 12;
numHiddenUnits = 100;
numClasses = 9;
layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,'OutputMode','sequence')
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

回归 LSTM 网络

要针对“序列到单个”回归创建一个 LSTM 网络,请创建一个层数组,其中包含一个序列输入层、一个 LSTM 层、一个全连接层和一个回归输出层。

将序列输入层的大小设置为输入数据的特征数量。将全连接层的大小设置为响应的数量。您不需要指定序列长度。

对于 LSTM 层,指定隐含单元的数量和输出模式 'last'

numFeatures = 12;
numHiddenUnits = 125;
numResponses = 1;

layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,'OutputMode','last')
    fullyConnectedLayer(numResponses)
    regressionLayer];

要针对“序列到序列”回归创建一个 LSTM 网络,请使用与“序列到单个”回归相同的架构,但将 LSTM 层的输出模式设置为 'sequence'

numFeatures = 12;
numHiddenUnits = 125;
numResponses = 1;

layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,'OutputMode','sequence')
    fullyConnectedLayer(numResponses)
    regressionLayer];

有关说明如何针对“序列到序列”回归训练 LSTM 网络和对新数据进行预测的示例,请参阅使用深度学习进行“序列到序列”回归

视频分类网络

要针对包含图像序列的数据(如视频数据和医学图像)创建一个深度学习网络,请使用序列输入层指定图像序列输入。

要使用卷积层来提取特征,也就是说,要将卷积运算独立地应用于视频的每帧,请使用一个序列折叠层,后跟一个卷积层,然后是一个序列展开层。要使用 LSTM 层从向量序列中学习,请使用一个扁平化层,后跟 LSTM 层和输出层。

inputSize = [28 28 1];
filterSize = 5;
numFilters = 20;
numHiddenUnits = 200;
numClasses = 10;

layers = [ ...
    sequenceInputLayer(inputSize,'Name','input')
    
    sequenceFoldingLayer('Name','fold')
    
    convolution2dLayer(filterSize,numFilters,'Name','conv')
    batchNormalizationLayer('Name','bn')
    reluLayer('Name','relu')
    
    sequenceUnfoldingLayer('Name','unfold')
    flattenLayer('Name','flatten')
    
    lstmLayer(numHiddenUnits,'OutputMode','last','Name','lstm')
    
    fullyConnectedLayer(numClasses, 'Name','fc')
    softmaxLayer('Name','softmax')
    classificationLayer('Name','classification')];

将这些层转换为一个层次图,并将序列折叠层的 miniBatchSize 输出连接到序列展开层的对应输入。

lgraph = layerGraph(layers);
lgraph = connectLayers(lgraph,'fold/miniBatchSize','unfold/miniBatchSize');

有关说明如何针对视频分类训练深度学习网络的示例,请参阅使用深度学习对视频进行分类

更深的 LSTM 网络

您可以通过在 LSTM 层之前插入具有输出模式 'sequence' 的额外 LSTM 层来加大 LSTM 网络的深度。为了防止过拟合,可以在 LSTM 层后插入丢弃层。

对于“序列到标签”分类网络,最后一个 LSTM 层的输出模式必须为 'last'

numFeatures = 12;
numHiddenUnits1 = 125;
numHiddenUnits2 = 100;
numClasses = 9;
layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits1,'OutputMode','sequence')
    dropoutLayer(0.2)
    lstmLayer(numHiddenUnits2,'OutputMode','last')
    dropoutLayer(0.2)
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

对于“序列到序列”分类网络,最后一个 LSTM 层的输出模式必须为 'sequence'

numFeatures = 12;
numHiddenUnits1 = 125;
numHiddenUnits2 = 100;
numClasses = 9;
layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits1,'OutputMode','sequence')
    dropoutLayer(0.2)
    lstmLayer(numHiddenUnits2,'OutputMode','sequence')
    dropoutLayer(0.2)
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

网络层

说明

sequenceInputLayer

序列输入层向网络输入序列数据。

lstmLayer

LSTM 层学习时序和序列数据中时间步之间的长期相关性。

bilstmLayer

双向 LSTM (BiLSTM) 层学习时序或序列数据的时间步之间的双向长期相关性。当您希望网络在每个时间步从完整时序中学习时,这些相关性会很有用。

gruLayer

GRU 层学习时序和序列数据中时间步之间的相关性。

sequenceFoldingLayer

序列折叠层将一批图像序列转换为一批图像。使用序列折叠层独立地对图像序列的时间步执行卷积运算。

sequenceUnfoldingLayer

序列展开层在序列折叠后还原输入数据的序列结构。

flattenLayer

扁平化层将输入的空间维度折叠成通道维度。

wordEmbeddingLayer (Text Analytics Toolbox)

单词嵌入层将单词索引映射到向量。

分类、预测和预报

要对新数据进行分类或预测,请使用 classifypredict

LSTM 网络可以记住各次预测之间的网络状态。如果您事先没有完整的时序,或您要对一个长时序进行多次预测,则网络状态会很有用。

要对一个时序的多个部分进行预测和分类并更新网络状态,请使用 predictAndUpdateStateclassifyAndUpdateState。要在各次预测之间重置网络状态,请使用 resetState

有关如何预测序列的将来时间步的示例,请参阅使用深度学习进行时序预测

序列填充、截断和拆分

LSTM 网络支持具有不同序列长度的输入数据。当使数据通过网络时,软件会填充、截断或拆分序列,以便每个小批量中的所有序列都具有指定的长度。您可以使用 trainingOptions 中的 SequenceLengthSequencePaddingValue 名称-值对组参数来指定序列长度和用于填充序列的值。

训练网络后,在使用 classifypredictclassifyAndUpdateStatepredictAndUpdateStateactivations 函数时,使用相同的小批量大小和填充选项。

按长度对序列排序

要在填充或截断序列时减少填充或丢弃的数据量,请尝试按序列长度对数据进行排序。要按序列长度对数据进行排序,首先使用 cellfun 对每个序列应用 size(X,2) 来获得每个序列的列数。然后使用 sort 对序列长度进行排序,并使用第二个输出对原始序列重新排序。

sequenceLengths = cellfun(@(X) size(X,2), XTrain);
[sequenceLengthsSorted,idx] = sort(sequenceLengths);
XTrain = XTrain(idx);

以下各图中以条形图显示了已排序和未排序数据的序列长度。

填充序列

如果您指定序列长度 'longest',则软件会填充序列,使小批量中的所有序列具有与小批量中的最长序列相同的长度。此选项是默认选项。

下图说明将 'SequenceLength' 设置为 'longest' 的效果。

截断序列

如果您指定序列长度 'shortest',则软件会截断序列,使小批量中的所有序列具有与该小批量中的最短序列相同的长度。序列中的其余数据被丢弃。

下图说明将 'SequenceLength' 设置为 'shortest' 的效果。

拆分序列

如果将序列长度设置为整数值,则软件会将小批量中的所有序列填充为大于该小批量中最长序列长度的指定长度的最接近倍数。然后,软件将每个序列拆分为指定长度的较小序列。如果发生拆分,则软件会创建额外的小批量。

如果整个序列无法放入内存中,请使用此选项。您也可以尝试通过将 trainingOptions 中的 'MiniBatchSize' 选项设置为较低的值来减少每个小批量的序列数。

如果您将序列长度指定为正整数,则软件会在连续的迭代中处理较小的序列。网络会在拆分的序列之间更新网络状态。

下图说明将 'SequenceLength' 设置为 5 的效果。

指定填充方向

填充和截断的位置会影响训练、分类和预测准确度。请尝试将 trainingOptions 中的 'SequencePaddingDirection' 选项设置为 'left''right',看看哪个最适合您的数据。

由于 LSTM 层一次处理一个时间步的序列数据,当层 OutputMode 属性为 'last' 时,最终时间步中的任何填充都会对层输出产生负面影响。要填充或截断左侧的序列数据,请将 'SequencePaddingDirection' 选项设置为 'left'

对于“序列到序列”网络(当每个 LSTM 层的 OutputMode 属性为 'sequence' 时),前几个时间步中的任何填充都会对较早时间步的预测产生负面影响。要填充或截断右侧的序列数据,请将 'SequencePaddingDirection' 选项设置为 'right'

下图说明左侧和右侧的填充序列数据。

下图说明左侧和右侧的截断序列数据。

归一化序列数据

要在训练时使用以零为中心的归一化自动对训练数据调整中心位置,请将 sequenceInputLayerNormalization 选项设置为 'zerocenter'。您也可以通过首先计算所有序列的每个特征的均值和标准差来归一化序列数据。然后,对于每个训练观测值,减去均值并除以标准差。

mu = mean([XTrain{:}],2);
sigma = std([XTrain{:}],0,2);
XTrain = cellfun(@(X) (X-mu)./sigma,XTrain,'UniformOutput',false);

无法放入内存的数据

如果数据太大而无法放入内存或在读取批量数据时无法执行特定操作,请对序列、时序和信号数据使用数据存储。

要了解详细信息,请参阅使用无法放入内存的序列数据训练网络使用深度学习对无法放入内存的文本数据进行分类

可视化

通过使用 activations 函数提取激活,调查并可视化 LSTM 网络从序列和时序数据中学习到的特征。要了解详细信息,请参阅Visualize Activations of LSTM Network

LSTM 层架构

下图说明具有 C 个长度为 S 的特征(通道)的时序 X 通过 LSTM 层的流程。在图中,htct 分别表示在时间步 t 的输出(也称为隐藏状态)和单元状态

第一个 LSTM 模块使用网络的初始状态和序列的第一个时间步来计算第一个输出和更新后的单元状态。在时间步 t 上,该模块使用网络的当前状态 (ct1,ht1) 和序列的下一个时间步来计算输出和更新后的单元状态 ct

该层的状态由隐藏状态(也称为输出状态)和单元状态组成。时间步 t 处的隐藏状态包含该时间步的 LSTM 层的输出。单元状态包含从前面的时间步中获得的信息。在每个时间步,该层都会在单元状态中添加或删除信息。该层使用不同的控制这些更新。

以下组件控制层的单元状态和隐藏状态。

组件目的
输入门 (i)控制单元状态更新的级别
遗忘门 (f)控制单元状态重置(遗忘)的级别
候选单元 (g)向单元状态添加信息
输出门 (o)控制添加到隐藏状态的单元状态的级别

下图说明在时间步 t 上的数据流。该图突出显示门如何遗忘、更新和输出单元状态和隐藏状态。

LSTM 层的可学习权重包括输入权重 W (InputWeights)、循环权重 R (RecurrentWeights) 以及偏置 b (Bias)。矩阵 W、R 和 b 分别是输入权重、循环权重和每个分量的偏置的串联。这些矩阵的串联如下:

W=[WiWfWgWo],R=[RiRfRgRo],b=[bibfbgbo],

其中 i、f、g、o 分别表示输入门、遗忘门、候选单元和输出门。

时间步 t 处的单元状态由下式给出:

ct=ftct1+itgt,

其中 表示 Hadamard 乘积(向量的按元素乘法)。

时间步 t 处的隐藏状态由下式给出:

ht=otσc(ct),

其中 σc 表示状态激活函数。默认情况下,lstmLayer 函数使用双曲正切函数 (tanh) 计算状态激活函数。

以下公式说明时间步 t 处的组件。

组件公式
输入门it=σg(Wixt+Riht1+bi)
遗忘门ft=σg(Wfxt+Rfht1+bf)
候选单元gt=σc(Wgxt+Rght1+bg)
输出门ot=σg(Woxt+Roht1+bo)

在这些计算中,σg 表示门激活函数。默认情况下,lstmLayer 函数使用 σ(x)=(1+ex)1 给出的 sigmoid 函数来计算门激活函数。

参考

[1] Hochreiter, S., and J. Schmidhuber. "Long short-term memory." Neural computation. Vol. 9, Number 8, 1997, pp.1735–1780.

另请参阅

| | | | | | | | | | (Text Analytics Toolbox) |

相关主题