sheng的学习笔记-TCN时序卷积:因果卷积、空洞卷积

卷积知识需要先看:sheng的学习笔记-AI-卷积神经网络

时序模型需要先看: sheng的学习笔记-AI-序列模型

Ai目录:sheng的学习笔记-AI目录-CSDN博客

在时序模型rnn中也可以使用卷积,此笔记记录这部分卷积内容

基础知识

什么是TCN 时序卷积 (temporal convolutional network)

TCN全称Temporal Convolutional Network,时序卷积网络,是在2018年提出的一个卷积模型,但是可以用来处理时间序列。

二维卷积 Conv2D

输入参数

卷积的输入参数:指需要做卷积的输入图像/音频等,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体图片的含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一

主要参数包括:

  • filters:卷积核个数,也是输出通道数。Integer, the dimensionality of the output space (i.e. the number of output filters in the convolution).
  • kernel_size: 卷积核大小,指定二维卷积窗口的高和宽,(如果kernel_size只有一个整数,代表宽和高相等):An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window. Can be a single integer to specify the same value for all spatial dimensions.
  • strides: 卷积步长,指定卷积窗沿高和宽方向的每次移动步长,An integer or tuple/list of 2 integers, (如果strides只有一个整数,代表沿着宽和高方向的步长相等) specifying the strides of the convolution along the height and width. Can be a single integer to specify the same value for all spatial dimensions. Specifying any stride value != 1 is incompatible with specifying any dilation_rate value != 1.
  • padding: 为valid或same中一种

一维卷积Conv1D

  • 输入变为三维变量
  • padding此时包括:samevalid 和causal

示例代码

def cnn_model():
    from tensorflow import keras

    inputs = keras.Input(shape=(34, 1))
    net = keras.layers.Conv1D(filters=128, kernel_size=(10), strides=(3), padding='VALID', name='conv_1')(inputs)
    net = keras.layers.BatchNormalization()(net)
    outputs = keras.layers.ReLU()(net)

    model = keras.Model(inputs=inputs, outputs=outputs)
    model.compile(
        loss=keras.losses.categorical_crossentropy,
        optimizer=keras.optimizers.Adadelta(),
        metrics=['accuracy']
    )

    model.summary()
    keras.utils.plot_model(model, 'cnn.png', show_shapes=True)

    return model

 因果卷积

使用因果卷积,要用函数Conv1D并且参数padding=causal

为什么用因果卷积

因为要处理序列问题(即要考虑时间问题)就不能使用普通的CNN卷积,在处理时间序列数据时,特别是在预测未来的时刻,我们不希望未来的信息在当前时刻被使用。但是在一维卷积的计算过程中,很显然我们会涉及到的不止过去的时间点,还有未来的时间点(即不止会涉及到上方的样本,还会涉及到下方的样本)。必须使用新的CNN模型,这个就是因果卷积的作用,

原理图

对序列问题(sequence modeling),主要抽象为,根据x1…xt和y1…yt-1去预测yt,使得yt接近于实际值

4次卷积,可以让最上层的一个节点,查看原始输入的5个节点 

这就引入了“因果卷积”。因果卷积保证了在任何时间点t,输出只依赖于时间点t及其之前的输入,而不依赖于t之后的输入。因果卷积可以通过对输入数据进行适当的“填充”来实现。具体地说,假设我们有一个一维的输入序列和一个大小为k的卷积核,为了实现因果卷积,我们可以在序列的开始处填充k-1个零,然后进行标准的卷积操作。这样,卷积的输出在任何时间点t都会依赖于时间点t及其之前的输入,如下图

缺点

但是存在问题是,如果考虑很久之前的变量x,那么卷积层数就必须增加

卷积层数的增加就带来:梯度消失,训练复杂,拟合效果不好的问题,为了决绝这个问题,出现了扩展卷积(dilated)

示例代码

使用因果卷积时,即设置padding=causal。注意因果卷积只适用于Conv1D和SeperableConv1D。

def cnn_model():
    from tensorflow import keras

    inputs = keras.Input(shape=(34, 1))
    net = keras.layers.Conv1D(filters=128, kernel_size=(10), strides=(3), padding='causal', name='conv_1')(inputs)
    net = keras.layers.BatchNormalization()(net)
    outputs = keras.layers.ReLU()(net)

    model = keras.Model(inputs=inputs, outputs=outputs)
    model.compile(
        loss=keras.losses.categorical_crossentropy,
        optimizer=keras.optimizers.Adadelta(),
        metrics=['accuracy']
    )

    model.summary()
    keras.utils.plot_model(model, 'cnn.png', show_shapes=True)

    return model

空洞卷积

什么是空洞卷积

Dilated Causal Convolution, 也叫扩展卷积、膨胀卷积、空洞卷积。

