python3 extract_model.py对应代码解读抽取式提取+生成式提取摘要代码解读------摘要代码解读4

extract_model.py中ResidualGatedConv1D模块解读

Masking的作用

首先我们需要进行对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的网络层

接下来首先调用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进行处理的维度变化
tensorflow操作使用pytorch进行操作如下所示
pytorch操作这里的维度不同主要是tensorflow中加入了参数padding=‘same’,当padding='same’的时候保留边界的卷积结果,所以输入的维度和输出的维度一样,如果不想保留边界的池化结果,则可以使用padding=‘valid’,此时边界就会变成维度-kernel_size+1
边界池化结果如果将dilation_rate放大之后,结果与pytorch中的conv1d结果类似
将dilation_rate放大之后结果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网络层
加上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而已

Guess you like

Origin blog.csdn.net/znevegiveup1/article/details/121040372