文本分类方法及词向量概述

文本分类方法及词向量概述

DataScience Club@BUAA

文本分类应该是自然语言处理中最普遍的一个应用,例如文章主题自动分类、邮件自动分类、垃圾邮件识别、用户情感分类等等。本文将从传统机器学习方法以及深度学习方法解读如何解决文本分类问题。

本文从传统的特征表示方法,到词向量,再到深度学习来阐述。

传统方法

传统文本分类方法遵循机器学习的一般流程,如图所示:

由训练数据,经过预处理后,经过特征工程得到特征表征,进而交给分类器监督训练,得到预测结果。

类似地,特征工程是这一流程中的工作重点,是把数据转化为样本表征(information)的过程,分类器做的事情,是把information转化为结果(knowledge)。

具体到文本分类问题中,经典的特征表示方法有词袋模型(Bag of words)和 tf-idf。

词袋模型故名思议,忽略其词序和语法,句法,将其仅仅看做是一个词集合,使用词袋模型将文本做特征表征就是一个根据词频(term frequency)表示成ones-hot的过程。

sklearn中有CountVectorizer即是它的实现。

sklearn.feature_extraction.text.CountVectorizer

这种表示方法会有什么问题呢,就是停用词对结果的影响非常大。在中文中,

出现次数最多的词是----"的"、"是"、"在"----这一类最常用的词。而这些词一般对于分类任务没有任何帮助。

使用什么方法能将它过滤掉呢?我们可以对每个词一个重要性调整系数,衡量一个词是不是常见词。如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性,正是我们所需要的关键词。TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语料库中的出现次数成反比。这就是tfidf的基本原理。

sklearn中有TfidfVectorizer即是它的实现。

sklearn.feature_extraction.text.TfidfVectorizer

以下短短的20行代码就是使用tf-idf作为特征,LR作为分类器解决kaggle toxic comment比赛的一个非常精巧的代码。

如果一个语料库的词表非常大的情况下,使用这两种特征表示方法,都有非常大的问题:特征稀疏以及不含语序。

对于特征稀疏可以用降维方法解决,如LDA,SVD等可以作用于此,这样就得到降维后的稠密表示,并且能起到挖掘隐含主题的作用。

对于不含语序可以添加n-grams的表示,能在一定程度上捕捉词的语序。sklearn中的tfidfvector可以使用ngram参数来增加n-grams信息。

传统的文本分类方法还有朴素贝叶斯的建模方式,使用贝叶斯公式直接对一句话的分类概率建模。

也可以使用基于词典的方式,但是这种方法有一个问题,需要规则修正双重甚至多重否定。如:尽管今天天气这么好,我也不是很开心呢。在情感分类中要格外注意。

词向量

词向量是NLP在深度学习兴起之后非常有代表性的成果。

传统的文本表示,在表示词的时候,使用one-hot面临特征稀疏以及不隐含语义的问题,无法通过直接衡量两个向量的相似度来衡量语义相关度。

词向量解决了这个问题,预训练的词向量可以提升很多NLP深度模型的性能,并且隐含向量的线性性质,聚类性质,在下文中我们将详细讲解。

比如蛤相关的单词都在向量空间中比较接近。(聚类性质)

也会出现 北京 - 中国 = 东京 - 日本 (线性性质)

词向量比较有名的模型有斯坦福大学的GloVe(矩阵分解方法),谷歌的word2vec和facebook的fasttext(神经网络方法)。

Glove的原理非常类似于推荐系统中的LSI模型,通过对词贡献矩阵的分解,得到降维表示。

下图同是

[I like deep learning], [i enjoy flying],[i like nlp]]

词贡献矩阵在窗口大小为1的时候如下所示:

对于这个矩阵使用SGD做一个如下损失函数的分解。f函数是词贡献值X的约束,b是bias向量,w是词向量

所有的词向量的获取都是基于一个基本的语言性质:相近词的相关性更大。矩阵分解方法基于此,神经网络方法也基于此。

除了矩阵分解方法,神经网络方法的基本原理是把词作为网络的参数,设计一种网络来监督训练随机初始化的向量。

比如word2vec的一种方法就是利用当前词预测上下文。在此不做重点解释,感兴趣的同学可以去看看论文:

GloVe: Global Vectors for Word Representation

word2vec:Efficient Estimation of Word Representation in Vector Space

fasttext:Bag of Tricks for Efficient Text Classification

值得一提的是,fasttext是 word2vec的作者Mikolov大佬跳槽去Facebook搞的,一个很大的贡献是他们在github上开源了百种以上语言的预训练词向量。

关于词向量listar的博客非常棒。http://licstar.net/archives/328

深度学习方法

深度学习方法主要有cnn based model和rnn based model两种,以及非常浅层的fasttext。

textCNN是Yoon Kim大佬提出的模型,简单而有效。其结构如下:

与图像中不同的是,textCNN使用了横跨词向量宽度的卷积核,并使用不同大小的卷积核捕捉不同范围的特征。

中科院的RCNN

这个模型用了上下文以及当前词的连接向量作为一个位置的特征表示。吐槽下跑的很慢,因为并联的三个LSTM。

HAN通过层次的Attention机制,能更好的捕捉长文本的语义。对长文本表现良好

文本分类的本质是拿到一个文本的特征表示,给全连接做分类,所以任何seq2seq的前端都可以作为特征提取器。比如attention is all your need等等

简单的rnn的最后隐层,attention,max,average都可以。

fastext

模型简单,简单,真的很简单,不想多说话,在某些特定数据上表现很快很好。

还有一些别的。。

感兴趣不妨一试。

这是深度模型在知乎数据集上的表现。

总结和思考

预训练词向量能够提升模型性能?

大部分是可以的。

为什么文本分类没有图像那样非常深的模型?

非常好的问题,希望大家能深入思考,以及文本和图像本质的区别在哪里。一般认为,文本作为一种高级的特征表示,本身文本分类没有非常多的非线性,浅层模型就表现良好。

有没有一个模型可以在所有数据上表现最优?

没有,model+数据 = 方法,有规律可循的是,数据量小的时候,简单的LSTM表现良好,长文本层次模型表现良好,数据量大类别大的时候textCNN表现良好。对语序敏感的任务,如情感分类,LSTM系列的模型良好。

词向量的本质是什么?

区别各个词的一组参数,既使用随机初始化的向量,保持不可训练,模型在自己的容量和记忆能力下也能得到一个还不错的结果。

使用词向量,就是一种更好的特征表示。区别在于解空间做梯度下降的初始位置不同。

使用词向量,更接近于好的解。

在某些数据下,使用预训练词向量和不使用性能相差无几。

参考:https://github.com/brightmart/text_classification

欢迎留言指正,回复文本分类获取完整的ppt。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180228G12HID00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券