天天看点

深度学习与文本分类总结

转自:https://blog.csdn.net/liuchonge/article/details/77140719

https://blog.csdn.net/liuchonge/article/details/77585222

前面一段时间一直忙着参加知乎看山杯机器学习挑战赛,现在比赛结束了想着总结一下最近的收获。因为这是一个多标签多类别的文本分类问题,而且题目非常适合用深度学习相关的知识去做,正好结合着这个竞赛把之前一段时间的学习成果检验一下。接下来我会分成常用模型总结、多标签/多类别专题、竞赛实战三部分进行介绍。 

首先我们先来总结一下文本分类中常用的几个深度学习模型,这里可以参考brightsmart大神在github上面开源出来的代码,自己在做竞赛的时候也进行了参考,收获很大,下面我也会部分引用其代码来阐述。他给出了几乎可以用于文本分类的所有基础模型及相关代码实现(基于TensorFlow),是一份很棒的总结!接下来我们详细的介绍一下每个模型的原理。

FastText

正好最近做商品分类的时候用到这个模型,了解了一下,是facebook在2016年提出来的模型,代码可以直接使用这里的。这个模型其实算不上深度学习,他跟word2vec的模型极其相似,即输入层是文本中的单词,然后经过一个嵌入层将单词转化为词向量,接下来对文本中所有的词进行求平均的操作得到一个文本的向量,然后再经过一个输出层映射到所有类别中,可以参考Bag of Tricks for Efficient Text Classification这篇论文,里面还详细论述了如何使用n-gram feature考虑单词的顺序关系,以及如何使用Hierarchical softmax机制加速softmax函数的计算速度。模型的原理图如下所示: 

深度学习与文本分类总结
  1. 这种模型的优点在于简单,无论训练还是预测的速度都很快,比其他深度学习模型高了几个量级
  2. 缺点是模型过于简单,准确度较低。(但是我听说有人只用这个模型竞赛里就做到了0.4的准确度,很厉害)

这里想说的是很多公司的实际场景里面,他们的数据并不像我们平时跑实验那么完美,各种人工标注,数据量也很大等等,很多应用的数据量又小、又很杂乱、甚至还没有标记==,所以那些深度学习的模型并不一定能派上很大的用场,反而这种简单快速的模型用的很多。这里也可以看一下其模型构建部分的代码,真的很简单: 

深度学习与文本分类总结

TextCNN

这个模型我们就不再赘述了,放张图镇楼。很经典想要了解的可以戳下面几个链接: 

深度学习与文本分类总结
  1. 论文Convolutional Neural Networks for Sentence Classification
  2. 我写的对模型架构的理解
  3. dennybritz使用TensorFlow实现的代码
  4. 我写的分析上面代码的博客

TextRNN

这种模型与TextCNN很像,只不过是把上面的Conv+Pooling替换成了Bi-LSTM,最后将两个方向上的输出进行拼接再传给输出层即可。但是这种模型仅仅是对TextCNN应用到RNN上进行的一个小改动,效果并不是很好。因为RNN模型在训练时速度很慢,所以并不推荐使用这种方法。

RCNN

这个模型是在Recurrent Convolutional Neural Network for Text Classification一文中提出的模型,架构如下图所示: 

深度学习与文本分类总结

这种模型的想法是在word embedding的基础上,求解每个单词左边和右边上下文的表示,然后将三者融合在一起作为单词的representation。在经过隐藏层、pooling层、输出层得到文本的representation。采用了一种recurrent的方式替代CNN中的卷积层。这样做的好处是,每个单词最终的表示都不仅仅是一个单词的表示这么简单,而是融合了其上下文信息,可以更好地反映其含义,下面跟一个max-pooling层相当于取出对文本信息贡献较大的单词及其组合,这样我们就可以得到其分类。具体图中的每个元素可以按照下面的公式计算: 

cl和cr是上下文representation,等于前面一个词的上下文表示与当前单词的embedding分别乘以权重参数再组合起来。最终的单词表示xi为cl、embed、cr三者的联合。在接下来将其通过一层神经网络得到yi。

深度学习与文本分类总结
深度学习与文本分类总结
深度学习与文本分类总结

这种方法相比TextRNN而言,组合了单词之间的上下文信息,可以更好的得到文本中的长依赖关系。而且相比RNN来讲,熟练速度更快,基本上可以与TextCNN达到相同的效果。也是一种十分优秀的文本分类模型。

Char CNN、Char RNN

这两种模型都是从char级别开始进行文本分类的方法,在这之前我已经对两种模型进行过分析和实现。可以参考我之前的几篇文章进行了解,由于参赛的时间有限,所以在竞赛过程中并未使用这两种方法进行检验效果。原因是官方提供了词向量和字符向量,但是据别的参赛选手反应使用字符向量效果普遍不好。而且官方给的语聊是经过脱敏处理的,并不适合使用char-cnn模型进行建模。

  • 字符级卷积神经网络(Char-CNN)实现文本分类–模型介绍与TensorFlow实现
  • 使用TensorFlow实现RNN模型入门篇2–char-rnn语言建模模型

