TCN网络在时序数据处理中的应用及原理解析

释放双眼,带上耳机,听听看~!
本文介绍了时间卷积网络(TCN)在时序数据处理中的应用及其基本结构和原理,包括一维卷积和零填充操作,以及TCN网络的优势和特点。

一、引言

时序数据是一种常见的数据类型,它包含了时间上连续的一系列观测值。近年来,深度学习在时序数据处理方面取得了巨大进展,时序数据建模和预测也被多个领域广泛应用,如信号处理、语音识别等。然而,传统的序列建模方法(如RNN循环神经网络、LSTM长短期记忆网络等)需要串行地对每个时刻进行计算,并且具有较大的参数量,这限制了它们在并行计算和训练效率方面的表现。

时间卷积网络( TCN ,Temporal Convolutional Network) 是一种基于卷积神经网络结构的方法,由于其可以并行地计算所有时间步中的数据,并且具有强大的建模长期依赖性能力和更少的参数量,已被广泛应用于语音识别、动作检测、时间序列分类等领域。

TCN网络在时序数据处理中的应用及原理解析

二、TCN的基本结构和原理

TCN 有两个原则:

  • 原则一: TCN 网络的输入和输出形状必须相同,以确保模型对时序数据的处理不会丢失信息。
  • 原则二: TCN 网络中的每一时刻的输出仅由该时刻及其之前的输入卷积得到,以确保其在处理序列时具有因果约束。

2.1 一维卷积(1D-CNN)和零填充(Padding)

TCN的全称是时间卷积网络,很明显,是一种对时序数据进行卷积操作的网络,那么时序数据是怎么样的,又是基于怎样的卷积操作呢?

2.1.1 时序数据

时序数据(如自然语言文本,音频波形等)作为输入到神经网络中时,通常需要进行嵌入(Embedding)操作,将其转化为一个低维向量表示,以更好地表征输入序列的语义信息。

Embedding的主要目的是将时序数据映射到一个稠密的连续向量空间中,使得相似的语义信息在该向量空间中也能够彼此接近。这样,神经网络就可以基于这些向量表示学习到输入数据的复杂语义信息,并在相似的向量表示之间进行泛化。

TCN网络在时序数据处理中的应用及原理解析

2.1.2 一维卷积(1D-CNN)

TCN所依赖的卷积操作在本质上就是一维卷积(1D-CNN)。一维卷积利用多个大小固定的卷积核与输入序列进行卷积运算来生成输出序列。卷积核的形状由输入通道数in_channelsin_channels和卷积核大小kernel_sizekernel_size共同决定,卷积核的数量则由输出通道数out_channelsout_channels决定。

经过Embedding后的时序数据的通道数由1扩展成了embedding_sizeembedding_size,对于有着in_channelsin_channels个通道的时序数据作为输入, 一维卷积使用out_channelsout_channels个大小为(in_channelsin_channels, kernel_sizekernel_size)的卷积核进行卷积操作。

TCN网络在时序数据处理中的应用及原理解析

2.1.3 零填充(Padding)

注:从此处开始,1D-CNN的输入和输出通道数默认为1,卷积核大小kernel_size默认为K。

TCN网络的第一个原则是输入和输出的形状必须相同。而在进行一维卷积操作时,假设第ii层的输入长度为LiL_i,卷积核大小为KK,则输出长度为Li+1=Li−K+1L_{i+1} = L_{i} – K + 1

为满足这个原则,TCN在使用卷积神经网络进行序列处理时,通常需要进行 Padding 操作。通过在输入序列的左侧添加一定数量(K−1K-1)的 0,实现信号维度的保持,使通过卷积和池化处理后的数据与输入数据的长度相同。

注意,在一维卷积中进行的Padding操作默认会在左右都进行填充,所以TCN进行了额外的裁剪操作。

TCN网络在时序数据处理中的应用及原理解析

2.1 因果卷积(Causal Convolutions)

TCN通过使用因果卷积满足原则二,因果卷积是一种只考虑过去时间状态的一维卷积操作。因果卷积的具体步骤如下图所示。

