CNN、RNN文本分类
知识储备
CNN卷积神经网络
一、参考资料:
(1)如何通俗易懂地解释卷积?https://www.zhihu.com/question/22298352/answer/228543288
(2)通俗理解 CNN:https://wmathor.com/index.php/archives/1353/
二、归纳理解和流程解释
1、结构和流程
补充:
卷积层(Convolutional Layer) - 主要作用是提取特征。
池化层(Max Pooling Layer) - 主要作用是下采样(downsampling),却不会损坏识别结果。
全连接层(Fully Connected Layer) - 主要作用是分类。
2、具体描述
2.1 数据输入层 :词嵌入
2.1.1 基本思想和目的
基本思想是将每个词表达成 n 维稠密、连续的实数向量,与之相对的one-hot encoding向量空间只有一个维度是1,其余都是0。分布式表示最大的优点是具备非常powerful的特征表达能力。不管是神经网络的隐层,还是多个潜在变量的概率主题模型,都是应用分布式表示。如下图所示,最终需要得到每个单词对应的一个稠密词向量,并且获得的词向量与词向量之间的距离需要能体现出词与词之间的相似性。
2.1.2 获得流程
词嵌入分为随机初始化和预训练初始化两部分。
①随机初始化
给定一个维度d,对于每一个词,随机生成一个d维的变量x,可以让x符合某种分布,例如标准正态分布,初始化类型可以看看:(【细聊】torch.nn.init 初始化:
https://blog.csdn.net/ViatorSun/article/details/119619246?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165018334316781683973823%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=165018334316781683973823&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-119619246.142v9control,157v4control&utm_term=nn.init.&spm=1018.2226.3001.4187)
②预训练初始化
拿别人已经训练好的模型作为初值,我用的是Glove,文件中的内容是:<单词,对应的向量>,这样就不用自己去训练一个来了,里面本身就存在距离等关系了。
用pytorch实现的代码参考:【基于Pytorch的torch.nn.embedding()实现词嵌入层:https://blog.csdn.net/weixin_43646592/article/details/119180298?spm=1001.2014.3001.5501】
2.2 卷积层:Conv
进行各个向量的线性乘积求和
对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器 filter)做内积(逐个元素相乘再求和)的操作就是所谓的"卷积"操作,也是卷积神经网络的名字来源,如下图显示
在 CNN 中,滤波器 filter(带着一组固定权重的神经元)对局部输入数据进行卷积计算。每计算完一个数据窗口内的局部数据后,数据窗口不断平移滑动,直到计算完所有数据。计算过程中,有这么几个参数:
(1)深度 depth:即神经元个数,决定输出的 depth 厚度。同时代表滤波器个数
(2)步长 stride:决定滑动多少步可以到边缘
(3)填充值 zero-padding:在外围边缘补充若干圈 0,方便从初始位置以步长为单位可以刚好滑倒末尾位置,通俗地讲就是为了总长能被步长整除
拿下面的动图作为例子
左边是输入(773 中,7*7 代表图像的长宽,3 代表 RGB 三个颜色通道)
中间部分是两个不同的滤波器 Filter w0、Filter w1
最右边则是两个不同的输出
从图中可以看到:
(1)深度 depth:有两个神经元,即两个滤波器,depth=2
(2)步长stride:数据窗口每次移动 2 个步长,取 3*3 的局部数据,即 stride=2
(3)填充值zero-padding:zero-padding=1
每次滤波器都是针对某一局部的数据窗口进行卷积,这就是所谓的 CNN 中的局部感知机制。
可以得到:经过卷积后的图像长宽计算公式
2.3 激励层:Relu
绝大部分神经网络采用的激励函数都是 Relu,它的优点是收敛快,求梯度简单,其图形表示如下
2.4 池化层:Pool
池化,简言之,就是取某个区域的平均值或最大(最小)值,如下图所示
上图所展示的是取区域最大值,即左上角 2x2 的矩阵中 6 最大,右上角 2x2 的矩阵中 8 最大,左下角 2x2 的矩阵中 3 最大,右下角 2x2 的矩阵中 4 最大,所以得到上图右边部分的结果:6 8 3 4
2.5 全连接层
参考文章:【CNN基础知识——全连接层(Fully Connected Layer):https://zhuanlan.zhihu.com/p/78760688】
全连接层就是将最后一层卷积得到的特征图(矩阵)展开成一维向量,并为分类器提供输入。
全连接层的作用:全连接层在整个网络卷积神经网络中起到“分类器”的作用。如果说卷积层、池化层和激活函数等操作是将原始数据映射到隐层特征空间的话(特征提取+选择的过程),全连接层则起到将学到的特征表示映射到样本的标记空间的作用。换句话说,就是把特征整合到一起(高度提纯特征),方便交给最后的分类器或者回归。
三、深度学习文本分类模型
1、fastText
极致简单.
原理是把句子中所有的词向量进行平均(某种意义上可以理解为只有一个avg-pooling特殊CNN),然后直接 softmax 层。其实文章也加入了一些 n-gram 特征的 trick 来捕获局部序列信息。带来的思考是文本分类问题是有一些“线性”问题的部分,也就是说不必做过多的非线性转换、特征组合即可捕获很多分类信息,因此有些任务即便简单的模型便可以搞定了。
fastText 中的网络结果是完全没有考虑词序信息的,而它用的 n-gram 特征 trick 恰恰说明了局部序列信息的重要意义。
2、TextCNN
卷积神经网络(CNN Convolutional Neural Network)核心点在于可以捕捉局部相关性,具体到文本分类任务中可以利用CNN来提取句子中类似 n-gram 的关键信息。
2.1 流程解释
解释下图:
(1)最左边图案: (数据输入层)
feature map 是将一句话中的各个词通过 WordEmbedding 得到的,feature map 的宽为 embedding 的维度,长为一句话的单词数量。例如下图中,很明显就是用一个 6 维的向量去编码每个词,并且一句话中有 9 个词
之所以有两张 feature map,你可以理解为 batchsize 为 2
(2)第二个图案:(卷积层)
其中,红色的框代表的就是卷积核。而且很明显可以看出,这是一个长宽不等的卷积核。有意思的是,卷积核的宽可以认为是 n-gram,比方说下图卷积核宽为 2,所以同时考虑了 “wait” 和 “for” 两个单词的词向量,因此可以认为该卷积是一个类似于 bigram 的模型
(3)后面:激活、池化、全连接层
2.2 详细过程
从左到右看,有3个区域(2,3,4),每个区域有两个滤波器;每个区域有两个特征映射;取每个区域的最大值作为新的输出值;最后接一层全连接的 softmax 层,输出每个类别的概率。
特征:这里的特征就是词向量,有静态(static)和非静态(non-static)方式。static方式采用比如word2vec预训练的词向量,训练过程不更新词向量,实质上属于迁移学习了,特别是数据量比较小的情况下,采用静态的词向量往往效果不错。non-static则是在训练过程中更新词向量。推荐的方式是 non-static 中的 fine-tunning方式,它是以预训练(pre-train)的word2vec向量初始化词向量,训练过程中调整词向量,能加速收敛,当然如果有充足的训练数据和资源,直接随机初始化词向量效果也是可以的。
名词解释
1)通道(Channels):图像中可以利用 (R, G, B) 作为不同channel(如上是2,3,4),而文本的输入的channel通常是不同方式的embedding方式(比如 word2vec或Glove),实践中也有利用静态词向量和fine-tunning词向量作为不同channel的做法。
2)一维卷积(conv-1d):图像是二维数据,经过词向量表达的文本为一维数据,因此在TextCNN卷积用的是一维卷积。一维卷积带来的问题是需要设计通过不同 filter_size 的 filter 获取不同宽度的视野。
3)Pooling层:利用CNN解决文本分类问题的文章还是很多的,比如这篇 A Convolutional Neural Network for Modelling Sentences 最有意思的输入是在 pooling 改成 (dynamic) k-max pooling ,pooling阶段保留 k 个最大的信息,保留了全局的序列信息。比如在情感分析场景,举个例子:
“ 我觉得这个地方景色还不错,但是人也实在太多了 ”
虽然前半部分体现情感是正向的,全局文本表达的是偏负面的情感,利用 k-max pooling能够很好捕捉这类信息。
TextCNN 的 PyTorch 实现:参考:https://wmathor.com/index.php/archives/1445/
尽管TextCNN能够在很多任务里面能有不错的表现,但CNN有个最大问题是固定 filter_size 的视野,一方面无法建模更长的序列信息,另一方面 filter_size 的超参调节也很繁琐。CNN本质是做文本的特征表达工作,而自然语言处理中更常用的是递归神经网络(RNN, Recurrent Neural Network),能够更好的表达上下文信息。具体在文本分类任务中,Bi-directional RNN(实际使用的是双向LSTM)从某种意义上可以理解为可以捕获变长且双向的的 “n-gram” 信息。
RNN循环神经网络
一、参考资料
1、(超详细!!)Pytorch循环神经网络(RNN)快速入门与实战:https://blog.csdn.net/weixin_45727931/article/details/114369073
2、(史上最小白之RNN详解):https://blog.csdn.net/Tink1995/article/details/104868903
二、归纳理解和流程解释
1、结构和流程
基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。RNN 是包含循环的网络,允许信息的持久化。结构可以展开显示如下:
进行RNN分类时,大概思路是:
在RNN的基础上,也有LSTM(RNN 长短期记忆循环神经网络)和GRU(RNN 门循环单元循环神经网络),这里只用了rnn
2、具体描述
数据输入层:这里和上面CNN中的一样,都是进行词嵌入,获得稠密的词向量,后面的隐藏层、激活层和全连接层和CNN对应的部分差别也不大,同时如果是pytorch,也可以使用其内置函数
三、部分网络
1、BiRNN
结构:
BiRNN在RNN的基础上增加了一层隐藏层,这层隐藏层中同样会进行信息传递,两个隐藏层值地计算方式也完全相同,只不过这次信息不是从前往后传,而是从后往前传,这样不仅能考虑到前文的信息而且能考虑到后文的信息了。
实现:比如一句话,“我爱NLP”,进行分词后是[“我”,“爱”,“NLP”],输入[[“我”],[“爱”],[“NLP”]],计算forward layer隐藏层值,然后将输入数据翻转成[[“NLP”],[“爱”],[“我”]],计算backward layer 隐藏层值,然后将两个隐藏层的值进行拼接,再输出来
2、DRNN 深层RNN
上图是DRNN的结构图,每一个红框里面都是一个BiRNN,然后一层BiRNN的输出值再作为另一个BiRNN的输入。多个BiRNN堆叠起来就成了DRNN。