HAN

这是Hierarchical Attention Network for Document Classification论文中提出的模型,这部分内容可以参考我之前的两篇文章,已经对模型和tf实现做了详细的介绍:

  • HAN模型介绍
  • 使用TensorFlow实现HAN代码详解
深度学习与文本分类总结
深度学习与文本分类总结

其基本思路就是将文本按层次分成单词、句子、文本三层关系,然后分别用两个Bi-LSTM模型去建模word-sentence、sentence-doc的模型。而且在每个模型中都引入了Attention机制来捕获更长的依赖关系,从而得出不同词/句子在构建句子/文本时的重要程度。这种模型相对来说效果在RNN模型中还是算不错的,因为它综合考虑了文本结构、词句的重要性等因素。

Dynamic Memory Network

这个模型是“Ask Me Anything: Dynamic Memory Networks for Natural Language Processing”一文提出来的。他的思路是所有的NLP任务都可以归为QA任务,也就是由输入、问题、答案构成。所以DMN是构建了一个QA的模型,然后也可以用于分类、翻译、序列数据等多重任务中。其模型主要有四部分组成:

深度学习与文本分类总结

这里输入是一段话,然后question相当于一种门控机制,会用Attention机制选择性的将input中的信息保存在episodic memory当中。接下来episodic memory的输出在经过answer模块产生问题的答案。具体的每个模块细节如下图所示:

深度学习与文本分类总结
  1. 输入模块的作用是将输入的文本表示成向量,这里采用RNN模型作为文本表示的模型。如果输入是一句话就使用RNN的hidden state作为其representation,如果输入是多句话,则在每句话后面添加标识符,然后给每句话都生成一个representation,如图中蓝色的小条。
  2. question模块的作用是将question表示成向量,与输入模块相似同样使用RNN作为模型,将最终的hidden state作为输出向量传入episodic memory模块,作为其初始状态。
  3. episodic memory模块通过迭代产生记忆。输入模块产生的句子表示会根据question模块进行注意力机制的加权,按照问题针对性的选择出相应的表示。记忆模块的两条线分别代表带着问题q第一次阅读input的记忆,以及带着问题q第二次阅读的记忆。
  4. answer module是根据episodic memory的最后一个memory作为模型的初始状态,这里使用GRU进行建模。然后生成最终的答案

这部分的详细介绍可以参考码农场对这篇论文的笔记。

Entity Network

在看到brightmart的分享之前并未听说过这个模型,后来查了一下,发现是2017年ICLR刚发的文章“Tracking the World State with Recurrent Entity Networks”,这些大牛们真的是紧跟业内最前沿==这篇论文等我之后有时间会专门去研究一下然后写篇博客来讲,这里先不说。放张模型的架构图感受一下~~ 

深度学习与文本分类总结

Attention is all your need

这是谷歌今年刚发的论文,对标Facebook之前发布的“Attention is all your need”。由于时间关系同样还没有仔细阅读过,先写在这占个坑位吧,看之后什么时候有时间实现一下。

总结

至此我们已经把主流的文本分类中会用到的深度学习模型说了个遍,从CNN到RNN,从seq2seq到Attention,我觉得这些模型各有优劣,在不同的任务上会有不同的表现效果。但是基本上来讲如果追求简单速度,可以使用fasttext,想要提升效果先可以试试textCNN和RCNN这两种模型,在接下来可以试试HAN这类LSTM或者GRU的模型,剩下几种也会有不错的效果,可以根据自己的精力和项目要求判断是否进行尝试。因为有的并不是专门为了文本分类设计的,所以效果上可能更需要自己针对具体的任务进行调整。

但是其实深度学习里面模型可能只是一部分,不同的模型肯定会取得不一样的效果。但是更加重要的参数调整,因为按照具体的任务和数据不一样,参数的选择会给最终的效果带来很大的差距。就单纯地按照这次竞赛来讲,相同的单模型分数会在0.30-0.41范围中波动,然而参数的选择和调优却是十分麻烦和困难的事情,所以很多人称之为黑盒==是门学问,等之后竞赛前排大神出了分享之后,我也会参考他们的经验写一下我对于这部分的理解。

上一篇博客中我们已经总结了文本分类中常用的深度学习模型,因为知乎的本次竞赛是多标签的文本分类任务,这也是我第一次接触多标签分类,所以想单独写一篇博客来记录这方面的相关知识。 

