pytorch中的卷积与池化

前言

使用pytorch搭建TextCNN时,需要使用卷积层与池化层,以下对pytorch中的卷积及池化层的特点进行记录。pytorch中卷积与池化需要重点关注input_channels、output_channles、kernel_size,即“输入张量通道数量、输出张量通道数量、核大小。”
 

卷积层

Conv1d

一维卷积是指卷积核张量是一维,其调用形式为:

torch.nn.Conv1d(in_channels: int, out_channels: int, 
kernel_size: Union[T, Tuple[T]], stride: Union[T, Tuple[T]] = 1, 

NLP问题中,上述四个参数比较常用,kernel_size与stride参数可以是单个整数,也可以是元组包装的单个整数。假设输入张量的形状为(N, Cin, Lin),则输出张量的形状为(N, Cout, Lout),卷积计算在最后一个维度上进行。
卷积层中权重的形状为output_channels * (in_channels * kernel_size), 偏差的形状为output_channels
在这里插入图片描述
在这里插入图片描述

Conv2d

二维卷积是指卷积核张量的尺寸是二维,其调用为:

torch.nn.Conv2d(in_channels: int, out_channels: int, 
kernel_size: Union[T, Tuple[T, T]], stride: Union[T, Tuple[T, T]] = 1

kernel_size与stride可以为整数或者元组,当为整数时,表示卷积核的长宽相当,为指定值;当为元组时,可以指定不同的长宽。对于stride也同理,表示向右向下移动的步长。卷积层中权重的形状为output_channels * (in_channels * (kernel_size_height * kernel_size_weight)), 偏差的形状为output_channels

在这里插入图片描述
2D卷积运算中还有一种特殊尺寸的卷积核——1*1卷积核,1*1卷积可以实现“对不同通道的特征加权求和与非线性转换,以及压缩通道数”。比如2D卷积核的shape为(输出通道,输入通道, 1, 1),则权重参数有“输入通道“数量的参数,可以理解为对输入通道加权。当“输出通道”数量小于“输入通道”数量时,则可以实现压缩通道数量的效果。

 

最大池化层

MaxPool1d

一维最大池化在一个一维窗口中取最大值,窗口大小有kerner_size指定,是单个值,窗口的步长由stride指定,默认为kernel_size的值。注意池化层是没有可学习参数的,调用如下:

torch.nn.MaxPool1d(kernel_size: Union[T, Tuple[T, ...]], 
stride: Optional[Union[T, Tuple[T, ...]]] = None

假设输入张量的形状为(N, C, Lin), 则输出的形状为(N, C, Lout)。注意卷积运算与池化运算的一个不同点,不论是一维还是二维运算,卷积运算都需要同时对输入的所有通道数据进行运算, 而池化运算是分别对通道数据进行运算。因此卷积核权重参数中的通道的数量,必须与输入数据的通道数量保持一致,而池化核则没有此要求。
在这里插入图片描述

MaxPool2d

对比一维最大池化,二维最大池化是在一个二维窗口中取最大值

在这里插入图片描述

补充材料

pytorch搭建TextCNN,需要使用二维卷积与一维最大池化,因为TextCNN本质是抽取N-gram特征

import torch
from torch import nn
import torch.nn.functional as F
from transformers import BertConfig, BertModel


class TextCNN(nn.Module):
    def __init__(self):
        """ 使用预训练模型训练的词嵌入向量 """
        super(TextCNN, self).__init__()
        self.embedding = nn.Embedding(21128, 768)
        bare_bert = BertModel.from_pretrained('hfl/chinese-bert-wwm')
        self.embedding.load_state_dict(bare_bert.embeddings.word_embeddings.state_dict(), strict=True)
        self.fc1 = nn.Linear(768, 100)  # 减低bert中的维度

        self.kernel_sizes = [2, 3, 4]
        # 对文本数据做二维卷积
        self.conv2s = nn.ModuleList([nn.Conv2d(1, 32, kernel_size=(kernel_size, 100))
                                     for kernel_size in self.kernel_sizes])
        self.dropout = nn.Dropout(0.1)
        self.fc2 = nn.Linear(32 * len(self.kernel_sizes), 33)

    @staticmethod
    def conv_and_maxpool(x, conv_layer):
        """
        initial x.shape: (batch_size, seq_len, 100)
        -> x.unsqueeze(1) -> shape: (batch_size, 1, seq_len, 100)
        -> nn.Conv2d(x) -> shape: (batch_size, output_channels, seq_len - kernel_size + 1, 1)
        -> squeeze(3) -> shape: (batch_size, output_channels, seq_len - kernel_size + 1)
        -> max_pool1d -> shape: (batch_size, output_channels, 1)
        -> squeeze(2) -> shape: (batch_size, output_channels)
        """
        x = conv_layer(x.unsqueeze(1)).squeeze(3)
        x = F.max_pool1d(x, x.shape[2], 1).squeeze(2)
        return x

    def forward(self, x, labels=None):
        x = self.embedding(x)
        x = self.fc1(x)

        x = torch.cat([self.conv_and_maxpool(x, conv_layer=conv) for conv in self.conv2s], dim=1)
        x = self.dropout(x)
        logits = self.fc2(x)
        if labels is None:
            return logits
        else:
            loss = F.cross_entropy(logits, labels)
            return loss, logits

 

参考资料

  1. torch.nn官网文档
  2. 中文文本分类 pytorch实现
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值