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

导读

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

  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》的情感分析篇。


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

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
深度学习之卷积神经网络(CNN)详解与代码实现(一) 卷积神经网络(CNN)是深度学习领域中应用广泛的一种神经网络,它通过卷积、池化等操作,能够有效地处理图像、语音、文本等数据类型。本文将从卷积神经网络的基本原理、结构、训练方法等方面进行详细介绍,并通过代码实现,加深读者对卷积神经网络的理解。 一、卷积神经网络的基本原理 卷积神经网络(CNN)的基本原理是通过卷积操作对输入数据进行特征提取,然后通过全连接层对特征进行分类或回归。卷积操作是CNN的核心,它可以有效地减少网络中的参数数量,提高模型的泛化能力。 卷积操作是指将一个卷积核(kernel)与输入数据进行卷积运算,得到一个特征图(feature map)。卷积核是一个小的矩阵,可以通过学习得到,它的作用是对输入数据进行特征提取。卷积操作可以提取出输入数据中的局部特征,不同的卷积核可以提取出不同的特征,从而实现对输入数据的特征提取。 二、卷积神经网络的结构 卷积神经网络的结构包括卷积层、池化层、全连接层等。其中卷积层和池化层是CNN的核心,全连接层用于分类或回归。 1. 卷积层 卷积层是CNN中最重要的层之一,它的作用是对输入数据进行特征提取。卷积层的参数包括卷积核的大小、深度、步长等,其中卷积核的大小和深度是最重要的参数。 卷积层的输入是一个四维张量,分别表示样本数量、图像高度、图像宽度、图像通道数。卷积核是一个三维张量,分别表示卷积核的高度、宽度、深度。 卷积操作可以通过矩阵乘法实现,也可以通过FFT等方法实现,但是前者的方法在卷积核较小时速度较慢,后者在卷积核较大时速度较慢。 2. 池化层 池化层是CNN中另一个重要的层,它的作用是对卷积层的输出进行降维和特征提取。池化操作可以通过最大池化、平均池化等方法实现。最大池化是指在一个池化区域内选取最大的值作为池化结果,平均池化是指在一个池化区域内取平均值作为池化结果。 池化操作可以有效地减少数据的大小,提高模型的泛化能力。但是需要注意的是,过度的池化会导致信息的丢失,从而影响模型的性能。 3. 全连接层 全连接层是CNN中的最后一层,它的作用是将卷积层和池化层的输出进行分类或回归。全连接层是一个标准的神经网络,其中每个神经元都与前一层的所有神经元相连。 全连接层的输出可以通过softmax函数进行分类,也可以通过线性函数进行回归。 三、卷积神经网络的训练方法 卷积神经网络的训练方法与其他神经网络类似,主要包括前向传播和反向传播两个过程。前向传播是指将输入数据通过卷积层、池化层、全连接层等一系列操作,得到最终的输出结果。反向传播是指将输出结果与真实标签进行比较,然后通过梯度下降等方法,不断调整网络参数,使得输出结果更加接近真实标签。 在训练过程中,需要注意的是,卷积神经网络通常需要较长的训练时间和大量的训练数据,以便得到更好的性能。此外,还需要注意选择适当的优化算法、学习率、正则化等参数,以避免过拟合和欠拟合等问题。 四、代码实现 下面是一个简单的卷积神经网络的代码实现,用于对手写数字进行分类。 ```python import tensorflow as tf # 加载数据 mnist = tf.keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() # 数据预处理 x_train, x_test = x_train / 255.0, x_test / 255.0 # 定义模型 model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值