可以看到,因果卷积具备两个特点:

  • 只考虑过去的信息。 时刻的输出yty_t仅依赖于x0,…,xtx_0,…,x_t,而不依赖任何“未来”的输入xt+1,…,xTx_{t+1},…,x_T
  • 追溯历史信息越久远,隐藏层越多。 图中,输出层期望采集输入层的5个时间步,则需要3个隐藏层。而业务的需求往往要求采取更多的时间步,确实是“深度”学习了。

TCN网络在时序数据处理中的应用及原理解析

由于因果卷积没有循环连接,它们通常比循环神经网络(RNN)训练速度更快,尤其是应用于非常长的序列。但单纯的因果卷积还是存在传统卷积神经网络的问题,即对时间的建模长度是受限于卷积核大小的,如果要想抓去更长的依赖关系,就需要线性的堆叠很多的层。为解决这个问题,TCN使用扩展卷积(Dilated Convolutions)以指数级地增加感受域,而不会大大增加计算成本。

2.3 扩展卷积(Dilated Convolutions)

扩展卷积是一种在因果卷积基础上进行的卷积操作,它将卷积核的采样间隔(跨度)扩大,使得输出的特征图具有更大的感受野和更高的表达能力。和传统卷积不同的是,扩展卷积类似于CNN中的空洞卷积,其允许卷积时的输入存在间隔采样,采样率受超参数 Dilation控制,指的是做卷积操作时kernel里面的元素之间的下标间隔。

扩展卷积的原理如图所示,其中蓝色圆表示的是当前卷积的输入时刻步,橙色圆表示的是当前卷积的输出时间步,白色圆表示的是Padding,黑色箭头表示输入和输出的连接方式。

可以看到,扩展卷积具备三个特点:

  • 同因果卷积相同的特性,只考虑过去的信息。
  • 同空洞卷积相同的特性,每一层对上一层信息的提取,都是跳跃式的,且逐层dilation以2的指数增长
  • 每一层扩展卷积都需要做Padding(通常情况下补0),以此保持输入和输出的 维度 大小一致,Padding的大小为:padding = (K−1)∗dilationpadding = (K-1)*dilation

TCN网络在时序数据处理中的应用及原理解析

2.4 残差连接(Residual Connections)

扩展卷积提高了因果卷积网络的扩展性,但TCN的感受野仍受网络深度nn、卷积核大小KK和扩展因子dilationdilation这三个参数的影响。即使使用扩展卷积在一定程度上优化了因果卷积的网络层数问题,但仍然需要较多的层数,这种大而深的网络模型的稳定性尤为重要。比如对于预测可能依赖于大小为2122^{12}的历史和高维输入序列的情况,需要一个至少有12层的TCN网络,且每层都包含多个卷积核用于特征提取。虽然增加网络深度可以提取更抽象、语义化的特征,但网络深度的增加也会带来梯度问题(梯度消失或梯度爆炸)和网络退化问题。

为解决上述问题,TCN对每个权重向量都进行归一化,并使用ReLU非线性激活函数和Dropout正则化,同时在设计中加入了残差连接(每两层扩展卷积进行一次残差连接),如图所示。

  • ReLU激活函数和Dropout正则化不仅可以帮助网络在训练时更快收敛,还可以避免梯度消失的问题。
  • 残差连接能够保持信息流的一致性,并帮助网络学习恒等映射,从而进一步提高网络的性能和泛化能力,减弱网络退化的问题。

需要注意的是,各层TCN的输入和输出的通道数可能会不一致,所以需要使用一个额外的1×1卷积,并逐时间步相加⊕oplus ,以得到和输出相同形状的张量。

TCN网络在时序数据处理中的应用及原理解析

三、TCN模型的PyTorch实现

原论文作者代码:github.com/locuslab/TC…

# 定义一个1-D卷积层的截断模块,主要用于去除sequence右边的padding
class Crop1d(nn.Module):
    def __init__(self, crop_size):
        super(Crop1d, self).__init__()
        self.crop_size = crop_size  # 输入需要被裁剪的序列长度

    def forward(self, sequence):
        return sequence[:, :, :-self.crop_size].contiguous()  # 裁剪输入,返回截断后的序列
        
