详解文本分类之多通道CNN的理论与实践

本文深入探讨了多通道卷积神经网络(multi_channel_CNN)在文本分类任务中的应用,介绍了其理论基础,包括如何通过不同类型的embedding初始化来创建多通道输入,以及在PyTorch中的实现细节。通过对比实验,展示了多通道卷积神经网络在效率和准确性上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导读

最近在梳理文本分类的各个神经网络算法,特地一个来总结下。接下来将要一个文章一个文章的讲解各个算法的理论与实践。目录暂定为:

  1. 多通道卷积神经网络(multi_channel_CNN)

  2. 深度卷积神经网络(deep_CNN)

  3. 基于字符的卷积神经网络(Char_CNN)

  4. 循环与卷积神经网络并用网络(LSTM_CNN)

  5. 树状循环神经网络(Tree-LSTM)

  6. Transformer(目前常用于NMT)

  7. etc..

之后的以后再补充。今天我们先讲第一个,多通道卷积神经网络。

 

先前知识补充

先说点基础的,我们最刚开始的分类其实就是embedding层之后直接经过线性层进行降维,将其映射到分类上,图为:

然后因为参数太多,计算太慢,所以产生了pooling池化层,取指定维度的一个参数代表整个维度,从而大大降低了计算量,而且效果还不错。图为:

之后又有人想到没有充分的利用到句子的上下词语的关系,所以就讲图像算法的CNN运用到了NLP上,这个就相当于NLP里的n-gram(unigram,bigram,trigram...)一样,寻找相邻词语组合形成的特征。图为:

有了上面的基础,我们引出multi_channel_CNN就容易多了。

 

multi_channel_CNN

多通道,就是CNN中的一次性卷积要处理的多少组数据。比如图像中,如果是只有灰度值的图像就只有一个通道,如果是彩色图片的话,就会RGB三个图像(也就是三个通道)。那么NLP中怎么利用这个多通道特征呢?有人就想了NLP中不就一个句子长度 * embed维度组成的一个二维输入吗?是这样的,刚开始我们用的都是单通道的。

但是有人就提出了这样的想法:

初始化两个不同的embedding,将句子用两个embedding表示出来,这样就可以有两个通道了。

时间确实是这样的,但是我们常用的是一个是随机初始化的embedding,另一个是使用预训练embedding(w2v or GloVe ...)。图为:

 

实践

这个其实和图像是想的差不多了。(pytorch)

class Multi_Channel_CNN 初始化:

