基于Text-CNN模型的中文文本分类实战

from:https://www.jianshu.com/p/f69e8a306862php

 

深度学习在文本分类中的鼻祖-TextCNNhtml

1.文本分类

转眼学生生涯就结束了,在家待就业期间正好有一段空闲期,能够对曾经感兴趣的一些知识点进行总结。java

本文介绍NLP中文本分类任务中核心流程进行了系统的介绍,文末给出一个基于Text-CNN模型在搜狗新闻数据集上二分类的Demo。python

文本分类是天然语言处理领域最活跃的研究方向之一,从样本数据的分类标签是否互斥上来讲,能够分为文本多分类与文本多标签分类。git

文本分类github

目前文本分类在工业界的应用场景很是广泛,重新闻的分类、商品评论信息的情感分类到微博信息打标签辅助推荐系统,了解文本分类技术是NLP初学者比较好的切入点,较简单且应用场景高频。web

2.数据准备

在机器学习领域有一句话:数据决定了模型最终的高度,不断优化的模型只不过是为了避免断逼近这个高度而已。编程

文本分类做为一种有监督学习的任务,毫无疑问的须要一个可用于有监督学习的语料集(X,Y)。本文中使用如下标记,X为特征,文本分类中即为文本序列,Y是标签,即文本的分类名称。数组

机器学习与传统编程技术的明显区别就是:机器学习是以数据为驱动的,传统的编程中,咱们核心任务是人工设计分类规则(指令代码),而后实现输入特征X得到分类标签Y。而在机器学习的方式中,咱们首要的是得到一个高质量的、大数据量的有监督语料集(X,Y),而后机器学习的方式会自动的从已构建的数据集上概括出(训练出)一套分类规则(分类模型),最后咱们利用得到的分类规则来实现对未标记文本的分类。网络

机器学习VS传统编程

换言之,传统的编程方式输入的是指令代码,而机器学习输入的是结构化数据

所以,在机器学习任务中,数据的质量与数量对最终模型的预测结果好坏具备决定性的做用。

常言道:Garbage in, garbage out!

在文本分类中,语料集(X,Y)的质量、数量决定了文本分类模型的分类效果。

语料集的质量:即数据集的特征X对应的标签Y是否标记的正确,通常在众包平台中会采用多人重复标记,而后基于投票的机制来控制语料集的标记质量。
语料集的数量:有监督语料集的标注复杂度,想要得到海量的高质量语料集的成本是十分高昂的,这也限制的语料集的数量。

在实际的文本分类任务中,通常经过搜集开源的数据集,或者利用爬虫获取结构化的网页信息来构建特定任务的语料集。不过,我仍是更喜欢关注一些公开的竞赛项目,可以得到企业准备的高质量、应对真实业务场景的数据集,例如:kaggle、知乎的看山杯、mrc2018-cipsc等,但大多数状况下企业只给脱敏以后的数据🤣.......

 

收藏数据集第一,比赛名次第二......

搜狗的新闻语料集:http://www.sogou.com/labs/resource/cs.php

3.文本的预处理

文本的预处理,主要针对剔除无心义的符号信息,或其它的冗余信息。例如,在使用爬虫获取的语料集上可能存在一些html的标签,这些符号对于文本分类任务来讲应该是冗余的无心义信息,能够剔除掉。

此外,针对中文、日语等无空格切分字词的语言,还须要进行分词处理,将一段文本序列划分为合理的词(字)序列。

英文中天生的就有空格把每一个词汇分割开来,因此不须要分词操做,但因为英文存在时态、缩写等问题,在预处理阶段会有词干提取、词性还原、大小写转换等。

中文分词的工具备很是多的方案,我通常习惯于使用Python版的JieBa分词工具包来进行分词的操做,使用很是的简单,使用pip install jieba就能够很方便的安装该工具包,jieba经常使用的API能够查看GitHub主页的实例。

文本预处理

 

推荐阅读:
中文分词原理【https://www.jianshu.com/p/6c085bf1086f
JieBa的GitHub官网:https://github.com/fxsjy/jieba

3.文本的数值化【词向量技术】

文本的数值化,即便用数字表明特定的词汇,由于计算机没法直接处理人类创造的词汇。为了让计算机可以理解词汇,咱们须要将词汇信息映射到一个数值化的语义空间中,这个语义空间咱们能够称之为词向量空间(词向量模型)。

文本的数值化方式有不少种,例如:TF-IDF、BOW、One-Hot、分布式的表示方式(word2vec、Glove)等。

