使用pytorch实现简单的TextCNN(步骤详解)

本文中将根据原理图所示,使用pytorch搭建简单的TextCNN网络结构。尽可能详细的描述每个步骤。
TextCNN的详细过程原理图如下:
使用pytorch实现简单的TextCNN(步骤详解)_第1张图片

以下代码基于https://blog.csdn.net/sunny_xsc1994/article/details/82969867进行修改得到

embedding_size=5, out_channels=2, kernel_size=[2,3,4], max_text_len=7

  • embedding_size 每个词向量的长度,在图中是d=5
  • out_channels 卷积产生的通道数,有多少个out_channels,就需要多少个一维卷积(也就是卷积核的数量)。图中可以看到每类卷积核,或者说filter,分别有两个,所以out_channels=2
  • kernel_size 卷积核的大小,即图中filter的行数。列数和embedding_size相同,因为这是一维的卷积。如图所示,分别是2,3,4
  • max_text_len the size of the window to take a max over. 我的理解是,MaxPool1d中会取图中feature maps中的最大值,为此,得确定一个范围,即多长的feature map中的最大值。当长度为feature map全长时,最大值自然只有一个,当长度为feature map全长减1时,最大值会有两个(这里步长stride假设为1),以此类推。 在这里我们选可能输入的句子中的最大长度(feature map长度最长为句子长度,这是卷积的结果,比较简单,就不赘述了),图中只有一条句子,所以最大长度是该句子的长度7.
class TextCNN(nn.Module):
    def __init__(self, config):
        super(TextCNN, self).__init__()
        self.dropout_rate = config.dropout_rate
        self.num_class = config.num_class
        self.config = config
 
        self.embedding = nn.Embedding(num_embeddings=config.vocab_size, 
                                embedding_dim=config.embedding_size)  # 创建词向量对象
        self.convs = nn.ModuleList([
                			  nn.Sequential(nn.Conv1d(in_channels=config.embedding_size, 
                                        			out_channels=config.out_channels, 
                                        			kernel_size=h),  # 卷积层,这里的Sequential只包含了卷积层,感觉这样写有些多余,
                                        									# Sequential可以把卷积层、 激活函数层和池化层都包含进去
                              nn.ReLU(), # 激活函数层
                              nn.MaxPool1d(kernel_size=config.max_text_len-h+1)) # 池化层,这里kernel_size的值应该不用进行这样多余的计算,我们的目的
                              #是将feature maps转为一行一列的向量,那么只要保证这里的kernel_size大于等于feature maps的行数就可以了
                     for h in config.kernel_size	# 不同卷积层的kernel_size不一样,注意:这里的kernel_size和池化层的kernel_size是不同的
                    ])			# 创建多个卷积层,包含了 图中的convolution、activation function和 maxPooling
        self.fc = nn.Linear(in_features=config.out_channels*len(config.kernel_size),
                            out_features=config.num_class) # 把最终的特征向量的大小转换成类别的大小,以此作为前向传播的输出。这里和图中的有些区别,貌似并没有用到softmax和regularization
    
    def forward(self, x):
        embed_x = self.embedding(x) # 将句子转为词向量矩阵,大小为1*7*5,这里的1是表示只有1条句子
        embed_x = embed_x.permute(0, 2, 1) # 将矩阵转置
        out = [conv(embed_x) for conv in self.convs]  #计算每层卷积的结果,这里输出的结果已经经过池化层处理了,对应着图中的6 个univariate vectors
        out = torch.cat(out, dim=1)  # 对6 个univariate vectors进行拼接
        out = out.view(-1, out.size(1))  #按照行优先的顺序排成一个n行1列的数据,这部分在图中没有表现出来,其实在程序运行的过程中6 个univariate vectors的大小可能是1*1*1,进行拼接后是1*1*6,我们在这里将其转换为1*6,可见每个值都没有丢失,只是矩阵的形状变了而已
        out = F.dropout(input=out, p=self.dropout_rate) # 这里也没有在图中的表现出来,这里是随机让一部分的神经元失活,避免过拟合。它只会在train的状态下才会生效。进入train状态可查看nn.Module。train()方法
        out = self.fc(out)
        return out

以上就是TextCNN的网络结构,至于怎么使用就不在这里赘述了。
写的有错误的地方,希望能在评论区指正,谢谢!

参考链接

https://blog.csdn.net/sunny_xsc1994/article/details/82969867

你可能感兴趣的:(自然语言处理)