def __init__(self, opts, vocab, label_vocab):
       super(Multi_Channel_CNN, self).__init__()

       random.seed(opts.seed)
       torch.manual_seed(opts.seed)
       torch.cuda.manual_seed(opts.seed)

       self.embed_dim = opts.embed_size
       self.word_num = vocab.m_size
       self.pre_embed_path = opts.pre_embed_path
       self.string2id = vocab.string2id
       self.embed_uniform_init = opts.embed_uniform_init
       self.stride = opts.stride
       self.kernel_size = opts.kernel_size
       self.kernel_num = opts.kernel_num
       self.label_num = label_vocab.m_size
       self.embed_dropout = opts.embed_dropout
       self.fc_dropout = opts.fc_dropout

       self.embeddings = nn.Embedding(self.word_num, self.embed_dim)
       self.embeddings_static = nn.Embedding(self.word_num, self.embed_dim)

       if opts.pre_embed_path != '':
           embedding = Embedding.load_predtrained_emb_zero(self.pre_embed_path, self.string2id)
           self.embeddings_static.weight.data.copy_(embedding)
       else:
           nn.init.uniform_(self.embeddings_static.weight.data, -self.embed_uniform_init, self.embed_uniform_init)

       nn.init.uniform_(self.embeddings.weight.data, -self.embed_uniform_init, self.embed_uniform_init)

       # 2 convs
       self.convs = nn.ModuleList(
           [nn.Conv2d(2, self.embed_dim, (K, self.embed_dim), stride=self.stride, padding=(K // 2, 0)) for K in self.kernel_size])

       in_fea = len(self.kernel_size)*self.kernel_num
       self.linear1 = nn.Linear(in_fea, in_fea // 2)
       self.linear2 = nn.Linear(in_fea // 2, self.label_num)
       self.embed_dropout = nn.Dropout(self.embed_dropout)
       self.fc_dropout = nn.Dropout(self.fc_dropout)

这个部分主要将输入的通道数1改为2即可。

 

数据流通部分:

def forward(self, input):
       static_embed = self.embeddings_static(input)  # torch.Size([64, 39, 100])
       embed = self.embeddings(input)  # torch.Size([64, 39, 100])

       x = torch.stack([static_embed, embed], 1)  # torch.Size([64, 2, 39, 100])

       out = self.embed_dropout(x)

       l = []
       for conv in self.convs:
           l.append(F.relu(conv(out)).squeeze(3))  # torch.Size([64, 100, 39])

       out = l
       l = []
       for i in out:
           l.append(F.max_pool1d(i, kernel_size=i.size(2)).squeeze(2))  # torch.Size([64, 100])

       out = torch.cat(l, 1)  # torch.Size([64, 300])

       out = self.fc_dropout(out)

       out = self.linear1(out)
       out = self.linear2(F.relu(out))

       return out

这里主要就是一个stack函数的应用,将两个embedding放到一个新的维度里。

 

数据对比

可以明显看出多通道优点还是很突出的。

 

github地址:

https://github.com/zenRRan/Sentiment-Analysis/blob/master/models/multi_channel_CNN.py

欢迎fork,有问题大家尽管指出!

 

PS:上述图片均来自于导师张梅山,唐都钰的《Deep Learning in Natural Language Processing》的情感分析篇。


更多精彩内容,请关注 深度学习自然语言处理 公众号,就是下方啦!跟随小博主,每天进步一丢丢!哈哈!

<think>好的,我现在需要帮助用户查找关于卷积神经网络(CNN)代码的详细解析以及原理的详解。首先,我应该回顾用户提供的参考引用内容,看看是否有相关的信息可以提取。 用户提供的引用中,引用[1]和[3]提到了CNN的基本结构和历史背景,包括卷积层、池化层、全连接层,以及稀疏连接和权值共享的特点。引用[2]提到了CNN的发展历程和一个手写数字识别的例子。引用[4]则涉及了PyTorch中的Embedding层和在药物分子蛋白质序列中的应用,还提到卷积后维度变化的问题。 用户的需求是CNN的代码实现和原理详解。我需要结合这些引用内容,并补充一些常见的CNN实现细节,比如使用PyTorch框架构建模型的具体步骤,各层的作用,以及前向传播的过程。例如,引用[1]提到PyTorch搭建CNN模型,可能需要展示一个简单的CNN结构,包含卷积层、激活函数、池化层和全连接层。 同时,用户可能需要了解CNN的工作原理,比如卷积操作如何提取特征,池化层如何降维,权值共享如何减少参数数量等。引用[2]和[3]中的背景信息可以用于解释CNN的优势和应用场景。 在代码部分,我需要确保使用正确的格式,行内数学公式用$...$,独立公式用$$...$$。例如,卷积操作的公式可以写成: $$(f * g)(t) = \int_{-\infty}^{\infty} f(\tau)g(t - \tau)d\tau$$ 但考虑到用户可能需要离散形式的卷积,更适合的可能是: $$(I * K)_{i,j} = \sum_{m}\sum_{n} I_{i+m,j+n}K_{m,n}$$ 另外,引用[4]提到的Embedding层可能不适用于图像处理,但用户的问题是关于CNN的一般代码,所以可能不需要涉及Embedding,除非用户有特定需求。不过用户的问题中没有提到自然语言处理,所以可能只需要关注图像相关的CNN结构。 接下来,我需要组织回答的结构,先解释原理,再展示代码,最后生成相关问题。需要确保各部分引用正确的来源,例如在提到卷积层结构时引用[1],在历史背景时引用[2]和[3]。 可能的问题点:用户是否需要具体的应用实例,比如手写数字识别?引用[2]提到了这个例子,所以在代码示例中使用MNIST数据集比较合适。同时,PyTorch的代码结构需要符合引用[1]和[4]中的内容,比如使用Conv2d、MaxPool2d和Linear层。 在编写代码时,需要注意注释,解释每一层的作用,比如卷积层的输入输出通道、池化层的核大小,以及全连接层的参数计算。例如,输入MNIST图像是1x28x28,经过卷积和池化后,特征图的尺寸变化需要计算清楚,以便正确设置全连接层的输入维度。 原理部分需要涵盖局部感受野、权值共享、池化的作用,以及多层结构如何提取抽象特征。这些内容可以结合引用[1]、[2]、[3]的信息进行说明。 最后,生成的相关问题需要围绕CNN的结构、优化、应用和其他网络的比较,确保覆盖用户可能感兴趣的扩展方向。</think>### 卷积神经网络(CNN)代码实现及原理详解 #### 一、CNN核心原理 1. **稀疏连接权值共享** CNN通过卷积核在局部感受野上滑动,实现参数共享(同一卷积核检测不同位置的特征),大幅减少参数量。例如,$3 \times 3$卷积核仅需9个参数,却可覆盖全图特征[^1]。 2. **层次化特征提取** - **卷积层**:提取局部特征,数学表达式为: $$(I * K)_{i,j} = \sum_{m}\sum_{n} I_{i+m,j+n}K_{m,n}$$ 其中$I$为输入,$K$为卷积核[^2]。 - **池化层**(如最大池化):降低空间维度,增强平移不变性,公式为: $$P_{i,j} = \max_{(m,n) \in R} I_{i+m,j+n}$$ - **全连接层**:将高层特征映射到分类结果[^3]。 --- #### 二、PyTorch代码实现(以MNIST分类为例) ```python import torch import torch.nn as nn class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() # 卷积层:输入通道1,输出通道16,卷积核3x3 self.conv1 = nn.Conv2d(1, 16, 3) # 最大池化:2x2窗口 self.pool = nn.MaxPool2d(2, 2) # 全连接层:输入维度16*13*13,输出10类 self.fc = nn.Linear(16 * 13 * 13, 10) def forward(self, x): x = self.pool(torch.relu(self.conv1(x))) # 输出尺寸:16x13x13 x = x.view(-1, 16 * 13 * 13) # 展平为向量 x = self.fc(x) return x ``` **代码解析** 1. **卷积层**:`nn.Conv2d`通过滑动窗口计算局部特征,权值共享机制减少参数冗余[^1]。 2. **池化层**:`MaxPool2d`缩小特征图尺寸,增强模型鲁棒性[^3]。 3. **维度计算**:MNIST输入为$1 \times 28 \times 28$,卷积后尺寸为$(28-3+1)=26$,池化后为$13 \times 13$。 --- #### 三、CNN优势应用场景 1. **图像识别**:通过多层卷积提取边缘→纹理→物体的层次特征[^2]。 2. **自然语言处理**:1D卷积用于文本分类(引用[4]中提及的Embedding层可扩展至此场景)。 3. **参数效率**:权值共享使参数量远少于全连接网络[^1]。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值