我通常经常使用的就是最经典的word2vec工具,该工具在NLP领域具备很是重要的意义!

word2ve工具,它是一种无监督的学习模型,能够在一个语料集上(不须要标记,主要思想是“具备类似邻近词分布的中心词之之间具备必定的语义类似度”),实现词汇信息到语义空间的映射,最终得到一个词向量模型(每一个词汇对应一个指定维度的数组)。

两种模型两种优化方式

它的核心优点就是实现了两个词汇信息之间的语义类似度的可计算性,也能够理解为是一种迁移学习的思想,word2vec获取的意义空间信息做为后续文本分类模型的输入。

python 中使用word2vec工具也是很是的便利,经过pip install gensim安装gensim工具包,此包汇总包含了word2vec工具。

【注:Ubuntu与Mac系统安装的gensim包中word2vec的API存在一些差别!】

Gensim官网:https://radimrehurek.com/gensim/models/word2vec.html

深度学习中将单词表示成向量是很广泛的状况,深度学习模型以词向量序列的形式读取序列化的单词,而不是以文本的形式。

 

今天大多数用于天然语言处理的深度学习模型都依赖词向量来表明单个单词的含义。对于不太熟悉这领域的人而言,能够这样简单的理解:咱们把每一种语言中的每个单词都与一串被叫作向量的数字联系起来了。

 

词向量

以上就是深度学习模型须要的数据格式的核心处理流程,在整个处理过程当中样本数据的处理流程以下图所示:

 

数据处理流程


4.文本分类模型

文本分类模型,能够大致上分为基于传统机器学习的文本分类模型,基于深度学习的文本分类模型,目前基于深度学习模型的文本分类模型已经成为了主流,下面基于CNN的文本分类模型。

深度学习的优点

文本分类模型,从最经典的2013年Kim提出Text-CNN模型开始,深度学习模型在文本分类任务上具备普遍的应用。2016年Kim跳槽FaceBook后提出了工业界的文本分类模型的“新宠”—FastText。

文本分类模型

为了实现文本分类模型,须要借助开源的深度学习框架,这样在开发中就不须要本身从零实现整个深度学习模型的各个功能模块。若是你以前作过Java Web开发的话,确定也使用过SSH或SSM等框架来简化你的开发工做。

深度学习框架有不少优秀的框架,我通常使用比较流行的tensorflow计算框架,该框架的使用者比较多,能够查阅的学习资料很是多,Github上的开源代码也比较多,很是有利于咱们学习。

tensorflow全家桶

文本分类的技术路线【研二时实验室内部的技术分享PPT】:

文本分类技术路线

 

目前深度学习在NLP的文本分类任务中已经具备比较普遍的探究,其中经典的深度学习模型结构有如下三种:

 

三种经典基于深度学习的文本分类模型

本文选择使用2013年Kim提出的Text-CNN模型做为文本分类模型,经过验证明验以及业界的共识,在文本分类任务中,CNN模型已经可以取到比较好的结果,虽然在某些数据集上效果可能会比RNN稍差一点,可是CNN模型训练的效率更高。因此,通常认为CNN模型在文本分类任务中是兼具效率与质量的理想模型。

卷积神经网络(CNN)的特色:

CNN的三个优势:

  1. sparse interaction(稀疏的交互)
  2. parameter sharing(参数共享)
  3. equivalent respresentation(等价表示)。

经典的简化卷积公式表示以下:

 

CNN中的卷积操做的计算公式

假设每一个词用三维向量表示,左边是4个词,右边是卷积矩阵,那么获得输出为:

卷积层的输出

若是基于这个结果作1-MaxPool池化(最大值池化),那么就取卷积层结果 o 中的最大值,即提取最显著的特征。

针对海量的文本多分类数据,也能够尝试一下浅层的深度学习模型FastText模型,该模型的分类效率更高。

Text-CNN模型结构

Kim提出的经典Text-CNN模型的总体网络架构如图所示,若是你学习过CNN或者CNN在图像中的使用,应该很容易就理解,由于该模型就是一个最简单、基础的CNN网络结构。

整个模型由四部分构成:输入层、卷积层、池化层、全链接层。

1.输入层(词嵌入层):

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的方向更新输入层的各个词汇对应的词向量。

2.卷积层:

在NLP领域通常卷积核只进行一维的滑动,即卷积核的宽度与词向量的维度等宽,卷积核只进行一维的滑动。

