文本将介绍将卷积神经⽹络应⽤到⽂本情感分析的开创性⼯作之⼀:TextCNN [1] 。
阅读本文后你可以掌握以下技能:
- 一维卷积、二维卷积的工作流程
- 文本分类模型TextCNN的结构及pytorch代码实现
- 模型如何加载预训练词向量
- 文本情感分析(分类)任务的一般流程
正餐之前,先来两碟开胃小菜。(跳过开胃小菜,直接吃正餐完全ok)
1.卷积层的介绍(开胃菜)
- 1 二维卷积层
卷积神经⽹络(Convolutional Neural Network,CNN)是含有卷积层(Convolutional Layer)的神经⽹络。卷积神经⽹络最常⻅的是⼆维卷积层。它有⾼和宽两个空间维度,常⽤来处理图像数据。这里将介绍简单形式的⼆维卷积层的⼯作原理。
虽然卷积层得名于卷积(Convolution)运算,但我们通常在卷积层中使⽤更加直观的互相关(Crosscorrelation)运算。在⼆维卷积层中,⼀个⼆维输⼊数组和⼀个⼆维核(kernel)数组通过互相关运算输出⼀个⼆维数组。 我们⽤⼀个具体例⼦来解释⼆维互相关运算的含义。如图1所示,输⼊是⼀个⾼和宽均为3的⼆维数组。我们将该数组的形状记为(3,3)。核数组的⾼和宽分别为2。该数组在卷积计算中⼜称卷积核或过滤器(filter)。卷积核窗⼝(⼜称卷积窗⼝)的形状取决于卷积核的⾼和宽,即 (2,2)。图1中的阴影部分为第⼀个输出元素及其计算所使⽤的输⼊和核数组元素:0✖️0 + 1✖️1 + 2✖️3 + 4✖️3=19。
在⼆维互相关运算中,卷积窗⼝从输⼊数组的最左上⽅开始,按从左往右、从上往下的顺序,依次在输⼊数组上滑动。当卷积窗⼝滑动到某⼀位置时,窗⼝中的输⼊⼦数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。图1中的输出数组⾼和宽分别为2,其中的4个元素是由⼆维互相关运算得出。
下⾯我们将上述过程实现在 corr2d 函数⾥。它接受输⼊数组 X 与核数组 K ,并输出数组 Y 。
import torch
def corr2d(X, K):
h, w = K.shape
Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1)) # 这里根据跟指定的X,Y计算输出结果的形状,并初始化该形状的矩阵元素全为0
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
Y[i, j] = (X[i: i + h, j: j + w] * K).sum()
return Y
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
K = torch.tensor([[0, 1], [2, 3]])
print(corr2d(X, K))
# 输出为:
tensor([[19., 25.],
[37., 43.]])
多个输入通道的互相关运算。当输⼊数据含多个通道时,我们需要构造⼀个输⼊通道数与输⼊数据的通道数相同的卷积核,从⽽能够与含多通道的输⼊数据做互相关运算。图2展示了含2个输⼊通道的⼆维互相关计算的例⼦。在每个通道上,⼆维输⼊数组与⼆维核数组做互相关运算,再按通道相加即得到输出。图2中阴影部分为第⼀个输出元素及其计算所使⽤的输⼊和核数组元素:(1✖️1 + 2✖️2 + 4✖️3 + 5✖️4)+(0✖️0 + 1✖️1 + 3✖️2 + 4✖️3)=56 。
接下来我们实现含多个输⼊通道的互相关运算。我们只需要对每个通道做互相关运算,然后通过add_n 函数来进⾏累加。
def corr2d_multi_in(X, K):
# 沿着X和K的第0维(通道维)分别计算再相加
res = corr2d(X[0, :, :], K[0, :, :]) # 注意哦这里调用的是本文上面的函数
for i in range(1, X.shape[0]):
res += corr2d(X[i, :, :], K[i, :, :])
return res
X = torch.tensor([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],[[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
K = torch.tensor([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])
print(corr2d_multi_in(X, K))
# 输出
tensor([[ 56., 72.],
[104., 120.]])
1.2 一维卷积层
在介绍模型前我们先学习一下一维卷机的工作原理。与⼆维卷积层⼀样,⼀维卷积层使⽤⼀维的互相关运算。在⼀维互相关运算中,卷积窗⼝从输⼊数组的最左⽅开始,按从左往右的顺序,依次在输⼊数组上滑动。当卷积窗⼝滑动到某⼀位置时,窗⼝中的输⼊⼦数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。如图3所示,输⼊是⼀个宽为7的⼀维数组,核数组的宽为2。可以看到输出的宽度为7-2+