在这里首先列出几篇参考的文章:

  1. 基于神经网络的多标签分类可以追溯到周志华在2006年发表的文章: Multi-Label Neural Networks with Applications to Functional Genomics and Text Categorization。其贡献在于提出了BP-MLL(多标签反向传播)以及新的误差函数: 
    深度学习与文本分类总结
  2. 然后是一篇基于周志华文章改进的论文:Large-scale Multi-label Text Classification Revisiting Neural Networks。这篇文章提出使用Adagrad,dropout等技术,此外还提出使用标准的交叉熵函数作为目标函数效果更好。
  3. 上面的文章还是使用普通的神经网络进行分类,接下来就出现了基于深度学习模型的方法。比如:Large Scale Multi-label Text Classification with Semantic Word Vectors。这篇文章很简单,就是把TextCNN和GRU直接用到多标签文本分类里,最后根据一个阈值alpha来确定样本是否属于某个类别。
  4. Improved Neural Network-based Multi-label Classification with Better Initialization Leveraging Label Co-occurrence。这篇文章提出了一种根据类别标签之间的共现关系来初始化最后输出层参数的方法。其也是基于TextCNN,不同之处是最后一个输出层的权重不使用随机初始化,而是根据标签之间的共现关系进行初始化。据作者说这样可以获得标签之间的关系,这样有一种聚类的效果。相似的样本会标记为相同的标签。此外他还提出了损失函数的计算方法。具体的细节部分可以去看相关论文。 
    深度学习与文本分类总结
    深度学习与文本分类总结
  5. 模型上的改进:Ensemble Application of Convolutional and Recurrent Neural Networks for Multi-label Text Categorization。这篇论文主要提出了一种CNN和RNN融合的机制,将CNN的输出作为RNN的初始状态然后进行类别的预测。架构图如下所示: 
    深度学习与文本分类总结

上面几篇论文是我在做竞赛的过程中阅读的几篇相关论文,每篇都会有一定的特点,但是实际的效果如何其实并不会像论文中提到的那样,也有可能是自己调参跳的不好。但是论文里面提到的创新点还是值得我们学习的。然后我们来总结一下多标签文本分类相关的东西,这里参考上面第三篇论文。首先来讲,多标签分类的算法可以分成下面三种类型:

  1. multi-label classification:将标签分成Y和Y的补集两个分区
  2. label ranking:将标签进行排序,排名靠前的就是预测为相关的类别
  3. multi-label ranking:上述二者的综合,同时产生分区和rank。设置阈值函数进行判断

此外,我们还可以使用Binary Relevance(BR)算法,将多标签问题转化为L个二分类问题。训练L个模型,每个模型处理一个类别,这样做的好处是可以并行训练L个模型,降低训练复杂度,而且可以方便的增删标签数量。最终只需要把结果合并成一个输出向量就可以了。但是也有一点的缺点,比如说由于分开训练L个模型,所以忽视了标签之间的相关性。而且当当数据集出现类别不均衡等现象时,效果也会变差。

上面说了几种如何看待多标签分类问题的思路和看法。其实就是将多标签分类进行转化。我感觉比较常用的应该是ranking和BR的方法。再反过来看这次知乎的竞赛,其实我看了前几名的解决方案,大都是只用了深度学习模型的堆砌,比如说CNN,RNN然后再加上模型融合和数据增强的一些手段得到了比较好的分数。但是我之前也采访过知乎机器学习团队的负责人,他当时也明确的表明现在选手使用的方法还都是比较老派,没有什么十分大的创新点出来,而且几乎没怎么利用标签之间的关系等信息。这里我就说一下我在竞赛里面做过的几种尝试。

1,首先来分析一下知乎所提供的数据都有哪些特点,第一给了1999个标签之间的父子关系,这样我们就可以将其构成一张树状关系图。

2,其次他给出了每个label的描述信息,我觉得这个信息是最重要的,因为这样我们最简单也可以计算样本和1999个标签之间的相似性然后排名取出前5个就可以粗略地进行类别标注。当然我们在结合深度学习的时候可以将其放在最后一层跟CNN的输出进行结合计算。我当时采用的方法是,将样本和1999个标签的title分别经过CNN进行计算,然后再将得到的文本表示和标签信息进行一个相似性计算得到每个类别的相似性概率表示。但是这种方法的缺点在于速度太慢,我当时训练了一天两夜才跑了2个epoch(CPU),所以中途放弃了,至今也不知道效果如何==

3,使用上面第四篇文献中所提出的方法,首先对数据进行预处理,得到所有训练数据中所出现的标签共现信息,取共现次数最高的前N个标签对作为初始化的依据。该模型的想法是通过这种自定义初始化网络权重的方法让模型学习到这种标签的共现信息,从而更加准确地进行类别预测。

4,在查阅文献的过程中,看到了一篇“Multi-Label Classification on Tree- and DAG-Structured Hierarchies”的论文,其提出将标签信息构建成有向无环图或者树状的分层结构。但是该方法是基于传统机器学习模型做的,由于竞赛过程中时间有限,所以并未加以尝试。此外,我还考虑是否可以将标签信息使用类似于word2vec中的分层softmax的机制进行处理。总之是尽量的把标签之间的父子关系图利用起来,以增强分类的准确度。这里也不过是一些自己的想法罢了,还并未进行实践,也希望有懂这方面知识的同学可以指点一二。

至此,关于多标签文本分类相关的知识就暂时总结到这里,其实也就是看的几篇论文和知乎竞赛中的一些思考。接下来抽时间把自己参加竞赛的一些具体的代码等再整理出一篇博客就将完结这个系列。

继续阅读