在Text-CNN模型中通常使用多个不一样尺寸的卷积核。卷积核的高度,即窗口值,能够理解为N-gram模型中的N,即利用的局部词序的长度,窗口值也是一个超参数,须要在任务中尝试,通常选取2-8之间的值。

卷积层

3.池化层:

在Text-CNN模型的池化层中使用了Max-pool(最大值池化),即减小了模型 的参数,又保证了在不定长的卷基层的输出上得到一个定长的全链接层的输入。

池化层

池化层除了最大值池化以外,也有论文讨论过 Top K最大值池化,即选取每个卷积层输出的Top k个最大值做为池化层的输出。

卷积层与池化层在分类模型的核心做用就是特征提取的功能,从输入的定长文本序列中,利用局部词序信息,提取初级的特征,并组合初级的特征为高级特征,经过卷积与池化操做,省去了传统机器学习中的特征工程的步骤。
但TextCNN的一个明显缺点就是,卷积、池化操做丢失了文本序列中的词汇的顺序、位置信息,比较难以捕获文本序列中的否认、反义等语义信息。

4.全链接层:

全链接层的做用就是分类器,原始的Text-CNN模型使用了只有一层隐藏层的全链接网络,至关于把卷积与池化层提取的特征输入到一个LR分类器中进行分类。

至此,Text-CNN的模型结构就算大致了解了,有人把深度学习模型看做一个黑盒子,知道格式化的输入,咱们就能够利用别人搭建好的模型框架训练在本身的数据集上实现必定的功能。可是在不一样的数据集上,模型的最佳状态也不惟一,这就需须要咱们在新的数据集上须要进行调优(调参)。

5.模型的效果评估与调优

针对分类问题,通常可使用准确率、召回率、F1值、混淆矩阵等指标,在文本多标签分类中通常还会考虑标签的位置加权等问题。

分类模型中的主要参数:词向量的维度、卷积核的个数、卷积核的窗口值、L2的参数、DropOut的参数、学习率等。

这是在模型优化的过程当中须要重点关注的参数。此外,通常数据集的类别不均衡问题对模型的影响也是比较显著的,能够尝试使用不一样的方法,评估不一样方案的模型效果。

文本分类中常常遇到的问题:

1.数据集类别不均衡

即语料集中,各个类别下的样本数量差别较大,会影响最终文本分类模型的效果。
主要存在两类解决方案:
(1)调整数据:数据加强处理,NLP中通常随分词后的词序列进行随机的打乱顺序、丢弃某些词汇而后分层的采样的方式来构造新的样本数据。

数据加强

(2)使用代价敏感函数:例如图像识别中的Focal Loss等。

2.文本分类模型的泛化能力

首先,对于一个未知的样本数据,分类模型只能给出分类标签中的一个,没法解决不属于分类标签体系的样本。

咱们没法预知将来的数据会是什么样的,也不能保证将来的全部分类状况在训练集中都已经出现过!

剩下影响分类模型泛化能力的就是模型过拟合的问题了。

 

过拟合问题

如何防止过拟合?那就是老生常谈的问题了:
(1)数据上:交叉验证
(2)模型上:使用DropOut、BatchNorm、正则项、Early Stop。

3.关于模型的上线方案:

一、基于Java的:
请参考:https://www.ioiogoo.cn/2018/04/03/java%E8%B0%83%E7%94%A8keras%E3%80%81tensorflow%E6%A8%A1%E5%9E%8B/
二、基于Flask等python的web框架:
请参考:https://guillaumegenthial.github.io/serving.html

序列标注模型的上线

 

三、基于google官方的tensorflow Serving框架:
请参考:https://www.jianshu.com/p/c1cd2d127ae2
阿里的基于容器部署的方案:https://yq.aliyun.com/articles/60894?spm=a2c4e.11153959.blogcont60601.11.815eea72lw2ij

6.基于Text-CNN模型的中文文本分类Demo:

我从搜狗的开源的的新闻数据集(small版)中,选择了两个类别的数据:计算机与交通两个类别,构建了一个中文文本二分类的数据集。

搜狗数据集的语料

实现文本二分类的Demo代码以及脚本运行的说明放在GitHub中:
https://github.com/x-hacker/CNN_ChineseTextBinaryClassify

以上就是简单的介绍了NLP中文本分类所涉及的主要流程,并给出了一个中文文本二分类的Demo代码。下面推荐一些拓展的资料,感兴趣的童鞋能够继续深刻研究。

补充资源: