欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LSTM输入结构

程序员文章站 2024-03-21 10:56:40
...

https://zhuanlan.zhihu.com/p/139617364

 

为了更好理解LSTM结构,必须理解LSTM的数据输入情况。仿照3通道图像的样子,在加上时间轴后的多样本的多特征的不同时刻的数据立方体如下图所示:

LSTM输入结构

三维数据立方体

 

右边的图是我们常见模型的输入,比如XGBOOST,lightGBM,决策树等模型,输入的数据格式都是这种(N*F)的矩阵,而左边是加上时间轴后的数据立方体,也就是时间轴上的切片,它的维度是(N*T*F),第一维度是样本数,第二维度是时间,第三维度是特征数,如下图所示:

LSTM输入结构

这样的数据立方体很多,比如天气预报数据,把样本理解成城市,时间轴是日期,特征是天气相关的降雨风速PM2.5等,这个数据立方体就很好理解了。在NLP里面,一句话会被embedding成一个矩阵,词与词的顺序是时间轴T,索引多个句子的embedding三维矩阵如下图所示:

LSTM输入结构

 

pytorch中定义的LSTM模型

pytorch中定义的LSTM模型的参数如下

class torch.nn.LSTM(*args, **kwargs)
参数有:
    input_size:x的特征维度
    hidden_size:隐藏层的特征维度
    num_layers:lstm隐层的层数,默认为1
    bias:False则bihbih=0和bhhbhh=0. 默认为True
    batch_first:True则输入输出的数据格式为 (batch, seq, feature)
    dropout:除最后一层,每一层的输出都进行dropout,默认为: 0
    bidirectional:True则为双向lstm默认为False

结合前面的图形,我们一个个看。

(1)input_size:x的特征维度,就是数据立方体中的F,在NLP中就是一个词被embedding后的向量长度,如下图所示:

LSTM输入结构

(2)hidden_size:隐藏层的特征维度(隐藏层神经元个数),如下图所示,我们有两个隐含层,每个隐藏层的特征维度都是5。注意,非双向LSTM的输出维度等于隐藏层的特征维度

LSTM输入结构

(3)num_layers:lstm隐层的层数,上面的图我们定义了2个隐藏层。

(4)batch_first:用于定义输入输出维度,后面再讲。

(5)bidirectional:是否是双向循环神经网络,如下图是一个双向循环神经网络,因此在使用双向LSTM的时候我需要特别注意,正向传播的时候有(Ht, Ct),反向传播也有(Ht', Ct'),前面我们说了非双向LSTM的输出维度等于隐藏层的特征维度,而双向LSTM的输出维度是隐含层特征数*2,而且H,C的维度是时间轴长度*2。

LSTM输入结构

 

喂给LSTM的数据格式

pytorch中LSTM的输入数据格式默认如下:

input(seq_len, batch, input_size)
参数有:
    seq_len:序列长度,在NLP中就是句子长度,一般都会用pad_sequence补齐长度
    batch:每次喂给网络的数据条数,在NLP中就是一次喂给网络多少个句子
    input_size:特征维度,和前面定义网络结构的input_size一致。

前面也说到,如果LSTM的参数 batch_first=True,则要求输入的格式是:

input(batch, seq_len, input_size)

刚好调换前面两个参数的位置。其实这是比较好理解的数据形式,下面以NLP中的embedding向量说明如何构造LSTM的输入。

之前我们的embedding矩阵如下图:

LSTM输入结构

如果把batch放在第一位,则三维矩阵的形式如下:

LSTM输入结构

其转换过程如下图所示:

LSTM输入结构

看懂了吗,这就是输入数据的格式,是不是很简单。

LSTM的另外两个输入是 h0  c0,可以理解成网络的初始化参数,用随机数生成即可。

h0(num_layers * num_directions, batch, hidden_size)
c0(num_layers * num_directions, batch, hidden_size)
参数:
    num_layers:隐藏层数
    num_directions:如果是单向循环网络,则num_directions=1,双向则num_directions=2
    batch:输入数据的batch
    hidden_size:隐藏层神经元个数

注意,如果我们定义的input格式是:

input(batch, seq_len, input_size)

则H和C的格式也是要变的:

h0(batc,num_layers * num_directions, h, hidden_size)
c0(batc,num_layers * num_directions, h, hidden_size)

 

LSTM的output格式

LSTM的输出是一个tuple,如下:

output,(ht, ct) = net(input)
    output: 最后一个状态的隐藏层的神经元输出
    ht:最后一个状态的隐含层的状态值
    ct:最后一个状态的隐含层的遗忘门值

output的默认维度是:

output(seq_len, batch, hidden_size * num_directions)
ht(num_layers * num_directions, batch, hidden_size)
ct(num_layers * num_directions, batch, hidden_size)

和input的情况类似,如果我们前面定义的input格式是:

input(batch, seq_len, input_size)

htct的格式也是要变的:

ht(batc,num_layers * num_directions, h, hidden_size)
ct(batc,num_layers * num_directions, h, hidden_size)

说了这么多,我们回过头来看看ht和ct在哪里,请看下图:

LSTM输入结构

output在哪里?请看下图:

LSTM输入结构

 

LSTM和其他网络组合

还记得吗,output的维度等于隐藏层神经元的个数,即hidden_size,在一些时间序列的预测中,会在output后,接上一个全连接层,全连接层的输入维度等于LSTM的hidden_size,之后的网络处理就和BP网络相同了,如下图:

LSTM输入结构

用pytorch实现上面的结构:

import torch
from torch import nn

class RegLSTM(nn.Module):
    def __init__(self):
        super(RegLSTM, self).__init__()
        # 定义LSTM
        self.rnn = nn.LSTM(input_size, hidden_size, hidden_num_layers)
        # 定义回归层网络,输入的特征维度等于LSTM的输出,输出维度为1
        self.reg = nn.Sequential(
            nn.Linear(hidden_size, 1)
        )

    def forward(self, x):
        x, (ht,ct) = self.rnn(x)
        seq_len, batch_size, hidden_size= x.shape
        x = y.view(-1, hidden_size)
        x = self.reg(x)
        x = x.view(seq_len, batch_size, -1)
        return x

当然,有些模型则是将输出当做另一个LSTM的输入,或者使用隐藏层ht,ct的信息进行建模,不一而足。

相关标签: MachineLearning