偶然的机会接触到TCN这个模型,然后就自己学习了一下并尝试实现了一下,今天根据自己的理解和认识在这里总结一下,文章最后有完整的模型结构代码。
目录
2.4 残差链接(Residual Connections)
1 TCN 概况
TCN 是时域卷积网络(Temporal Convolutional Network)的简称。
1.1 对比 RNN 的区别
到目前为止,深度学习背景下的序列建模主题主要与递归神经网络架构(如 LSTM 和 GRU)有关。在许多任务中,卷积网络可以取得比 RNNs 更好的性能,同时避免了递 归模型的常见缺陷,如梯度爆炸/消失问题。
RNN 的优点:
建模长期依赖关系:由于循环连接的存在,RNN 可以很好地捕捉序列中的长期依 赖关系。它可以通过将过去的信息保持在隐藏状态中来传递上下文信息。
动态长度处理:RNN 能够处理变长的序列数据,适应输入序列长度的变化。 自然地处理时间:由于 RNN 的循环性质,它天然适应处理时间序列数据。
RNN 的缺点:
难以并行化计算:由于 RNN 在每个时间步骤上依赖前一个时间步骤的输出,导致 计算难以并行化,限制了其在大规模数据上的训练和推理效率。
梯度消失和梯度爆炸问题:在训练中,RNN 的梯度信息在传播过程中可能会出现 梯度消失或梯度爆炸的问题,这会导致训练的不稳定性。
TCN 的优点:
可并行化计算:TCN 采用卷积操作,可以进行高效的并行计算,充分利用现代硬 件加速能力,适用于大规模数据处理。
捕捉局部依赖关系:TCN 通过堆叠卷积层并增大卷积核的感受野,可以有效地捕 捉序列数据中的局部依赖关系。
稳定的梯度传播:相对于 RNN,TCN 训练中的梯度传播更稳定,不容易遇到梯度消 失或梯度爆炸的问题。
TCN 的缺点:
有限的建模能力:传统的卷积操作在局部感受野内工作,因此对于较长的序列建 模和处理长期依赖关系,可能不如 RNN 表现好。但可以通过使用深层 TCN 和膨胀卷积 等技术来扩大感受野。
1.2 TCN 特点
并行计算能力:相对于传统的循环神经网络(RNN),TCN 采用卷积操作,可以进 行高效的并行计算。这使得 TCN 在大规模数据上的训练和推理方面具有优势,能够更 好地利用现代硬件的并行计算能力。
长依赖关系建模:传统的卷积操作在局部感受野内工作,导致原始的 TCN 可能对 较长的序列数据难以捕捉长期依赖关系。然而,通过使用一些技术,如深层 TCN 和膨 胀卷积(dilated convolutions),TCN 可以扩大感受野并增加信息传递的距离,从 而更有效地捕捉和建模长期依赖关系。
多尺度信息提取:TCN 可以通过堆叠多个卷积层来提取不同尺度的特征。每个卷 积层通过不同大小的卷积核对输入进行处理,从而捕捉序列数据中的不同时间范围的 特征。这种多尺度信息提取能力使得 TCN 对序列数据中的局部依赖关系更加敏感。
输入长度灵活性:TCN 与传统的 RNN 相比,更灵活地处理变长的输入序列。TCN 的输入可以是固定长度的序列数据,也可以是可变长度的序列数据。这方面的灵活性 使得 TCN 在处理不同长度的序列数据时更加便捷。
适用于各种序列建模任务:由于 TCN 的并行计算能力和长依赖关系建模能力,它 适用于各种序列建模任务,如语音识别、自然语言处理、动作识别、时间序列预测等。 它在某些任务中的性能表现可能与传统的 RNN 相当甚至更好。
2 TCN 结构
它由具有相同输入和输出长度的扩张的、因果的 1D 卷积层组成。
2.1 1D 卷积
一维卷积分为:full 卷积、same 卷积和 valid 卷积
全卷积保留了输入序列的所有信息但计算代价较高,同卷积保留了输入序列的所 有信息且输出长度相同但计算代价相对较高,有效卷积计算代价较低但可能会丢失输 入序列的边界信息。根据具体的任务和需求,可以选择适合的卷积方式。
以一个长度为 5 的一维张量 I 和长度为 3 的一维张量 k(卷积核)为例
一维 full 卷积
Full 卷积的计算过程是:K 沿着 I 顺序移动,每移动到一个固定位置,对应位置 的值相乘再求和,计算过程如下:
将得到的值依次存入一维张量 Cfull,该张量就是 I 和卷积核 K 的 full 卷积结果, 其中 K 卷积核或者滤波器或者卷积掩码,卷积符号用符号*表示,记 Cfull=I*K
一维 same 卷积
卷积核 K 都有一个锚点,然后将锚点顺序移动到张量 I 的每一个位置处,对应位 置相乘再求和,计算过程如下:
假设卷积核的长度为 FL,如果 FL 为奇数,锚点位置在(FL-1)/2 处;如果 FL 为偶 数,锚点位置在(FL-2)/2 处。
一维 Valid 卷积
从 full 卷积的计算过程可知,如果 K 靠近 I, 就会有部分延伸到 I 之外,valid 卷积只考虑 I 能完 全覆盖 K 的情况,即 K 在 I 的内部移动的情况,计算 过 程 如下:
三种卷积类型的关系
2.2 因果卷积(Causal Convolution)
因果卷积可以用上图直观表示。 即对于上一层 t 时刻的值,只依赖于下一层 t 时刻及其之前的值。和传统的卷积神经网络的不同之处在于,因果卷积不能看到未来 的数据,它是单向的结构,不是双向的。也就是说只有有了前面的因才有后面的果, 是一种严格的时间约束模型,因此被成为因果卷积。
2.3 膨胀卷积(Dilated Convolution)
如图 TCN 结构图(a)。单纯的因果卷积还是存在传统卷积神经网络的问题,即对时 间的建模长度受限于卷积核大小的,如果要想抓去更长的依赖关系,就需要线性的堆 叠很多的层。为了解决这个问题,研究人员提出了膨胀卷积。
膨胀卷积(dilated convolution)是通过跳过部分输入来使 filter 可以应用于 大于 filter 本身长度的区域。等同于通过增加零来从原始 filter 中生成更大的 filter。
2.4 残差链接(Residual Connections)
如图 TCN 结构图(b)。 残差链接被证明是训练深层网络的有效方法,它使得网络 可以以跨层的方式传递信息。本文构建了一个残差块来代替一层的卷积。如上图所示, 一个残差块包含两层的卷积和非线性映射,在每层中还加入了 WeightNorm 和 Dropout 来正则化网络。为什么要 1×1 卷积呢?1×1 卷积是可以用来降维的 。作者直接把较 下层的特征图跳层连接到上层,对应的每个 Cell 的特征图数量(也就是通道数 channel)不一致,导致不能直接做类似 Resnet 的跳层特征图加和操作,于是,为了 两个层加和时特征图数量吻合,用 1×1 卷积做了一个降维的操作。
3 模型对比结果
3.1 代码示例
# 定义inputs层
inputs = keras.layers.Input(shape=(x_train.shape[1], x_train.shape[2]), name='inputs')
# 定义TCN网络
Conv1D_tar1 = keras.layers.Conv1D(5, 3, 1, activation='relu', padding='same', name='Conv1D_tar1')(inputs)
Dropout1 = keras.layers.Dropout(0.2, name='Dropout1')(Conv1D_tar1)
Conv1D_tar2 = keras.layers.Conv1D(5, 3, 2, activation='relu', padding='same', name='Conv1D_tar2')(Dropout1)
Dropout2 = keras.layers.Dropout(0.2, name='Dropout2')(Conv1D_tar2)
Conv1D_tar3 = keras.layers.Conv1D(5, 3, 4, activation='relu', padding='same', name='Conv1D_tar3')(Dropout2)
Dropout3 = keras.layers.Dropout(0.2, name='Dropout3')(Conv1D_tar3)
Conv1D1 = keras.layers.Conv1D(5, 3, 1, activation='relu', padding='same', name='Conv1D1')(inputs)
Conv1D2 = keras.layers.Conv1D(5, 3, 1, activation='relu', padding='same', name='Conv1D2')(Conv1D1)
# 维度变换合并
merged_Conv1D = keras.layers.Concatenate(name='merged_Conv1D', axis=1)([Conv1D2, Dropout3])
Flatten = keras.layers.Flatten(name='Flatten')(merged_Conv1D)
# 定义全连接层
dense_tar1 = keras.layers.Dense(64, activation='relu', name='dense_tar1')(Flatten)
dense_tar2 = keras.layers.Dense(24, activation='relu', name='dense_tar2')(dense_tar1)
outputs_tar = keras.layers.Dense(5, activation='relu', name='outputs_tar')(dense_tar2)
model = keras.Model(inputs=inputs, outputs=outputs_tar)
MAPE: 0.124 MSE: 0.700