单纯的因果卷积还是存在传统卷积神经网络的问题,即对时间的建模长度受限于卷积核大小的,如果要想抓去更长的依赖关系,就需要线性的堆叠很多的层。标准的 CNN 可以通过增加 pooling 层来获得更大的感受野,而经过 pooling 层后肯定存在信息损失的问题。

        空洞卷积是在标准的卷积里注入空洞,以此来增加感受野。空洞卷积多了一个超参数 dilation rate,指的是 kernel 的间隔数量(标准的 CNN 中 dilatation rate 等于 1)。空洞的好处是不做 pooling 损失信息的情况下,增加了感受野,让每个卷积输出都包含较大范围的信息。下图展示了标准 CNN (左)和 Dilated Convolution (右),右图中的 dilatation rate 等于 2 。 

原理图

与正常的卷积不同的是,膨胀卷积引入了“扩张率”的超参数,该超参数定义了卷积核处理数据时各值的间距。

dilation = 1,卷积后的感受野为3;

dilation = 2,卷积后的感受野为5;

dilation = 3,卷积后的感受野为7;

从b和c可以看出,有无膨胀卷积,不影响输出特征的尺寸,但是利用膨胀卷积可以增大感受野

空洞卷积在时序中原理图

dilated的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。在图像需要全局信息或者语音文本需要较长的sequence信息依赖的问题中,都能很好的应用dilated conv,比如图像分割、语音合成WaveNet、机器翻译ByteNet中.

因为研究对象是时间序列,TCN 采用一维的卷积网络。上图是 TCN 架构中的因果卷积与空洞卷积,可以看到每一层  t 时刻的值只依赖于上一层  t,t-1.....时刻的值,体现了因果卷积的特性;而每一层对上一层信息的提取,都是跳跃式的,且逐层 dilated rate 以 2 的指数增长,体现了空洞卷积的特性。由于采用了空洞卷积,因此每一层都要做 padding(通常情况下补 0),padding 的大小为  。 

示例代码

使用因果空洞卷积时,即设置padding=causal, dilated_rate > 1

def cnn_model():
    from tensorflow import keras

    inputs = keras.Input(shape=(34, 1))
    net = keras.layers.Conv1D(filters=128, kernel_size=(10), strides=(1), padding='causal', dilation_rate=3, name='conv_1')(inputs)
    net = keras.layers.BatchNormalization()(net)
    outputs = keras.layers.ReLU()(net)

    model = keras.Model(inputs=inputs, outputs=outputs)
    model.compile(
        loss=keras.losses.categorical_crossentropy,
        optimizer=keras.optimizers.Adadelta(),
        metrics=['accuracy']
    )

    model.summary()
    keras.utils.plot_model(model, 'cnn.png', show_shapes=True)

    return model

注意,当dilated_rate > 1时,strides需等于1,否则会出现错误:

  • ValueError: strides > 1 not supported in conjunction with dilation_rate > 1

残差改进

变为:

TCN整体架构图

架构图

下面每一层,都是有2个空洞卷积加一次残差操作,空洞卷积看下面讲述

下面左边的图是完整架构图 

残差链接被证明是训练深层网络的有效方法,它使得网络可以以跨层的方式传递信息。本文构建了一个残差块来代替一层的卷积。如上图所示,一个残差块包含两层的卷积和非线性映射,在每层中还加入了WeightNorm和Dropout来正则化网络。

加1×1卷积原因:1×1卷积是可以用来降维的 。作者直接把较下层的特征图跳层连接到上层,对应的每个Cell的特征图数量(也就是通道数channel)不一致,导致不能直接做类似Resnet的跳层特征图加和操作,于是,为了两个层加和时特征图数量吻合,用1×1卷积做了一个降维的操作。

优缺点

优点:

  • 并行性(Parallelism)。与在 RNN 中对后续时间步的预测必须等待其前任完成的情况不同,卷积可以并行完成,因为每一层都使用相同的滤波器。因此,在训练和评估中,长输入序列可以在 TCN 中作为一个整体进行处理,而不是像在 RNN 中那样按顺序处理。
  • 灵活的感受野大小(Flexible receptive field size)。TCN 可以通过多种方式改变其感受野大小。例如,堆叠更多扩张(因果)卷积层、使用更大的膨胀因子或增加滤波器大小都是可行的选择(可能有不同的解释)。因此,TCN 可以更好地控制模型的内存大小,并且易于适应不同的领域。
  • 稳定的梯度(Stable gradients)。与循环架构不同,TCN 的反向传播路径与序列的时间方向不同。因此,TCN 避免了梯度爆炸/消失的问题,这是 RNN 的一个主要问题,并导致了 LSTM、GRU、HF-RNN(Martens & Sutskever,2011)等的发展。
  • 训练时内存要求低。特别是在输入序列较长的情况下,LSTM 和 GRU 很容易占用大量内存来存储它们的多个单元门的部分结果。而在 TCN 中,滤波器跨层共享,反向传播路径仅取决于网络深度。因此,在实践中,我们发现门控 RNN 可能比 TCN 使用更多的内存。
  • 可变长度输入。就像 RNN 以循环方式对可变长度的输入进行建模一样,TCN 也可以通过滑动 1D 卷积核来接收任意长度的输入。这意味着 TCN 可以作为 RNN 的替代品,用于任意长度的序列数据。