# 定义用于时间序列预测的1-D卷积神经网络
class TemporalBlock(nn.Module):
    def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2):
        super(TemporalBlock, self).__init__()

        # 定义两个卷积层,对权重进行规范化
        self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))  # 第一层卷积层
        self.crop1 = Crop1d(padding)  # 第一层卷积层后面的截取模块
        self.relu1 = nn.ReLU()  # 第一层卷积的激活函数
        self.dropout1 = nn.Dropout(dropout)  # 第一层卷积的dropout层

        self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))  # 第二层卷积层
        self.crop2 = Crop1d(padding)  # 第二层卷积层后面的截取模块
        self.relu2 = nn.ReLU()  # 第二层卷积的激活函数
        self.dropout2 = nn.Dropout(dropout)  # 第二层卷积的dropout层

        # 将两个卷积层、截取模块、激活函数和dropout层按照顺序放入一个新的模型中,并作为TimeBlock的网络模型
        self.net = nn.Sequential(self.conv1, self.crop1, self.relu1, self.dropout1,
                                 self.conv2, self.crop2, self.relu2, self.dropout2)

        # 如果输入和输出的特征通道数不同,定义1x1的卷积层进行通道数的转换
        self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
        self.relu = nn.ReLU()
        self.init_weights()  # 初始化模型参数

    # 对模型的参数进行初始化
    def init_weights(self):
        self.conv1.weight.data.normal_(0, 0.01)
        self.conv2.weight.data.normal_(0, 0.01)
        if self.downsample is not None:
            self.downsample.weight.data.normal_(0, 0.01)

    # 前向传播计算
    def forward(self, x):
        out = self.net(x)  # 对输入的x进行卷积操作,并通过relu和dropout层进行处理
        res_part = x if self.downsample is None else self.downsample(
            x)  # 如果输出的通道数和输入的通道数不一致,则需要定义一个1x1的卷积层进行通道数转换,这里将res_part指定为输入x或转换后的输出结果。
        res = out + res_part  # 使用相加的方式进行残差连接
        return self.relu(res)  # 通过激活函数处理后返回
        
# 定义用于时间序列预测的卷积神经网络模型
class TemporalConvNet(nn.Module):
    # num_inputs是一个列表,其长度代表TemporalBlock的层数,值表示输入序列的通道数(特征维度)。
    # out_channels是一个列表,其长度代表TemporalBlock的层数,值表示每个TemporalBlock中输出的通道数(特征维度)。
    # kernel_size是卷积核的大小,默认为2。
    def __init__(self, in_channels, out_channels, kernel_size=2, dropout=0.2):
        super(TemporalConvNet, self).__init__()
        layers = []
        num_levels = len(out_channels)
        # 使用for循环,定义多个TemporalBlock模块,并按序添加到网络结构中
        for i in range(num_levels):
            dilation_size = 2 ** i  # 逐层dilation以2的指数增长
            in_channel = in_channels[i]
            out_channel = out_channels[i]
            layers += [TemporalBlock(in_channel, out_channel, kernel_size, stride=1, dilation=dilation_size,
                                     padding=(kernel_size - 1) * dilation_size, dropout=dropout)]
        self.network = nn.Sequential(*layers)

    # 模型前向计算,按顺序执行各模块的前向计算
    def forward(self, x):
        return self.network(x)

四、总结

TCN在时序数据建模方面具有许多优点和应用前景。它采用了因果卷积和扩展卷积来处理序列化数据,同时利用残差连接提升模型的准确性和训练速度。相对于传统的循环神经网络和长短时记忆网络,TCN具有并行计算能力、参数较少以及无门限结构等优点。在实际应用中,TCN在金融、信号处理、文本分类、视频分类等领域都有着非常广泛的应用。

五、参考

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

Photoshop 2023 Beta发布:AI绘图功能大幅升级

2023-11-23 21:22:14

AI教程

ACL 大会论文解读:Text-to-Table 任务及其应用场景

2023-11-23 21:30:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索