赞
踩
中文nlp任务的一般流程:
1、获取语料
语料:是NLP任务所研究的内容。
通常用一个文本集合作为语料库。
来源:已有语料--积累的文档;下载语料——搜狗语料、人民日报语料;抓取语料。
2、语料预处理
①语料清洗
留下有用的,删除噪音数据。
常见的数据清洗方法:
人工去重、对齐、删除和标注等,或者规则提取内容、正则表达式匹配、根据词性和命名实体提取、编写脚本或代码批处理等。
②分词
将文本分成语句。
常见的分词算法:基于字符串匹配的分词方法、基于理解的分词方法、基于统计的分词方法和基于规则的分词方法。
③词性标注
给词语打词类标签,如形容词、动词、名词等; 在情感分析、知识推理等任务中需要。
常见的词性标注方法有:基于规则;基于统计(如基于最大熵的词性标注、基于统计最大概率输出词性和基于HMM的词性标注)
④去停用词
去掉对文本特征没用任何贡献作用的字词,比如标点符号、语气、人称等。
3、特征工程
把分词表示成计算机能够计算的类型,一般为向量。
常用的表示模型:
词袋模型(Bag of Word,Bow) TF-IDF
词向量 One-hot Word2Vec
4、特征选择
选择合适的、表达能力强的特征。
常见的特征选择方法有:DF、MI、IG、CHI、WLLR、WFO
5、模型训练
机器学习模型:KNN、SVM、Naive Bayes、决策树、GBDT、K-means等
深度学习模型:CNN、RNN、LSTM、Seq2Seq、FastText、TextCNN
注意过拟合、欠拟合问题
过拟合:在训练集上表现很好,但是在测试集上表现很差。
常见的解决方法有:增大数据的训练量;增加正则化项,如L1正则和L2正则;特征选取不合理,人工筛选特征和使用特征选择算法;采用Dropout方法等。
欠拟合:模型不能很好的拟合数据。
常见的解决方法有:添加其他特征项;增加模型复杂度,比如神经网络加更多的层、线性模型通过添加多项式使模型泛化能力更强;减少正则化参数,正则化的目的是用来防止过拟合的,但是现在出现了欠拟合,则需要减少正则化参数。
6、评价指标
错误率、精度、准确率、精确率、召回率、F1衡量。
ROC曲线、AUC曲线
7、模型上线应用
第一种就是线下训练模型,然后让模型进行线上部署。
第二种就是在线训练,在线训练完成之后把模型pickle持久化。
词嵌入(Word Embedding)
词是自然语言用来表达意思的一套复杂系统,在这套系统中,词是表达意思的基本单元。词嵌入就是把词映射为实数域向量的技术。在NLP领域中,文本表示是第一步,也是很重要的一步。因为普通的文本语言无法被机器所理解,必须通过转化将对应文本转化为机器所能理解的语言文本。早期是基于规则的方法进行转化,现代的方法是基于统计机器学习的方法。
数据决定了机器学习的上限,而算法只是尽可能的接近这个上限,在文本中数据就是指的是文本表示,文本表示分为离散表示和分布式表示。
1、离散表示
1.1、One-hot表示
One-hot简称读热向量编码,也是特征工程中最常用的方法。其步骤如下:
例如:John likes to watch movies. Mary likes too
John also likes to watch football games.
以上两句可以构造一个词典,**{"John": 1, "likes": 2, "to": 3, "watch": 4, "movies": 5, "also": 6, "football": 7, "games": 8, "Mary": 9, "too": 10} **
每个词典索引对应着比特位。那么利用One-hot表示为:
**John: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] **
likes: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0] .......等等,以此类推。
One-hot表示文本信息的缺点:
1.2、词袋模型
词袋模型(Bag-of-words model),像是句子或是文件这样的文字可以用一个袋子装着这些词的方式表现,这种表现方式不考虑文法以及词的顺序。
文档的向量表示可以直接将各词的词向量表示加和。例如:
John likes to watch movies. Mary likes too
John also likes to watch football games.
以上两句可以构造一个词典,**{"John": 1, "likes": 2, "to": 3, "watch": 4, "movies": 5, "also": 6, "football": 7, "games": 8, "Mary": 9, "too": 10} **
那么第一句的向量表示为:[1,2,1,1,1,0,0,0,1,1],其中的2表示likes在该句中出现了2次,依次类推。
词袋模型同样有一下缺点:
TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF意思是词频(Term Frequency),IDF意思是逆文本频率指数(Inverse Document Frequency)。
字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。
分母之所以加1,是为了避免分母为0。
那么,
,从这个公式可以看出,当w在文档中出现的次数增大时,而TF-IDF的值是减小的,所以也就体现了以上所说的了。
缺点:还是没有把词与词之间的关系顺序表达出来。
n-gram模型为了保持词的顺序,做了一个滑窗的操作,这里的n表示的就是滑窗的大小,例如2-gram模型,也就是把2个词当做一组来处理,然后向后移动一个词的长度,再次组成另一组词,把这些生成一个字典,按照词袋模型的方式进行编码得到结果。改模型考虑了词的顺序。
例如:
John likes to watch movies. Mary likes too
John also likes to watch football games.
以上两句可以构造一个词典,{"John likes”: 1, "likes to”: 2, "to watch”: 3, "watch movies”: 4, "Mary likes”: 5, "likes too”: 6, "John also”: 7, "also likes”: 8, “watch football”: 9, "football games": 10}
那么第一句的向量表示为:[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],其中第一个1表示John likes在该句中出现了1次,依次类推。
**缺点:**随着n的大小增加,词表会成指数型膨胀,会越来越大。
由于存在以下的问题,对于一般的NLP问题,是可以使用离散表示文本信息来解决问题的,但对于要求精度较高的场景就不适合了。
2、分布式表示
为了模型的精度,发明了分布式的表示文本信息的方法。
分布式表示:用一个词附近的其他词用来表示该词。这种方法是基于人的语言表达,认为一个词是由这个词的周边词汇一起来构成精确的语义信息。就好比,物以类聚人以群分,如果你想了解一个人,可以通过他周围的人进行了解,因为周围人都有一些共同点才能聚集起来。
英语单词通常有其内部结构和形成⽅式。例如,我们可以从“dog”“dogs”和“dogcatcher”的字⾯上推测它们的关系。这些词都有同⼀个词根“dog”,但使⽤不同的后缀来改变词的含义。而且,这个关联可以推⼴⾄其他词汇。
在word2vec中,我们并没有直接利⽤构词学中的信息。⽆论是在跳字模型还是连续词袋模型中,我们都将形态不同的单词⽤不同的向量来表⽰。例如,“dog”和“dogs”分别⽤两个不同的向量表⽰,而模型中并未直接表达这两个向量之间的关系。鉴于此,fastText提出了⼦词嵌⼊(subword embedding)的⽅法,从而试图将构词信息引⼊word2vec中的CBOW。
这里有一点需要特别注意,一般情况下,使用fastText进行文本分类的同时也会产生词的embedding,即embedding是fastText分类的产物。除非你决定使用预训练的embedding来训练fastText分类模型,这另当别论。
word2vec把语料库中的每个单词当成原子的,它会为每个单词生成一个向量。这忽略了单词内部的形态特征,比如:“book” 和“books”,“阿里巴巴”和“阿里”,这两个例子中,两个单词都有较多公共字符,即它们的内部形态类似,但是在传统的word2vec中,这种单词内部形态信息因为它们被转换成不同的id丢失了。
**为了克服这个问题,fastText使用了字符级别的n-grams来表示一个单词。**对于单词“book”,假设n的取值为3,则它的trigram有:
“<bo”, “boo”, “ook”, “ok>”
其中,<表示前缀,>表示后缀。于是,我们可以用这些trigram来表示“book”这个单词,进一步,我们可以用这4个trigram的向量叠加来表示“apple”的词向量。
这带来两点好处:
之前提到过,fastText模型架构和word2vec的CBOW模型架构非常相似。下面是fastText模型架构图:
注意:此架构图没有展示词向量的训练过程。可以看到,和CBOW一样,fastText模型也只有三层:输入层、隐含层、输出层(Hierarchical Softmax),输入都是多个经向量表示的单词,输出都是一个特定的target,隐含层都是对多个词向量的叠加平均。
不同的是,
**值得注意的是,fastText在输入时,将单词的字符级别的n-gram向量作为额外的特征;在输出时,fastText采用了分层Softmax,大大降低了模型训练时间。**这两个知识点在前文中已经讲过,这里不再赘述。
fastText相关公式的推导和CBOW非常类似,这里也不展开了。
现在抛开那些不是很讨人喜欢的公式推导,来想一想fastText文本分类的核心思想是什么?
仔细观察模型的后半部分,即从隐含层输出到输出层输出,会发现它就是一个softmax线性多类别分类器,分类器的输入是一个用来表征当前文档的向量;
模型的前半部分,即从输入层输入到隐含层输出部分,主要在做一件事情:生成用来表征文档的向量。那么它是如何做的呢?**叠加构成这篇文档的所有词及n-gram的词向量,然后取平均。**叠加词向量背后的思想就是传统的词袋法,即将文档看成一个由词构成的集合。
**于是fastText的核心思想就是:将整篇文档的词及n-gram向量叠加平均得到文档向量,然后使用文档向量做softmax多分类。**这中间涉及到两个技巧:字符级n-gram特征的引入以及分层Softmax分类。
还有个问题,就是为何fastText的分类效果常常不输于传统的非线性分类器?
假设我们有两段文本:
肚子 饿了 我 要 吃饭
肚子 饿了 我 要 吃东西
这两段文本意思几乎一模一样,如果要分类,肯定要分到同一个类中去。但在传统的分类器中,用来表征这两段文本的向量可能差距非常大。传统的文本分类中,你需要计算出每个词的权重,比如TF-IDF值, “吃饭”和“吃东西” 算出的TF-IDF值相差可能会比较大,其它词类似,于是,VSM(向量空间模型)中用来表征这两段文本的文本向量差别可能比较大。
但是fastText就不一样了,它是用单词的embedding叠加获得的文档向量,词向量的重要特点就是向量的距离可以用来衡量单词间的语义相似程度,于是,在fastText模型中,这两段文本的向量应该是非常相似的,于是,它们很大概率会被分到同一个类中。
使用词embedding而非词本身作为特征,这是fastText效果好的一个原因;另一个原因就是字符级n-gram特征的引入对分类效果会有一些提升 。
有意思的是,fastText和Word2Vec的作者是同一个人。
相同点:
之前一直不明白fasttext用层次softmax时叶子节点是啥,CBOW很清楚,它的叶子节点是词和词频,后来看了源码才知道,其实fasttext叶子节点里是类标和类标的频数。
Word2Vec | fastText | |
---|---|---|
输入 | one-hot形式的单词的向量 | embedding过的单词的词向量和n-gram向量 |
输出 | 对应的是每一个term,计算某term概率最大 | 对应的是分类的标签。 |
本质不同,体现在softmax的使用:
word2vec的目的是得到词向量,该词向量最终是在输入层得到的,输出层对应的h-softmax也会生成一系列的向量,但是最终都被抛弃,不会使用。
fastText则充分利用了h-softmax的分类功能,遍历分类树的所有叶节点,找到概率最大的label
fastText优点:
1、Glove的基本表达
GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具,它可以把一个单词表达成一个由实数组成的向量,这些向量捕捉到了单词之间一些语义特性,比如相似性(similarity)、类比性(analogy)等。我们通过对向量的运算,比如欧几里得距离或者cosine相似度,可以计算出两个单词之间的语义相似性。
2、Glove的实现步骤
2.1 构建共现矩阵
什么是共现矩阵?
共现矩阵顾名思义就是共同出现的意思,词文档的共现矩阵主要用于发现主题(topic),用于主题模型,如LSA。
局域窗中的word-word共现矩阵可以挖掘语法和语义信息,例如:
有以上三句话,设置滑窗为2,可以得到一个词典:{"I like","like deep","deep learning","like NLP","I enjoy","enjoy flying","I like"}。
我们可以得到一个共现矩阵(对称矩阵):
中间的每个格子表示的是行和列组成的词组在词典中共同出现的次数,也就体现了共现的特性。
GloVe的共现矩阵
根据语料库(corpus)构建一个共现矩阵(Co-ocurrence Matrix)X,矩阵中的每一个元素 Xij 代表单词 i 和上下文单词 j 在特定大小的上下文窗口(context window)内共同出现的次数。一般而言,这个次数的最小单位是1,但是GloVe不这么认为:它根据两个单词在上下文窗口的距离 d,提出了一个衰减函数(decreasing weighting):decay=1/d 用于计算权重,也就是说距离越远的两个单词所占总计数(total count)的权重越小。
构建词向量(Word Vector)和共现矩阵(Co-ocurrence Matrix)之间的近似关系,论文的作者提出以下的公式可以近似地表达两者之间的关系:
其中w是我们最终要求解的词向量;分别是两个词向量的bias term。当然你对这个公式一定有非常多的疑问,比如它到底是怎么来的,为什么要使用这个公式,为什么要构造两个词向量 ?请参考参考文献:GloVe: Global Vectors for Word Representation - ACL Anthology 和
NLP从词袋到Word2Vec的文本表示_mantchs的博客-CSDN博客
有了2.2的公式之后我们就可以构造它的loss function了:
这个loss function的基本形式就是最简单的mean square loss,只不过在此基础上加了一个权重函数
,那么这个函数起了什么作用,为什么要添加这个函数呢?我们知道在一个语料库中,肯定存在很多单词他们在一起出现的次数是很多的(frequent co-occurrences),那么我们希望:
满足以上三个条件的函数有很多,论文作者采用了如下形式的分段函数:
这个函数图像如下所示:
虽然很多人声称GloVe是一种无监督(unsupervised learing)的学习方式(因为它确实不需要人工标注label),但其实它还是有label的,这个label就是以上公式中的 log(Xij),而公式中的向量 w和-/w 就是要不断更新/学习的参数,所以本质上它的训练方式跟监督学习的训练方法没什么不一样,都是基于梯度下降的。
具体地,这篇论文里的实验是这么做的:**采用了AdaGrad的梯度下降算法,对矩阵 X 中的所有非零元素进行随机采样,学习曲率(learning rate)设为0.05,在vector size小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。**最终学习得到的是两个vector是 w和-/w,因为 X 是对称的(symmetric),所以从原理上讲w和-/w 是也是对称的,他们唯一的区别是初始化的值不一样,而导致最终的值不一样。
所以这两者其实是等价的,都可以当成最终的结果来使用。但是为了提高鲁棒性,我们最终会选择两者之和
**作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。**在训练了400亿个token组成的语料后,得到的实验结果如下图所示:
这个图一共采用了三个指标:语义准确度,语法准确度以及总体准确度。那么我们不难发现Vector Dimension在300时能达到最佳,而context Windows size大致在6到10之间。
LSA(Latent Semantic Analysis)是一种比较早的count-based的词向量表征工具,它也是基于co-occurance matrix的,只不过采用了基于奇异值分解(SVD)的矩阵分解技术对大矩阵进行降维,而我们知道SVD的复杂度是很高的,所以它的计算代价比较大。还有一点是它对所有单词的统计权重都是一致的。而这些缺点在GloVe中被一一克服了。
而word2vec最大的缺点则是没有充分利用所有的语料,所以GloVe其实是把两者的优点结合了起来。从这篇论文给出的实验结果来看,GloVe的性能是远超LSA和word2vec的,但网上也有人说GloVe和word2vec实际表现其实差不多。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。