缺点:

  • 评估期间的数据存储。在评估/测试中,RNN 只需保持隐藏状态并获取当前输入 xt 即可生成预测。换句话说,整个历史的“摘要”由一组固定长度的向量 ht 提供,而实际观察到的序列可以被丢弃。相比之下,TCN 需要接收到有效历史长度的原始序列,因此在评估期间可能需要更多内存。
  • 域迁移的潜在参数变化(Potential parameter change for a transfer of domain)。不同领域对模型预测所需的历史数量可能有不同的要求。因此,当将模型从只需要很少内存的域(即小 k 和 d)转移到需要更长内存的域(即大得多的 k 和 d)时,TCN 可能会因为没有足够大的感受野。

参考文章:

【卷积】一维/二维、因果、空洞卷积_padding='causal-CSDN博客

TCN 时序卷积网络 (temporal convolutional network)【因果卷积、空洞卷积】-CSDN博客

LSTM的备胎,用卷积处理时间序列——TCN与因果卷积(理论+Python实践) - 阅读清单 - 腾讯云开发者社区-腾讯云 TCN(Temporal Convolutional Network,时间卷积网络)-CSDN博客

时间卷积网络(TCN)原理+代码详解-CSDN博客

TCN 神经网络示意图 tcn和cnn_jkfox的技术博客_51CTO博客

### 使用TCN模型预测二维时间序列数据 对于二维时间序列数据的预测,可以采用扩展的时间卷积网络(TCN)。TCN是一种基于卷积神经网络(CNN)架构设计的模型,特别适用于处理顺序数据。该方法不仅能够捕捉局部特征,还能通过堆叠多层膨胀卷积有效扩大感受野范围,从而更好地理解长期依赖关系[^1]。 为了适应二维输入,通常的做法是在原有的一维卷积基础上增加额外的空间维度。具体来说: - 输入张量形状应调整为 `[batch_size, channels, height, width]` 或者 `[batch_size, time_steps, features]` 形式的三维数组; - 卷积操作需改为两维形式 `Conv2D` 来替代标准的一维版本; - 如果原始问题是单变量时间序列,则可能需要先将其转换成适合二维表示的形式;如果是多变量情况则可以直接作为矩阵输入给模型训练过程。 下面给出一段简化版Python代码片段展示如何构建并训练这样一个改进后的TCN模型来进行二维时间序列预测任务: ```python import torch from torch import nn class TCNLayer(nn.Module): def __init__(self, c_in, c_out, kernel_size=3, dilation=1): super().__init__() padding = (kernel_size - 1) * dilation self.conv = nn.Conv2d(c_in, c_out, kernel_size=(kernel_size, 1), stride=1, padding=(padding, 0), dilation=dilation) def forward(self, x): return self.conv(x) class TemporalBlock(nn.Module): def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, dropout=0.2): super(TemporalBlock, self).__init__() conv_layer_1 = TCNLayer(n_inputs, n_outputs, kernel_size, dilation) relu_1 = nn.ReLU() dropout_1 = nn.Dropout(dropout) conv_layer_2 = TCNLayer(n_outputs, n_outputs, kernel_size, dilation*2) relu_2 = nn.ReLU() dropout_2 = nn.Dropout(dropout) net = nn.Sequential(conv_layer_1, relu_1, dropout_1, conv_layer_2, relu_2, dropout_2) downsample = nn.Conv2d( n_inputs, n_outputs, 1) if n_inputs != n_outputs else None self.net = nn.Sequential(net) self.downsample = downsample self.relu = nn.ReLU() def forward(self, x): out = self.net(x) res = x if self.downsample is None else self.downsample(x) return self.relu(out + res) class TCNPredictor(nn.Module): def __init__(self, input_channels, output_channels, num_layers=8, hidden_units=64, kernel_size=7, dropout=0.2): super(TCNPredictor, self).__init__() layers = [] for i in range(num_layers): dilations = 2 ** i layer = TemporalBlock(input_channels if i == 0 else hidden_units, hidden_units, kernel_size, stride=1, dilation=dilations, dropout=dropout) layers.append(layer) final_conv = nn.Conv2d(hidden_units, output_channels, 1) seq_model = [*layers, final_conv] model = nn.Sequential(*seq_model) model.apply(init_weights) def init_weights(m): if isinstance(m, nn.Conv2d): nn.init.xavier_uniform_(m.weight.data) model.apply(init_weights) sequence_length = 100 # 假设的时间步数长度 feature_dim = 5 # 特征数量 batch_size = 32 # 批次大小 dummy_input = torch.randn(batch_size, feature_dim, sequence_length, 1) print(model(dummy_input).shape) tcn_predictor = TCNPredictor(5, 1) print(tcn_predictor) ``` 此段代码定义了一个基本框架用于创建一个针对二维时间序列数据优化过的TCN预测器实例,并打印出了模型结构及其预期输出尺寸。需要注意的是这只是一个非常基础的例子,在实际应用中还需要考虑更多因素如正则化技术的选择、超参数调优等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值