基于卷积神经网络CNN的文本分类原理和实战
前言
本文介绍了CNN在NLP中的应用:文本分类。
文本分类:是自然语言处理领域最活跃的研究方向之一,目前文本分类在工业界的应用场景非常普遍,从新闻的分类、商品评论信息的情感分类到微博信息打标签辅助推荐系统,
卷积神经网络:主要用来做图片分类、目标检测等图像相关的任务,
文本的预处理
文本的预处理,主要针对剔除无意义的符号信息,或其它的冗余信息。
-
在使用爬虫获取的语料集上可能存在一些html标签,这些符号对于文本分类任务来说应该是冗余的无意义信息,可以剔除掉。
-
分词:针对中文、日语等无空格切分字词的语言,还需要进行分词处理,将一段文本序列划分为合理的词(字)序列。
英文中天生的就有空格把每个词汇分割开来,所以不需要分词操作,但由于英文存在时态、缩写等问题,在预处理阶段会有词干提取、词性还原、大小写转换等。 -
去除停用词。
-
shuffle打乱数据集
中文分词的工具有非常多的方案,我一般习惯于使用Python版的JieBa分词工具包来进行分词的操作,使用非常的简单,使用pip install jieba就可以很方便的安装该工具包,jieba常用的API可以查看GitHub主页的实例。
分词工具
- 中科院计算所NLPIRhttp://ictclas.nlpir.org/nlpir/
- ansj分词器https://github.com/NLPchina/ansj_seg
- 哈工大的LTPhttps://github.com/HIT-SCIR/ltp
- 清华大学THULAChttps://github.com/thunlp/THULAC
- 斯坦福分词器,Java实现的CRF算法。https://nlp.stanford.edu/software/segmenter.shtml
- Hanlp分词器,求解的是最短路径。https://github.com/hankcs/HanLP
- 结巴分词,基于前缀词典,生成句子中所有可能成词所构成的有向无环图 (DAG),采用动态规划查找最大概率路径, 找出基于词频的最大切分组合,对于未登录词,采用了 HMM 模型,使用 Viterbi 算法。https://github.com/yanyiwu/cppjieba
- KCWS分词器(字嵌入+Bi-LSTM+CRF),本质上是序列标注。https://github.com/koth/kcws
- ZParhttps://github.com/frcchang/zpar/releases
- IKAnalyzerhttps://github.com/wks/ik-analyzer
中文分词性能对比可以参考
文本的数值化
文本的数值化,即使用数字代表特定的词汇,因为计算机无法直接处理人类创造的词汇。为了让计算机能够理解词汇,我们需要将词汇信息映射到一个数值化的语义空间中,这个语义空间我们可以称之为词向量空间(词向量模型)。
文本的数值化方式有很多种,例如:TF-IDF、BOW、One-Hot、分布式的表示方式(word2vec、Glove)等。
一般常用的就是最经典的word2vec工具,word2vec工具,它是一种无监督的学习模型,主要思想是“具有相似邻近词分布的中心词之之间具有一定的语义相似度”),实现词汇信息到语义空间的映射,最终获得一个词向量模型(每个词汇对应一个指定维度的数组)。
python 中使用word2vec工具很多,建议使用Gensim,通过pip install gensim安装gensim工具包。
Gensim官网:https://radimrehurek.com/gensim/models/word2vec.html
以上就是深度学习模型需要的数据格式的核心处理流程,在整个处理过程中样本数据的处理流程如下图所示:
243af7b3-e079-4da8-83c4-1dbe3e039b38.png
文本分类模型
文本分类模型,可以大体上分为基于传统机器学习的文本分类模型,基于深度学习的文本分类模型,目前基于深度学习模型的文本分类模型已经成为了主流,下面基于CNN的文本分类模型。
文本分类模型,从最经典的2013年Kim提出Text-CNN模型开始,深度学习模型在文本分类任务上具有广泛的应用。2016年Kim跳槽FaceBook后提出了工业界的文本分类模型的“新宠”—FastText。
本文选择使用2013年Kim提出的Text-CNN模型作为文本分类模型,通过验证实验以及业界的共识,在文本分类任务中,CNN模型已经能够取到比较好的结果,虽然在某些数据集上效果可能会比RNN稍差一点,但是CNN模型训练的效率更高。所以,一般认为CNN模型在文本分类任务中是兼具效率与质量的理想模型。
卷积神经网络(CNN)的特点:
sparse interaction(稀疏的交互)
parameter sharing(参数共享)
equivalent respresentation(等价表示)。
针对海量的文本多分类数据,也可以尝试一下浅层的深度学习模型FastText模型,该模型的分类效率更高。
Kim提出的经典Text-CNN模型的整体网络架构如图所示,
整个模型由四部分构成:输入层、卷积层、池化层、全连接层。
输入层(词嵌入层):
Text-CNN模型的输入层需要输入一个定长的文本序列,我们需要通过分析语料集样本的长度指定一个输入序列的长度L,比L短的样本序列需要填充(自己定义填充符),比L长的序列需要截取。最终输入层输入的是文本序列中各个词汇对应的分布式表示,即词向量。
对于输入层输入的词向量的表达方式,Text-CNN模型的作者Kim在论文中也分析了几个变种的方式:
1.static(静态词向量)
使用预训练的词向量,即利用word2vec、fastText或者Glove等词向量工具,在开放领域数据上进行无监督的学习,获得词汇的具体词向量表示方式,拿来直接作为输入层的输入,并且在TextCNN模型训练过程中不再调整词向量, 这属于迁移学习在NLP领域的一种具体的应用。
2.non-static(非静态词向量)
预训练的词向量+ 动态调整 , 即拿word2vec训练好的词向量初始化, 训练过程中再对词向量进行微调。
3.multiple channel(多通道)
借鉴图像中的RGB三通道的思想, 这里也可以用 static 与 non-static 两种词向量初始化方式来搭建两个通道。
4.CNN-rand(随机初始化)
指定词向量的维度embedding_size后,文本分类模型对不同单词的向量作随机初始化, 后续有监督学习过程中,通过BP的方向更新输入层的各个词汇对应的词向量。
注意事项
1,CNN输入层是大小固定的,所以对于不同文本,找出最大的文本序列,其他的进行填补;
2,词向量要经过大规模数据进行训练;
卷积层:
在NLP领域一般卷积核只进行一维的滑动,即卷积核的宽度与词向量的维度等宽,卷积核只进行一维的滑动。
在Text-CNN模型中一般使用多个不同尺寸的卷积核。卷积核的高度,即窗口值,可以理解为N-gram模型中的N,即利用的局部词序的长度,窗口值也是一个超参数,需要在任务中尝试,一般选取2-8之间的值。
注意事项
1,CNN在文本分类中,卷积核的宽度和词向量的宽度一样,只做一纬滑;
2,CNN的卷积就是对应相乘求和,不需要翻转,和信号处理卷积不同;
3,卷积层包括卷积操作和非线性激活函数,图中f()函数就是非线性激活函数;
4,卷积核有多个,卷积核的参数是通过训练得到的;
池化层:
在Text-CNN模型的池化层中使用了Max-pool(最大值池化),即减少模型的参数,又保证了在不定长的卷基层的输出上获得一个定长的全连接层的输入。
池化层除了最大值池化之外,也有论文讨论过 Top K最大值池化,即选取每一个卷积层输出的Top k个最大值作为池化层的输出。
卷积层与池化层在分类模型的核心作用就是提取特征,从输入的定长文本序列中,利用局部词序信息,提取初级的特征,并组合初级的特征为高级特征,通过卷积与池化操作,省去了传统机器学习中的特征工程的步骤。
但TextCNN的一个明显缺点就是,卷积、池化操作丢失了文本序列中的词汇的顺序、位置信息,比较难以捕获文本序列中的否定、反义等语义信息。
全连接层:
全连接层的作用就是分类器,原始的Text-CNN模型使用了只有一层隐藏层的全连接网络,相当于把卷积与池化层提取的特征输入到一个LR分类器中进行分类。
CNN的结构:(卷积+非线性激活函数(Relu或tanh)+池化层)× n + 几个全连接层;
深度CNN网络:几个卷积层+几个全连接层
模型的效果评估与调优
针对分类问题,一般可以使用准确率、召回率、F1值、混淆矩阵等指标,在文本多标签分类中一般还会考虑标签的位置加权等问题。
分类模型中的主要参数:词向量的维度、卷积核的个数、卷积核的窗口值、L2的参数、DropOut的参数、学习率等。
这是在模型优化的过程中需要重点关注的参数。此外,一般数据集的类别不均衡问题对模型的影响也是比较显著的,可以尝试使用不同的方法,评估不同方案的模型效果。
TensorFlow实现CNN文本分类
github代码,预训练词向量下载地址:https://nlp.stanford.edu/projects/glove/, 我用的是400,000个词汇的300维Glove词向量。
下面是tensorflow中卷积和池化的函数,拿出来讲解一下。
tf.nn.conv2d
tf.nn.conv2d(input,filter,strides,padding,use_cudnn_on_gpu=None,name=None)
参数:
>>>>input:
一个Tensor,每个元素的数据类型必须为float32或float64。
input的形状:[batch, in_height, in_width, in_channels],
batch为训练过程中每迭代一次迭代数据条数。
in_height, in_width分别为矩阵(图片)的高和宽
in_channels为矩阵(图片)的通道,比如图片可以有RGB三通道。
即输入:(句子个数, 句子长度, embedding尺寸, 通道数)
>>>>filter:
卷积核,也是一个Tensor,元素类型和input类型一致。
filter的形状:[filter_height, filter_width, in_channels, out_channels]
(其中out_channels也是该卷积核的个数)。
参数分别为卷积核的高,宽,输入的channels和输出的channels
卷积核:(卷积核尺寸, embedding尺寸, 通道数, 卷积核个数)
>>>>stride:
步长,长度为4的list,元素类型为int。表示每一维度滑动的步长。其中strides[0] = strides[3] = 1。strides[1]和strides[2]分别表示在hight和width方向的步长。
>>>>padding:
可选参数为"SAME", “VALID”。
SAME表示填充,VALID不填充。
>>>>use_cudnn_on_gpu:
bool类型,有True和False两种选择。
>>>>name:
此操作的名字
tf.nn.max_pool
池化
tf.nn.max_pool(value, ksize, strides, padding, name=None)
参数和卷积很类似:
value:需要池化的输入,池化层通常跟在卷积层后面,所以输入的shape依然是[batch, hei ght, width, channels]。
ksize:池化窗口的大小,四维向量,一般是[1, height, width, 1],前后两个1对应的是batch和channels,都不池化所以为1
strides:步长,和卷积一样,前后都为1,中间两个分表表示窗口在每一个维度上滑动的步长,shape:[1, stride,stride, 1]
padding:‘VALID’ 或’SAME’
返回:一个Tensor,类型不变,shape仍然是[batch, height, width, channels]这种形式
结论
CNN-static和CNN-non-static效果差不多,也就是说词向量经过预训练的效果不错。
关于模型的上线方案:
基于Java的:
请参考:https://www.ioiogoo.cn/2018/04/03/java%E8%B0%83%E7%94%A8keras%E3%80%81tensorflow%E6%A8%A1%E5%9E%8B/
2、基于Flask等python的web框架:
请参考:https://guillaumegenthial.github.io/serving.html
3、基于google官方的tensorflow Serving框架:
请参考:https://www.jianshu.com/p/c1cd2d127ae2
阿里的基于容器部署的方案:https://yq.aliyun.com/articles/60894?spm=a2c4e.11153959.blogcont60601.11.815eea72lw2ij
补充资料
下面推荐一些拓展的资料,感兴趣的童鞋可以继续深入研究。
各种文本分类模型的实例代码:https://github.com/brightmart/text_classification
中文文本分类对比:https://github.com/Edward1Chou/Textclassification
CNN-RNN中文文本分类,基于TensorFlow :https://github.com/gaussic/text-classification-cnn-rnn
参考
- https://www.jianshu.com/p/e6d71a9b1554
- 2014年基于CNN的文本分类模型:Convolutional Neural Networks for Sentence Classification
- 中文分词性能对比可以:(https://blog.csdn.net/Mr_Yener/article/details/85636042)
- 基于TensorFlow的CNN文本分类的实现:https://github.com/dennybritz/cnn-text-classification-tf
- Implementing a CNN for Text Classification in TensorFlow:http://www.wildml.com/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow/
- 文本分类方法对比:https://github.com/brightmart/text_classification
- CNN和RNN文本分类对比:https://github.com/gaussic/text-classification-cnn-rnn
网友评论