首先我们需要进行对Conv1D模型的解读
self.conv1d = Conv1D(
filters=self.filters * 2,
kernel_size=self.kernel_size,
dilation_rate=self.dilation_rate,
padding='same',
)
调用的过程为
首先使用继承下来的mask的内容
这里我们通过一个例子来说明mask的作用
import numpy as np
data = np.array([[[1,2,3,0,0],
[1,2,3,4,5]]])
masks = np.array([[[True],[False]]])
result = data*masks
print('result = ')
print(result)
结果为
result =
[[[1 2 3 0 0]
[0 0 0 0 0]]]
这里的形状(1,2,5)可以视为batch,maxlen,以及对应的维度,也就是说这里将标为False的最后一个维度的数值全部置为0,这类似于padding之后为了防止0影响到后续的学习过程,将对应数值置0的操作。
接下来首先调用conv1d网络层内容
outputs = self.conv1d(inputs)
在自然语言处理(NLP)领域,甚至图像处理的时候,我们可能会用到一维卷积(conv1d).以为卷积可以看作是二维卷积(conv2d)的简化,二维卷积是将一个特征图在width和height两个方向上进行滑动窗操作,对应位置进行相乘求和;而一维卷积则只是在width或者说height方向上进行滑动窗口并相乘求和
conv1d网络的构造部分
self.conv1d = Conv1D(
filters=self.filters * 2,
kernel_size=self.kernel_size,
dilation_rate=self.dilation_rate,
padding='same',
)
这里首先解析一下一维卷积的过程
红色代表卷积核为4的时候(一维卷积的宽永远与原先矩阵的宽相同,所以输出的矩阵永远为长条条),绿色代表卷积核为3的时候,黄色代表卷积核为2的时候。
引入一段对应的tensorflow调用ResidualGatedConv1D进行处理的维度变化
使用pytorch进行操作如下所示
这里的维度不同主要是tensorflow中加入了参数padding=‘same’,当padding='same’的时候保留边界的卷积结果,所以输入的维度和输出的维度一样,如果不想保留边界的池化结果,则可以使用padding=‘valid’,此时边界就会变成维度-kernel_size+1
如果将dilation_rate放大之后,结果与pytorch中的conv1d结果类似
conv1d只能够处理三维度的数据,所以较为适用于nlp数据处理的操作过程
另外一个需要注意的是,pytorch中的conv1d与tensorflow中的conv1d有所不同,pytorch中的conv1d是自左向右来切分的,所以切分出来后缩小的为最后一个维度,tensorflow中的conv1d是自上向下来切分的,所以切分出来后缩小的为倒数第二个维度(中间的维度)。
conv1d使用padding操作的时候都是在边界补零。
pytorch之中也有padding,不过pytorch中的padding与tensorflow中的padding定义不同,查看官方的原文件
padding(int or tuple,optional)-Zero-padding added to both sides of the input
也就是说这个是手动指定添加多少个padding网络层
可以看到,在对输入的inputs卷积进行padding之后,输出的维度保持不变
一维卷积只有长能够改变,所以输出的内容永远是一个长条条,二维卷积长和宽都能够被改变,所以输出的形状可以为一个矩阵。
初始化传入参数的时候
x = ResidualGatedConv1D(hidden_size, 3, dilation_rate=1)(x)
x = Dropout(0.1)(x)
#x = (18,256,384)
x = ResidualGatedConv1D(hidden_size, 3, dilation_rate=2)(x)
x = Dropout(0.1)(x)
#x = (18,256,384)
x = ResidualGatedConv1D(hidden_size, 3, dilation_rate=4)(x)
x = Dropout(0.1)(x)
#x = (18,256,384)
x = ResidualGatedConv1D(hidden_size, 3, dilation_rate=8)(x)
x = Dropout(0.1)(x)
#x = (18,256,384)
x = ResidualGatedConv1D(hidden_size, 3, dilation_rate=1)(x)
x = Dropout(0.1)(x)
#x = (18,256,384)
x = ResidualGatedConv1D(hidden_size, 3, dilation_rate=1)(x)
这里传入的hidden_size = 384,kernel_size = 3,dilation_rate = 1,2,4,8不等,
最终输出的结果
Y = i n p u t s + L a y e r N o r m a l i z a t i o n [ C o n v 1 D 1 ( x ) × s i g m o i d ( C o n v 1 D 2 ( x ) ) ] Y = inputs+LayerNormalization[Conv1D_{1}(x) \times sigmoid(Conv1D_{2}(x))] Y=inputs+LayerNormalization[Conv1D1(x)×sigmoid(Conv1D2(x))]
这里的第一个 C o n v 1 D 1 ( x ) Conv1D_{1}(x) Conv1D1(x)采用取向量前面一半[0:384]的方式,第二个 C o n v 1 D 2 ( x ) Conv1D_{2}(x) Conv1D2(x)采用取向量后面一半[385:768]的方式
但是这里self.alpha = 0,本质上就相当于过了一个conv1d而已