标准卷积和因果卷积的区别(一维)

标准(传统)卷积和因果卷积的区别(一维)

问题的起源

TCN论文及代码解读总结中提到

因果卷积和传统的卷积神经网络的不同之处在于,因果卷积不能看到未来的数据

找了很长时间没有捋清头绪,转头把方向指向了代码,就从官方文档下手吧,在Pytorch文档里面没有找到因果卷积的相关定义,却在Keras中文文档里面找到了,当padding值为"causal"时,表示因果(膨胀)卷积,回头看Pytorch文档发现Pytorch的padding没有"causal"这个值!但它们都有{"valid", "same"}
那么问题来了:

padding值为{"valid", "same"}是不是代表标准卷积?

下面就开始找文章验证自己猜想,并尝试复现相关代码

相关文章

第一篇常规卷积与因果卷积的区别详解

这篇博客有Pytorch实现TCN的代码参考,结合TCN说明了常规卷积和因果卷积的区别只是padding位置不同。标准卷积是在两边padding,而因果卷积只是在前面padding,该博客也解释了TCN为了实现因果卷积对Conv1d进行Chomp1d处理的原因。但看到下面评论有点疑惑???说大错特错???我带着疑问找到了下面这个链接,也验证了这篇博客说的没有问题,评论有问题。

第二篇Machine Learning for Finance这应该是一本书

白嫖看到了想看到的部分,解释了标准卷积和因果卷积的区别,太幸运了吧!这里只把图片放到这里,供参考哈
标准卷积原文给出了这句解释:Standard convolution does not take the direction of convolution into account.(标准卷积不考虑卷积的方向)说实话我没看懂
因果卷积
同样原文也解释了这个图片:Causal convolution shifts the filter in the right direction.(因果卷积将过滤器朝正确的方向移动)自行翻译理解吧

个人理解

因果卷积和标准卷积只是padding的位置区别。
对比
对于因果卷积不能看到未来的数据给出一下个人见解,这里涉及到一个知识点(感受野)。我们以输出的t3值为例,标准卷积输出为3,标准卷积的感受野为[3,4,1],也就是意味着它用t1、t2、t3时刻的数据去预测t3,也就造成了标准卷积看到了未来数据的问题;对于因果卷积来说,输出的t3值为10,因果卷积的感受野为[0,3,4],也就避免了上面问题。
这里有个前提:
数据和标签在一起,而不是单独分开,如果标签和数据分开,就不会导致未来数据泄露。
即当传递给模型的数据格式为[t1,t2,t3,t4,t5],用标准卷积预测t5值就会导致数据泄露,而要用标准卷积预测t6值可能会引入padding的噪声,影响模型性能。

个人部分看法:当padding值为 "same",妥妥的传统卷积。

复现相关代码

为了进一步验证猜想,尝试用代码层面去解释。对于{"valid", "same"}卷积过程,这里我们可以参考各种卷积方式的最全讲解,与下面代码进行对比验证。

  1. 引入相关模块
from keras.layers import Conv1D
from keras import Sequential
import numpy as np
  1. 自定义卷积核
def my_init(shape, dtype=None):
    # 自定义必须保留 shape, dtype 两个属性
    init = [[[-2]], [[2]], [[1]]]
    return init
  1. 定义Conv1D层,将padding设置为"causal",有兴趣的可以自行修改为其他属性{"valid", "same"}去尝试。
model = Sequential([
    Conv1D(1, kernel_size=3, name='cnn1', padding='causal',
           kernel_initializer=my_init,  # 全部初始化为0
           use_bias=False),  # 不使用偏置
])
  1. 自定义传入的数据,并用模型进行输出
x_list = [3, 4, 1, 5, 6]    # 自定义列表
# 将列表转换为np数组,并转换为(batch_size, steps, input_dim)格式
x = np.array(x_list, dtype='float64').reshape(1, -1, 1)
y = model(x)
print(y)

tf.Tensor(
[[[ 3.]
[10.]
[ 3.]
[-1.]
[14.]]], shape=(1, 5, 1), dtype=float32)

  1. 查看层的初始化权重值
layer = model.get_layer('cnn1')  # 通过层的名字得到层
k = layer.get_weights()  # 查看层的初始化权重值
print(k)

接着讨论

我们假设这样一个场景,给出了t1-t5时刻的数据,我们要预测t6时刻的数据,为了关联更多的数据,那我们是不是要增加感受野,让卷积输出的t6时刻数据包含较大范围的信息,让我们完善一下因果卷积流程吧,同时对比一下当padding值为 "valid"的情况。
因果卷积对比

个人部分看法:
当落脚到代码实现上,抛开其他输出时刻数据,只关注t6时刻的数据,会发现我们可以定义padding值为"valid"会实现相同的效果!!!
那是不是意味着padding值为"valid"定义的卷积是因果卷积???我个人看法是认同的。
但当模型复杂度上升之后,要保证输入前后维度保持不变,那就不能选择"valid"这个属性值,而应该参照TCN中的方法。

最后用Pytorch代码去实现两层padding值为"valid"运行后的结果

import torch.nn as nn
import torch
import numpy as np

cnn1 = nn.Conv1d(1, 1, kernel_size=3, padding='valid', bias=False)
cnn1.weight.data = torch.Tensor([[[-2, 2, 1]]])
cnn2 = nn.Conv1d(1, 1, kernel_size=3, padding='valid', bias=False)
cnn2.weight.data = torch.Tensor([[[-2, 2, 1]]])
x_list = [3, 4, 1, 5, 6]  # 自定义列表
# 将列表转换为np数组,并转换为(batch_size, steps, input_dim)格式
x = torch.Tensor(np.array(x_list, dtype='float64').reshape(1, 1, -1))
y = cnn1(x)
y = cnn2(y)
print(y)

tensor([[[6.]]], grad_fn=< ConvolutionBackward1 >)

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值