文本表示

导言

文本分类是自然语言处理中研究最为广泛的任务之一,通过构建模型实现对文本内容进行自动分类,有很多应用场景,比如新闻文章主题分类,产品评论情感分类,检索中用户查询的意图分类等等。文本分类的大致流程:文本预处理,抽取文本特征,构造分类器。其中研究最多的就是文本特征抽取,更广义上说是文本表示。

关于文本表示,研究者从不同的角度出发,提出大量的文本表示模型。本文重点梳理现有模型,大致分为三类,即基于向量空间模型、基于主题模型和基于神经网络的方法,针对每类给出一些具有代表性的模型,阐述其基本思想,对于具体的细节,读者可以阅读给出的参考文献。

基于向量空间模型的方法

向量空间模型是将文本表示成实数值分量所构成的向量,一般而言,每个分量对应一个词项,相当于将文本表示成空间中的一个点。向量不仅可以用来训练分类器,而且计算向量之间的相似度可以度量文本之间的相似度。

最常用的是TF-IDF计算方式,即向量的维度对应词表的大小,对应维度使用TF-IDF计算。向量空间模型的优点是简单明了,向量维度意义明确,效果不错,但也存在明显的缺点,其一,维度随着词表增大而增大,且向量高度稀疏;其二,无法处理“一义多词”和“一词多义”问题。

在向量空间模型中,文档集合相当于表示成高维稀疏矩阵,如图1中所示,文档集合矩阵的维度是N*V,其中N是文档数目,V是词表的大小。为了更好的提升文本的语义表示能力,有人提出通过矩阵分解的方法,对高维稀疏矩阵进行分解,最为著名的便是潜在语义分析(Latent semantic analysis, LSA),具体而言,LSA会构建一个文档与词项的共现矩阵,矩阵的元素一般通过TFIDF计算得到,最终通过奇异值分解的方法对原始矩阵降维,可以得到文档向量和词项向量。如图1所示,分解后,每个文档可以用k维向量表示(k << V),相当于潜在语义分析实现对文档的低维语义表示。但是,以上过程通过矩阵分解得到,空间中维度的物理含义不明确,无法解释。

图1  LSA

基于主题模型的方法

第2节中提到LSA算法通过线性代数中奇异值分解实现文档映射到低维语义空间里的向量,但是空间中每一个维度是没有明确物理意义的,主题模型尝试从概率生成模型的角度实现文本的表示,每一个维度是一个“主题(topic)”,这个主题通常是一组词的聚类,因此可以通过主题大概猜测每个维度所代表的语义,具有一定的解释性。

最早的主题模型pLSA (probabilistic LSA),假设文档具有主题分布,文档中的词从主题对应的词分布中抽取。如图2所示,以d表示文档,w表示词,z表示主题(隐变量),则文档和词的联合概率p(d, w)的生成过程可表示为:

其中p(z|d)和p(w|z)作为参数可以用EM算法进行学习。然而,pLSA没有假设主题的的先验分布,导致参数随训练文档的数目呈线性增长,参数空间很大。

图2  pLSA

 

于是,有人提出更加完善的主题的模型LDA(Latent Dirichlet allocation),可以认为pLSA体现频率学派的思想,而LDA是贝叶斯学派的思想,LDA在已有的模型上中的2个多项式分布引入了狄利克雷先验分布,从而解决pLSA中存在的问题。如图3所示,每个文档的主题分布为多项式分布Mult(θ),其中θ从狄利克雷先验分布Dir(α)抽取,同理,对于主题的词分布为多项式分布Mult(Φ),参数Φ也是从狄利克雷先验Dir(β)抽取得到。

图3  LDA

基于主题模型的方法,引入“主题”概念,具有一定的物理意义,从而得到文档的主题分布表示。当然,主题模型很存在一些问题,比如训练参数多导致训练时间长,对短文本的建模效果不好,主题数目的设置需要人工设定可能导致不合理。后来,也有很多人提出改进的方法,在这就不一一赘述了。

基于神经网络的方法

现今,基于神经网络的方法受到广泛关注,各种各样的模型被相继提出,本节总结其中最具有代表性的模型,将其分为三类:

第一类,基于词向量合成的模型,该类方法仅是在词向量基础上简单合成;

第二类,基于RNN/CNN的模型,该类方法利用更复杂的深度学习模型对文本进行建模;

第三类,基于注意力机制的模型,在已有神经网络模型基础上,引入注意力机制,提升文本建模效果。

基于词向量合成的模型

2003年Bengio等人开始使用神经网络来做语言模型的工作,尝试得到词的低维、稠密的向量表示,2013年Mikolov等人提出简化的模型,即著名的Word2Vec,包含两个模型CBOW和Skip-gram,前者通过窗口语境预测目标词出现的概率,后者使用目标词预测窗口中的每个语境词出现的概率。语义上相似或相关的词,得到的表示向量也相近,这样的特性使得Word2Vec获得巨大成功。

后来,Mikolov等人又延续Word2Vec的思想,提出Doc2Vec,核心思想是将文档向量当作“语境”,用来预测文档中的词。Doc2Vec算法可以得到词向量和文档向量。如图4所示,两个算法的思想基本一致。

图4  Word2Vec和Doc2Vec比较

其实,也可以通过最简单的合成方式实现从词向量到句子向量的表示,fastText就是这样简单有效的模型,如图5所示,输入层是词向量,然后通过把句子里的词向量平均就得到句子的表示,最后送到分类器中。不过,输入端会另外补充一些n-gram信息来捕捉局部序列信息。fastText是线性分类模型,实验表明在诸多“简单”文本分类任务中表现出色,且具备训练速度非常快的优点,所以可以成为很好的Baseline。

图5  fastText模型

基于RNN/CNN的模型

自然语言中,词构成句子,句子构成文档,有很多工作尝试合理表示词向量同时,也有很多模型被提出来建模句子和文档,其中最常见的网络结构便是LSTM和CNN。

2014年Kim提出基于卷积神经网络的文本分类,如图6所示,输入是句子对应的词向量矩阵,经过一层卷积层和一层Max Pooling层,得到句子的表示,送入到全连接层,最后softmax输出。卷积神经网络擅长提取重要的局部特征,在文本分类中,可以理解为不同大小的卷积核在提取不同n-gram特征。一般认为,卷积神经网络无法考虑长距离的依赖信息,且没有考虑词序信息,在有限的窗口下提取句子特征,会损失一些语义信息。

图6 CNN网络用于文本分类

针对CNN的不足之处,LSTM和GRU等循环神经网络因为擅长捕捉长距离信息,所以也被大家尝试用来文本表示。如图7所示,图中利用双向LSTM来建模输入句子,输入是句子的词向量,输入至BiLSTM中进行序列建模。最后句子表示,可以尝试两种方法,其一,选择最后的hidden state用来表示句子;其二,所有hidden state的平均用于表示句子。

图7 BiLSTM用于文本表示

刚才分析到,CNN擅长提取局部特征,而LSTM擅长捕捉长距离信息,不难想到,有人尝试结合两种网络的优点,提出RCNN用于文本建模。如图8所示,整个网络结构主要有两部分组成,循环结构和Max Pooling。循环结构,可以理解为,在已有词向量为输入的基础上,通过双向RNN网络学习每一个词的左、右上下文信息,接着将三部分(left context, word embedding, right context)表示向量拼接起来,作为句子中每一个词的表示,然后使用变换得到中间语义表示;Max Pooling层,采用element-wise的max pooling方式,可以从变长的输入中得到固定的句子表示。

图8  RCNN用于文本表示

基于注意力机制的模型

注意力被认为是一种有效选择信息的方式,可以过滤掉大量与任务无关的信息,最先在机器翻译任务中被提出,解决seq2seq中encoder过程把源序列映射成固定大小的向量存在“损失”信息的情况。紧接着,Attention被推广到各种NLP任务中,文本表示任务当然不例外。这里,主要介绍两种Attention的形式,Hierarchical Attention 和 Self-Attention。

Hierarchical Attention网络结构,如图9所示,该模型基于两个基本假设,其一,文档是分层结构的,词构成句子,句子构成文档;其二,文档中不同词或句子提供的信息量不一样的,该模型适合用来表示包含多个句子的文档的表示问题。模型主要由word encoder和sentence encoder,以及相应的attention组成,word encoder部分用于得到句子的表示,该层的输入为句子的词向量,经过双向GRU后得到中间表示,word attention部分对中间表示按attention值进行加权得到此句最终的句子表示;sentence encoder部分用于得到文档的表示,使用word encoder部分得到文档中所有句子的表示后,将此作为sentence encoder部分的输入,类比word encoder的计算,可以最终得到文档的表示。简言之,利用Hierarchical Attention结构,一层词输入得到句子表示,一层句子输入得到文档表示。即使文档长度较长,但是在注意力的作用下,依然可以较好的捕捉到有效的特征信息,忽略无意义的输入。

图9  Hierarchical Attention

Self-Attention网络结构,如图10所示,大多数神经网络模型将文本表示成一维的向量,但是此模型通过二维矩阵来表示句子,包括两部分,一部分是双向的LSTM,另一部分是自注意力机制,自注意力机制实现对双向LSTM中所有的隐藏状态以不同权重的方式线形组合,每一次组合获得句子的一部分表示,多次组合便得到矩阵表示(图中矩阵M)。

图10  Self-Attention

总结

本文简述了具有代表性的文本表示模型,将现有模型分为三类进行介绍,包括基于向量空间模型、基于主题模型和基于神经网络的方法。不过,本文中提及的神经网络方法大部分都是有监督方法,通常都是结合具体的应用根据有监督的信息进行训练,其实也有大量的方法是通过无监督的方法获得普适性的文本表示,感兴趣的读者可以自行去翻阅相关文献。

 

语言的特征表示

引言

自然语言处理在人工智能领域有着重要的地位,在 1950 年提出的图灵测试中,自然语言处理能力就是让机器能表现出与人类无法区分的智能的重要组成部分。

自然语言处理问题不仅是学术界研究的热点,在工业界也有许多成果。如谷歌文本搜索引擎,苹果的 Siri 和微软小冰等等产品都受益于自然语言处理问题的研究成果。

自然语言处理可以分为核心任务和应用两部分,核心任务代表在自然语言各个应用方向上需要解决的共同问题,包括语言模型,语言形态学,语法分析以及语义分析等等,而应用部分则更关注与解决自然语言处理的具体任务,如机器翻译,信息检索,问答系统,对话系统等等。深度学习领域近年来的高速发展给自然语言处理问题的解决带来了很多启发,但是深度学习算法需要大量的 “像石油一样贵重” 的标记训练数据,为算法的应用带来了很多挑战。近期一些研究提出使用迁移学习的方法来缓解缺少带有标记的训练数据的问题,2018 年提出的 BERT(Bidirectional Encoder Representations from Transformers)模型就是这种思想在解决自然语言处理的核心任务中的一个有效应用。BERT 的出现刷新了当时自然语言处理各个领域任务上的最优成绩,也引起了广泛的讨论。

问题

语言模型的任务形式是什么?语言模型如何帮助提升其他自然语言处理任务的效果?

分析与解答

语言模型是自然语言处理中的核心任务,它一方面可以评估语言生成概率,直接用于生成符合人类认知的语言;另一方面由于语言模型的训练不依赖任何额外的监督信息,因此适合用来学习语句的通用语义表示。目前非常普及的做法就是利用语言模型在大规模的开放语料库上预训练神经网络,然后在此基础上针对特定任务来对模型进行微调。近两年里具有代表性的模型 ELMo [6] , GPT [7] 和 BERT [8] 都利用了这种思路。图 Fig. 1 更直观地展示各个模型的结构,其中黄色的输入层为词或句的嵌入表示,蓝色的中间层为核心的网络结构,绿色的输出层对应预测的词或分类标签。下面对三个模型分别进行介绍。

 

 

Figure 1: 经典的预训练语言模型

GPT 则基于 Transformer 单向编码器结构,将单向语言模型作为预训练阶段的目标函数。预训练学习到的网络结构和参数将作为具体任务模型对应的初始值,然后针对分类,序列标注,句子关系判断等不同任务对网络结构进行改造,同时将语言模型作为辅助任务对模型参数进行微调。GPT 将语言模型作为辅助任务的方式也是一种很好地利用语言模型的思路,不仅可以提升模型的泛化能力,同时也能加快模型的收敛。

 

BERT 是谷歌于 2018 年底提出的语言特征表示模型,横扫 11 项自然语言处理任务比赛记录,一时间掀起广泛讨论,但在模型架构上其实和前两者是一脉相承的。BERT 相对于之前工作的改进点主要可以归纳为以下两个方面:

第一,实现真正的双向多层语言模型对词级别语义进行深度建模。BERT 作者认为 ELMo 分开学习上文和下文,GPT 则只利用上文信息,二者都没有很好地对句子的上下文信息同时进行建模。但如果直接在语言模型任务中用完整的句子作为输入,由于自注意力机制的特性,对每个词进行预测的时候实际已经泄露了当前词的信息。因此,在 Transformer 双向编码器结构的基础上,BERT 在预训练阶段引入 Masked 语言模型的任务,即每轮训练中选择语料中 15% 的词,随机替换成 [MASK] 标记或其他随机词或保持原样,并对这些词进行预测。

第二,显式地对句子关系建模以更好地表征句级别的语义。语言模型任务以任意词序列作为输入,没有显式地考虑句子之间的关系。为了更好地表征句级别的特征,BERT 模型对输入层的嵌入表示做了两点改进,一是引入了句子向量(如图中 EA 和 EB 所示)同时作为输入,二是引入了 [SEP] 标记表示句子的结尾和 [CLS] 标记表示句子关系,并分别学习对应的向量。然后在预训练阶段通过 [CLS] 标记对应的隐藏层表示来预测句子 B 是否为句子 A 的下一句(如图中 [IsNext] 标签所示),从而完成对模型参数的学习和更新。

在面对具体任务时,BERT 同样保留预训练得到的模型结构,然后通过参数微调来优化不同任务对应的目标,比如在进行句子关系判断等任务时直接利用 [CLS] 标记对应的嵌入表示进行分类。相较 GPT,BERT 在利用预训练的语言模型做下游 NLP 任务时,对模型结构的改动更小,泛化性能更强。

三个模型的基本思想相似,在模型细节上则有一些差别,简单归纳如下:

 

预训练方法 BERT和OpenAI GPT有什么区别?

解析

1.GPT在BooksCorpus(800M单词)训练;BERT在BooksCorpus(800M单词)和维基百科(2,500M单词)训练
2.GPT使用一种句子分隔符([SEP])和分类符词块([CLS]),它们仅在微调时引入;BERT在预训练期间学习[SEP],[CLS]和句子A/B嵌入
3.GPT用一个批量32,000单词训练1M步;BERT用一个批量128,000单词训练1M步
4.GPT对所有微调实验使用的5e-5相同学习率;BERT选择特定于任务的微调学习率,在开发集表现最佳

 

 

文本挖掘预处理之向量化与Hash Trick

    在文本挖掘的分词原理中,我们讲到了文本挖掘的预处理的关键一步:“分词”,而在做了分词后,如果我们是做文本分类聚类,则后面关键的特征预处理步骤有向量化或向量化的特例Hash Trick,本文我们就对向量化和特例Hash Trick预处理方法做一个总结。

1. 词袋模型

    在讲向量化与Hash Trick之前,我们先说说词袋模型(Bag of Words,简称BoW)。词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。

    词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。向量化完毕后一般也会使用TF-IDF进行特征的权重修正,再将特征进行标准化。 再进行一些其他的特征工程后,就可以将数据带入机器学习算法进行分类聚类了。

    总结下词袋模型的三部曲:分词(tokenizing),统计修订词特征值(counting)与标准化(normalizing)。

    与词袋模型非常类似的一个模型是词集模型(Set of Words,简称SoW),和词袋模型唯一的不同是它仅仅考虑词是否在文本中出现,而不考虑词频。也就是一个词在文本在文本中出现1次和多次特征处理是一样的。在大多数时候,我们使用词袋模型,后面的讨论也是以词袋模型为主。

    当然,词袋模型有很大的局限性,因为它仅仅考虑了词频,没有考虑上下文的关系,因此会丢失一部分文本的语义。但是大多数时候,如果我们的目的是分类聚类,则词袋模型表现的很好。

2. 词袋模型之向量化

    在词袋模型的统计词频这一步,我们会得到该文本中所有词的词频,有了词频,我们就可以用词向量表示这个文本。这里我们举一个例子,例子直接用scikit-learn的CountVectorizer类来完成,这个类可以帮我们完成文本的词频统计与向量化,代码如下:

    完整代码参见我的github:https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/hash_trick.ipynb

复制代码

from sklearn.feature_extraction.text import CountVectorizer  
vectorizer=CountVectorizer()
corpus=["I come to China to travel", 
    "This is a car polupar in China",          
    "I love tea and Apple ",   
    "The work is to write some papers in science"] 
print vectorizer.fit_transform(corpus)

复制代码

    我们看看对于上面4个文本的处理输出如下:

  (0, 16)	1
  (0, 3)	1
  (0, 15)	2
  (0, 4)	1
  (1, 5)	1
  (1, 9)	1
  (1, 2)	1
  (1, 6)	1
  (1, 14)	1
  (1, 3)	1
  (2, 1)	1
  (2, 0)	1
  (2, 12)	1
  (2, 7)	1
  (3, 10)	1
  (3, 8)	1
  (3, 11)	1
  (3, 18)	1
  (3, 17)	1
  (3, 13)	1
  (3, 5)	1
  (3, 6)	1
  (3, 15)	1

    可以看出4个文本的词频已经统计出,在输出中,左边的括号中的第一个数字是文本的序号,第2个数字是词的序号,注意词的序号是基于所有的文档的。第三个数字就是我们的词频。

    我们可以进一步看看每个文本的词向量特征和各个特征代表的词,代码如下:

print vectorizer.fit_transform(corpus).toarray()
print vectorizer.get_feature_names()

    输出如下:

[[0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 1 0 0]
 [0 0 1 1 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0]
 [1 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 0 1 1 0 1 0 1 1 0 1 0 1 0 1 1]]
[u'and', u'apple', u'car', u'china', u'come', u'in', u'is', u'love', u'papers', u'polupar', u'science', u'some', u'tea', u'the', u'this', u'to', u'travel', u'work', u'write']

    可以看到我们一共有19个词,所以4个文本都是19维的特征向量。而每一维的向量依次对应了下面的19个词。另外由于词"I"在英文中是停用词,不参加词频的统计。

    由于大部分的文本都只会使用词汇表中的很少一部分的词,因此我们的词向量中会有大量的0。也就是说词向量是稀疏的。在实际应用中一般使用稀疏矩阵来存储。

    将文本做了词频统计后,我们一般会通过TF-IDF进行词特征值修订,这部分我们后面再讲。

    向量化的方法很好用,也很直接,但是在有些场景下很难使用,比如分词后的词汇表非常大,达到100万+,此时如果我们直接使用向量化的方法,将对应的样本对应特征矩阵载入内存,有可能将内存撑爆,在这种情况下我们怎么办呢?第一反应是我们要进行特征的降维,说的没错!而Hash Trick就是非常常用的文本特征降维方法。

3.  Hash Trick

    在大规模的文本处理中,由于特征的维度对应分词词汇表的大小,所以维度可能非常恐怖,此时需要进行降维,不能直接用我们上一节的向量化方法。而最常用的文本降维方法是Hash Trick。说到Hash,一点也不神秘,学过数据结构的同学都知道。这里的Hash意义也类似。

    在Hash Trick里,我们会定义一个特征Hash后对应的哈希表的大小,这个哈希表的维度会远远小于我们的词汇表的特征维度,因此可以看成是降维。具体的方法是,对应任意一个特征名,我们会用Hash函数找到对应哈希表的位置,然后将该特征名对应的词频统计值累加到该哈希表位置。如果用数学语言表示,假如哈希函数h使第i个特征哈希到位置j,即h(i)=j,则第i个原始特征的词频数值ϕ(i)将累加到哈希后的第j个特征的词频数值ϕ¯上,即:

ϕ¯(j)=∑i∈J;h(i)=jϕ(i)

    其中J是原始特征的维度。

    但是上面的方法有一个问题,有可能两个原始特征的哈希后位置在一起导致词频累加特征值突然变大,为了解决这个问题,出现了hash Trick的变种signed hash trick,此时除了哈希函数h,我们多了一个一个哈希函数:

ξ:N→±1

    此时我们有

ϕ¯(j)=∑i∈J;h(i)=jξ(i)ϕ(i)

    这样做的好处是,哈希后的特征仍然是一个无偏的估计,不会导致某些哈希位置的值过大。

    当然,大家会有疑惑,这种方法来处理特征,哈希后的特征是否能够很好的代表哈希前的特征呢?从实际应用中说,由于文本特征的高稀疏性,这么做是可行的。如果大家对理论上为何这种方法有效,建议参考论文:Feature hashing for large scale multitask learning.这里就不多说了。

    在scikit-learn的HashingVectorizer类中,实现了基于signed hash trick的算法,这里我们就用HashingVectorizer来实践一下Hash Trick,为了简单,我们使用上面的19维词汇表,并哈希降维到6维。当然在实际应用中,19维的数据根本不需要Hash Trick,这里只是做一个演示,代码如下:

from sklearn.feature_extraction.text import HashingVectorizer 
vectorizer2=HashingVectorizer(n_features = 6,norm = None)
print vectorizer2.fit_transform(corpus)

    输出如下:

  (0, 1)	2.0
  (0, 2)	-1.0
  (0, 4)	1.0
  (0, 5)	-1.0
  (1, 0)	1.0
  (1, 1)	1.0
  (1, 2)	-1.0
  (1, 5)	-1.0
  (2, 0)	2.0
  (2, 5)	-2.0
  (3, 0)	0.0
  (3, 1)	4.0
  (3, 2)	-1.0
  (3, 3)	1.0
  (3, 5)	-1.0

    大家可以看到结果里面有负数,这是因为我们的哈希函数ξ可以哈希到1或者-1导致的。

    和PCA类似,Hash Trick降维后的特征我们已经不知道它代表的特征名字和意义。此时我们不能像上一节向量化时候可以知道每一列的意义,所以Hash Trick的解释性不强。

4. 向量化与Hash Trick小结

    这里我们对向量化与它的特例Hash Trick做一个总结。在特征预处理的时候,我们什么时候用一般意义的向量化,什么时候用Hash Trick呢?标准也很简单。

    一般来说,只要词汇表的特征不至于太大,大到内存不够用,肯定是使用一般意义的向量化比较好。因为向量化的方法解释性很强,我们知道每一维特征对应哪一个词,进而我们还可以使用TF-IDF对各个词特征的权重修改,进一步完善特征的表示。

    而Hash Trick用大规模机器学习上,此时我们的词汇量极大,使用向量化方法内存不够用,而使用Hash Trick降维速度很快,降维后的特征仍然可以帮我们完成后续的分类和聚类工作。当然由于分布式计算框架的存在,其实一般我们不会出现内存不够的情况。因此,实际工作中我使用的都是特征向量化。

    向量化与Hash Trick就介绍到这里,下一篇我们讨论TF-IDF。

 

文本挖掘预处理之向量化与Hash Trick中我们讲到在文本挖掘的预处理中,向量化之后一般都伴随着TF-IDF的处理,那么什么是TF-IDF,为什么一般我们要加这一步预处理呢?这里就对TF-IDF的原理做一个总结。

1. 文本向量化特征的不足

    在将文本分词并向量化后,我们可以得到词汇表中每个词在各个文本中形成的词向量,比如在文本挖掘预处理之向量化与Hash Trick这篇文章中,我们将下面4个短文本做了词频统计:

corpus=["I come to China to travel", 
    "This is a car polupar in China",          
    "I love tea and Apple ",   
    "The work is to write some papers in science"] 

    不考虑停用词,处理后得到的词向量如下:

[[0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 1 0 0]
 [0 0 1 1 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0]
 [1 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 0 1 1 0 1 0 1 1 0 1 0 1 0 1 1]]

    如果我们直接将统计词频后的19维特征做为文本分类的输入,会发现有一些问题。比如第一个文本,我们发现"come","China"和“Travel”各出现1次,而“to“出现了两次。似乎看起来这个文本与”to“这个特征更关系紧密。但是实际上”to“是一个非常普遍的词,几乎所有的文本都会用到,因此虽然它的词频为2,但是重要性却比词频为1的"China"和“Travel”要低的多。如果我们的向量化特征仅仅用词频表示就无法反应这一点。因此我们需要进一步的预处理来反应文本的这个特征,而这个预处理就是TF-IDF。

2. TF-IDF概述

    TF-IDF是Term Frequency -  Inverse Document Frequency的缩写,即“词频-逆文本频率”。它由两部分组成,TF和IDF。

    前面的TF也就是我们前面说到的词频,我们之前做的向量化也就是做了文本中各个词的出现频率统计,并作为文本特征,这个很好理解。关键是后面的这个IDF,即“逆文本频率”如何理解。在上一节中,我们讲到几乎所有文本都会出现的"to"其词频虽然高,但是重要性却应该比词频低的"China"和“Travel”要低。我们的IDF就是来帮助我们来反应这个词的重要性的,进而修正仅仅用词频表示的词特征值。

    概括来讲, IDF反应了一个词在所有文本中出现的频率,如果一个词在很多的文本中出现,那么它的IDF值应该低,比如上文中的“to”。而反过来如果一个词在比较少的文本中出现,那么它的IDF值应该高。比如一些专业的名词如“Machine Learning”。这样的词IDF值应该高。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。

    上面是从定性上说明的IDF的作用,那么如何对一个词的IDF进行定量分析呢?这里直接给出一个词x的IDF的基本公式如下:

IDF(x)=logNN(x)

    其中,N代表语料库中文本的总数,而N(x)代表语料库中包含词x的文本总数。为什么IDF的基本公式应该是是上面这样的而不是像N/N(x)这样的形式呢?这就涉及到信息论相关的一些知识了。感兴趣的朋友建议阅读吴军博士的《数学之美》第11章。

    上面的IDF公式已经可以使用了,但是在一些特殊的情况会有一些小问题,比如某一个生僻词在语料库中没有,这样我们的分母为0, IDF没有意义了。所以常用的IDF我们需要做一些平滑,使语料库中没有出现的词也可以得到一个合适的IDF值。平滑的方法有很多种,最常见的IDF平滑后的公式之一为:

IDF(x)=logN+1N(x)+1+1

    有了IDF的定义,我们就可以计算某一个词的TF-IDF值了:

TF−IDF(x)=TF(x)∗IDF(x)

    其中TF(x)指词x在当前文本中的词频。

3. 用scikit-learn进行TF-IDF预处理

    在scikit-learn中,有两种方法进行TF-IDF的预处理。

    完整代码参见我的github:https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/tf-idf.ipynb

    第一种方法是在用CountVectorizer类向量化之后再调用TfidfTransformer类进行预处理。第二种方法是直接用TfidfVectorizer完成向量化与TF-IDF预处理。

    首先我们来看第一种方法,CountVectorizer+TfidfTransformer的组合,代码如下:

复制代码

from sklearn.feature_extraction.text import TfidfTransformer  
from sklearn.feature_extraction.text import CountVectorizer  

corpus=["I come to China to travel", 
    "This is a car polupar in China",          
    "I love tea and Apple ",   
    "The work is to write some papers in science"] 

vectorizer=CountVectorizer()

transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))  
print tfidf

复制代码

    输出的各个文本各个词的TF-IDF值如下:

  (0, 4)	0.442462137895
  (0, 15)	0.697684463384
  (0, 3)	0.348842231692
  (0, 16)	0.442462137895
  (1, 3)	0.357455043342
  (1, 14)	0.453386397373
  (1, 6)	0.357455043342
  (1, 2)	0.453386397373
  (1, 9)	0.453386397373
  (1, 5)	0.357455043342
  (2, 7)	0.5
  (2, 12)	0.5
  (2, 0)	0.5
  (2, 1)	0.5
  (3, 15)	0.281131628441
  (3, 6)	0.281131628441
  (3, 5)	0.281131628441
  (3, 13)	0.356579823338
  (3, 17)	0.356579823338
  (3, 18)	0.356579823338
  (3, 11)	0.356579823338
  (3, 8)	0.356579823338
  (3, 10)	0.356579823338

    现在我们用TfidfVectorizer一步到位,代码如下:

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf2 = TfidfVectorizer()
re = tfidf2.fit_transform(corpus)
print re

    输出的各个文本各个词的TF-IDF值和第一种的输出完全相同。大家可以自己去验证一下。

    由于第二种方法比较的简洁,因此在实际应用中推荐使用,一步到位完成向量化,TF-IDF与标准化。

4. TF-IDF小结

    TF-IDF是非常常用的文本挖掘预处理基本步骤,但是如果预处理中使用了Hash Trick,则一般就无法使用TF-IDF了,因为Hash Trick后我们已经无法得到哈希后的各特征的IDF的值。使用了IF-IDF并标准化以后,我们就可以使用各个文本的词特征向量作为文本的特征,进行分类或者聚类分析。

    当然TF-IDF不光可以用于文本挖掘,在信息检索等很多领域都有使用。因此值得好好的理解这个方法的思想。

 

中文文本挖掘预处理流程总结

    在对文本做数据分析时,我们一大半的时间都会花在文本预处理上,而中文和英文的预处理流程稍有不同,本文就对中文文本挖掘的预处理流程做一个总结。

1. 中文文本挖掘预处理特点

    首先我们看看中文文本挖掘预处理和英文文本挖掘预处理相比的一些特殊点。

    首先,中文文本是没有像英文的单词空格那样隔开的,因此不能直接像英文一样可以直接用最简单的空格和标点符号完成分词。所以一般我们需要用分词算法来完成分词,在文本挖掘的分词原理中,我们已经讲到了中文的分词原理,这里就不多说。

    第二,中文的编码不是utf8,而是unicode。这样会导致在分词的时候,和英文相比,我们要处理编码的问题。

    这两点构成了中文分词相比英文分词的一些不同点,后面我们也会重点讲述这部分的处理。当然,英文分词也有自己的烦恼,这个我们在以后再讲。了解了中文预处理的一些特点后,我们就言归正传,通过实践总结下中文文本挖掘预处理流程。

2.  中文文本挖掘预处理一:数据收集

    在文本挖掘之前,我们需要得到文本数据,文本数据的获取方法一般有两种:使用别人做好的语料库和自己用爬虫去在网上去爬自己的语料数据。

    对于第一种方法,常用的文本语料库在网上有很多,如果大家只是学习,则可以直接下载下来使用,但如果是某些特殊主题的语料库,比如“机器学习”相关的语料库,则这种方法行不通,需要我们自己用第二种方法去获取。

    对于第二种使用爬虫的方法,开源工具有很多,通用的爬虫我一般使用beautifulsoup。但是我们我们需要某些特殊的语料数据,比如上面提到的“机器学习”相关的语料库,则需要用主题爬虫(也叫聚焦爬虫)来完成。这个我一般使用ache。 ache允许我们用关键字或者一个分类算法来过滤出我们需要的主题语料,比较强大。

3.  中文文本挖掘预处理二:除去数据中非文本部分

    这一步主要是针对我们用爬虫收集的语料数据,由于爬下来的内容中有很多html的一些标签,需要去掉。少量的非文本内容的可以直接用Python的正则表达式(re)删除, 复杂的则可以用beautifulsoup来去除。去除掉这些非文本的内容后,我们就可以进行真正的文本预处理了。

4. 中文文本挖掘预处理三:处理中文编码问题

    由于Python2不支持unicode的处理,因此我们使用Python2做中文文本预处理时需要遵循的原则是,存储数据都用utf8,读出来进行中文相关处理时,使用GBK之类的中文编码,在下面一节的分词时,我们再用例子说明这个问题。

5. 中文文本挖掘预处理四:中文分词

    常用的中文分词软件有很多,个人比较推荐结巴分词。安装也很简单,比如基于Python的,用"pip install jieba"就可以完成。下面我们就用例子来看看如何中文分词。

    完整代码参见我的github: https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/chinese_digging.ipynb

    首先我们准备了两段文本,这两段文本在两个文件中。两段文本的内容分别是nlp_test0.txt和nlp_test2.txt:

          沙瑞金赞叹易学习的胸怀,是金山的百姓有福,可是这件事对李达康的触动很大。易学习又回忆起他们三人分开的前一晚,大家一起喝酒话别,易学习被降职到道口县当县长,王大路下海经商,李达康连连赔礼道歉,觉得对不起大家,他最对不起的是王大路,就和易学习一起给王大路凑了5万块钱,王大路自己东挪西撮了5万块,开始下海经商。没想到后来王大路竟然做得风生水起。沙瑞金觉得他们三人,在困难时期还能以沫相助,很不容易。

    沙瑞金向毛娅打听他们家在京州的别墅,毛娅笑着说,王大路事业有成之后,要给欧阳菁和她公司的股权,她们没有要,王大路就在京州帝豪园买了三套别墅,可是李达康和易学习都不要,这些房子都在王大路的名下,欧阳菁好像去住过,毛娅不想去,她觉得房子太大很浪费,自己家住得就很踏实。

   我们先讲文本从第一个文件中读取,并使用中文GBK编码,再调用结巴分词,最后把分词结果用uft8格式存在另一个文本nlp_test1.txt

中。代码如下:

复制代码

# -*- coding: utf-8 -*-

import jieba

with open('./nlp_test0.txt') as f:
    document = f.read()
    
    document_decode = document.decode('GBK')
    document_cut = jieba.cut(document_decode)
    #print  ' '.join(jieba_cut)  //如果打印结果,则分词效果消失,后面的result无法显示
    result = ' '.join(document_cut)
    result = result.encode('utf-8')
    with open('./nlp_test1.txt', 'w') as f2:
        f2.write(result)
f.close()
f2.close()

复制代码

    输出的文本内容如下:

    沙 瑞金 赞叹 易 学习 的 胸怀 , 是 金山 的 百姓 有福 , 可是 这件 事对 李达康 的 触动 很大 。 易 学习 又 回忆起 他们 三人 分开 的 前一晚 , 大家 一起 喝酒 话别 , 易 学习 被 降职 到 道口 县当 县长 , 王 大路 下海经商 , 李达康 连连 赔礼道歉 , 觉得 对不起 大家 , 他 最 对不起 的 是 王 大路 , 就 和 易 学习 一起 给 王 大路 凑 了 5 万块 钱 , 王 大路 自己 东挪西撮 了 5 万块 , 开始 下海经商 。 没想到 后来 王 大路 竟然 做 得 风生水 起 。 沙 瑞金 觉得 他们 三人 , 在 困难 时期 还 能 以沫 相助 , 很 不 容易 。

    可以发现对于一些人名和地名,jieba处理的不好,不过我们可以帮jieba加入词汇如下:

jieba.suggest_freq('沙瑞金', True)
jieba.suggest_freq('易学习', True)
jieba.suggest_freq('王大路', True)
jieba.suggest_freq('京州', True)

    现在我们再来进行读文件,编码,分词,编码和写文件,代码如下:

复制代码

with open('./nlp_test0.txt') as f:
    document = f.read()
    
    document_decode = document.decode('GBK')
    document_cut = jieba.cut(document_decode)
    #print  ' '.join(jieba_cut)
    result = ' '.join(document_cut)
    result = result.encode('utf-8')
    with open('./nlp_test1.txt', 'w') as f2:
        f2.write(result)
f.close()
f2.close()   

复制代码

    输出的文本内容如下:

    沙瑞金 赞叹 易学习 的 胸怀 , 是 金山 的 百姓 有福 , 可是 这件 事对 李达康 的 触动 很大 。 易学习 又 回忆起 他们 三人 分开 的 前一晚 , 大家 一起 喝酒 话别 , 易学习 被 降职 到 道口 县当 县长 , 王大路 下海经商 , 李达康 连连 赔礼道歉 , 觉得 对不起 大家 , 他 最 对不起 的 是 王大路 , 就 和 易学习 一起 给 王大路 凑 了 5 万块 钱 , 王大路 自己 东挪西撮 了 5 万块 , 开始 下海经商 。 没想到 后来 王大路 竟然 做 得 风生水 起 。 沙瑞金 觉得 他们 三人 , 在 困难 时期 还 能 以沫 相助 , 很 不 容易 。

    基本已经可以满足要求。同样的方法我们对第二段文本nlp_test2.txt进行分词和写入文件nlp_test3.txt。

复制代码

with open('./nlp_test2.txt') as f:
    document2 = f.read()
    
    document2_decode = document2.decode('GBK')
    document2_cut = jieba.cut(document2_decode)
    #print  ' '.join(jieba_cut)
    result = ' '.join(document2_cut)
    result = result.encode('utf-8')
    with open('./nlp_test3.txt', 'w') as f2:
        f2.write(result)
f.close()
f2.close()  

复制代码

    输出的文本内容如下:

    沙瑞金 向 毛娅 打听 他们 家 在 京州 的 别墅 , 毛娅 笑 着 说 , 王大路 事业有成 之后 , 要 给 欧阳 菁 和 她 公司 的 股权 , 她们 没有 要 , 王大路 就 在 京州 帝豪园 买 了 三套 别墅 , 可是 李达康 和 易学习 都 不要 , 这些 房子 都 在 王大路 的 名下 , 欧阳 菁 好像 去 住 过 , 毛娅 不想 去 , 她 觉得 房子 太大 很 浪费 , 自己 家住 得 就 很 踏实 。

    可见分词效果还不错。

6. 中文文本挖掘预处理五:引入停用词

    在上面我们解析的文本中有很多无效的词,比如“着”,“和”,还有一些标点符号,这些我们不想在文本分析的时候引入,因此需要去掉,这些词就是停用词。常用的中文停用词表是1208个,下载地址在这。当然也有其他版本的停用词表,不过这个1208词版是我常用的。

    在我们用scikit-learn做特征处理的时候,可以通过参数stop_words来引入一个数组作为停用词表。

    现在我们将停用词表从文件读出,并切分成一个数组备用:

复制代码

#从文件导入停用词表
stpwrdpath = "stop_words.txt"
stpwrd_dic = open(stpwrdpath, 'rb')
stpwrd_content = stpwrd_dic.read()
#将停用词表转换为list  
stpwrdlst = stpwrd_content.splitlines()
stpwrd_dic.close()

复制代码

7. 中文文本挖掘预处理六:特征处理

    现在我们就可以用scikit-learn来对我们的文本特征进行处理了,在文本挖掘预处理之向量化与Hash Trick中,我们讲到了两种特征处理的方法,向量化与Hash Trick。而向量化是最常用的方法,因为它可以接着进行TF-IDF的特征处理。在文本挖掘预处理之TF-IDF中,我们也讲到了TF-IDF特征处理的方法。这里我们就用scikit-learn的TfidfVectorizer类来进行TF-IDF特征处理。

    TfidfVectorizer类可以帮助我们完成向量化,TF-IDF和标准化三步。当然,还可以帮我们处理停用词。

    现在我们把上面分词好的文本载入内存:

复制代码

with open('./nlp_test1.txt') as f3:
    res1 = f3.read()
print res1
with open('./nlp_test3.txt') as f4:
    res2 = f4.read()
print res2

复制代码

    这里的输出还是我们上面分完词的文本。现在我们可以进行向量化,TF-IDF和标准化三步处理了。注意,这里我们引入了我们上面的停用词表。

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [res1,res2]
vector = TfidfVectorizer(stop_words=stpwrdlst)
tfidf = vector.fit_transform(corpus)
print tfidf

    部分输出如下:

  (0, 44)	0.154467434933
  (0, 59)	0.108549295069
  (0, 39)	0.308934869866
  (0, 53)	0.108549295069
  ....
  (1, 27)	0.139891059658
  (1, 47)	0.139891059658
  (1, 30)	0.139891059658
  (1, 60)	0.139891059658

    我们再来看看每次词和TF-IDF的对应关系:

复制代码

wordlist = vector.get_feature_names()#获取词袋模型中的所有词  
# tf-idf矩阵 元素a[i][j]表示j词在i类文本中的tf-idf权重
weightlist = tfidf.toarray()  
#打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重
for i in range(len(weightlist)):  
    print "-------第",i,"段文本的词语tf-idf权重------"  
    for j in range(len(wordlist)):  
        print wordlist[j],weightlist[i][j]  

复制代码

    部分输出如下:

-------第 0 段文本的词语tf-idf权重------
一起 0.217098590137
万块 0.217098590137
三人 0.217098590137
三套 0.0
下海经商 0.217098590137
.....
-------第 1 段文本的词语tf-idf权重------
.....
李达康 0.0995336411066
欧阳 0.279782119316
毛娅 0.419673178975
沙瑞金 0.0995336411066
没想到 0.0
没有 0.139891059658
浪费 0.139891059658
王大路 0.29860092332
.....

 

8. 中文文本挖掘预处理七:建立分析模型

    有了每段文本的TF-IDF的特征向量,我们就可以利用这些数据建立分类模型,或者聚类模型了,或者进行主题模型的分析。比如我们上面的两段文本,就可以是两个训练样本了。此时的分类聚类模型和之前讲的非自然语言处理的数据分析没有什么两样。因此对应的算法都可以直接使用。而主题模型是自然语言处理比较特殊的一块,这个我们后面再单独讲。

9.中文文本挖掘预处理总结

    上面我们对中文文本挖掘预处理的过程做了一个总结,希望可以帮助到大家。需要注意的是这个流程主要针对一些常用的文本挖掘,并使用了词袋模型,对于某一些自然语言处理的需求则流程需要修改。比如我们涉及到词上下文关系的一些需求,此时不能使用词袋模型。而有时候我们对于特征的处理有自己的特殊需求,因此这个流程仅供自然语言处理入门者参考。

    下一篇我们来总结英文文本挖掘预处理流程,尽情期待。

 

英文文本挖掘预处理流程总结

    在中文文本挖掘预处理流程总结中,我们总结了中文文本挖掘的预处理流程,这里我们再对英文文本挖掘的预处理流程做一个总结。

1.  英文文本挖掘预处理特点

    英文文本的预处理方法和中文的有部分区别。首先,英文文本挖掘预处理一般可以不做分词(特殊需求除外),而中文预处理分词是必不可少的一步。第二点,大部分英文文本都是uft-8的编码,这样在大多数时候处理的时候不用考虑编码转换的问题,而中文文本处理必须要处理unicode的编码问题。这两部分我们在中文文本挖掘预处理里已经讲了。

    而英文文本的预处理也有自己特殊的地方,第三点就是拼写问题,很多时候,我们的预处理要包括拼写检查,比如“Helo World”这样的错误,我们不能在分析的时候讲错纠错。所以需要在预处理前加以纠正。第四点就是词干提取(stemming)和词形还原(lemmatization)。这个东西主要是英文有单数,复数和各种时态,导致一个词会有不同的形式。比如“countries”和"country","wolf"和"wolves",我们期望是有一个词。

    后面的预处理中,我们会重点讲述第三点和第四点的处理。

2.  英文文本挖掘预处理一:数据收集

    这部分英文和中文类似。获取方法一般有两种:使用别人做好的语料库和自己用爬虫去在网上去爬自己的语料数据。

    对于第一种方法,常用的文本语料库在网上有很多,如果大家只是学习,则可以直接下载下来使用,但如果是某些特殊主题的语料库,比如“deep learning”相关的语料库,则这种方法行不通,需要我们自己用第二种方法去获取。

    对于第二种使用爬虫的方法,开源工具有很多,通用的爬虫我一般使用beautifulsoup。但是我们我们需要某些特殊的语料数据,比如上面提到的“deep learning”相关的语料库,则需要用主题爬虫(也叫聚焦爬虫)来完成。这个我一般使用ache。 ache允许我们用关键字或者一个分类算法模型来过滤出我们需要的主题语料,比较强大。

3.  英文文本挖掘预处理二:除去数据中非文本部分

    这一步主要是针对我们用爬虫收集的语料数据,由于爬下来的内容中有很多html的一些标签,需要去掉。少量的非文本内容的可以直接用Python的正则表达式(re)删除, 复杂的则可以用beautifulsoup来去除。另外还有一些特殊的非英文字符(non-alpha),也可以用Python的正则表达式(re)删除。

4.  英文文本挖掘预处理三:拼写检查更正

    由于英文文本中可能有拼写错误,因此一般需要进行拼写检查。如果确信我们分析的文本没有拼写问题,可以略去此步。

    拼写检查,我们一般用pyenchant类库完成。pyenchant的安装很简单:"pip install pyenchant"即可。

    对于一段文本,我们可以用下面的方式去找出拼写错误:

    完整代码参见我的github: https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/english_digging.ipynb

from enchant.checker import SpellChecker
chkr = SpellChecker("en_US")
chkr.set_text("Many peope likee to watch In the Name of People.")
for err in chkr:
    print "ERROR:", err.word

    输出是:

ERROR: peope
ERROR: likee

    找出错误后,我们可以自己来决定是否要改正。当然,我们也可以用pyenchant中的wxSpellCheckerDialog类来用对话框的形式来交互决定是忽略,改正还是全部改正文本中的错误拼写。大家感兴趣的话可以去研究pyenchant的官方文档。

5.  英文文本挖掘预处理四:词干提取(stemming)和词形还原(lemmatization)

    词干提取(stemming)和词型还原(lemmatization)是英文文本预处理的特色。两者其实有共同点,即都是要找到词的原始形式。只不过词干提取(stemming)会更加激进一点,它在寻找词干的时候可以会得到不是词的词干。比如"imaging"的词干可能得到的是"imag", 并不是一个词。而词形还原则保守一些,它一般只对能够还原成一个正确的词的词进行处理。个人比较喜欢使用词型还原而不是词干提取。

    在实际应用中,一般使用nltk来进行词干提取和词型还原。安装nltk也很简单,"pip install nltk"即可。只不过我们一般需要下载nltk的语料库,可以用下面的代码完成,nltk会弹出对话框选择要下载的内容。选择下载语料库就可以了。

import nltk
nltk.download()

    在nltk中,做词干提取的方法有PorterStemmer,LancasterStemmer和SnowballStemmer。个人推荐使用SnowballStemmer。这个类可以处理很多种语言,当然,除了中文。

from nltk.stem import SnowballStemmer
stemmer = SnowballStemmer("english") # Choose a language
stemmer.stem("countries") # Stem a word

    输出是"countri",这个词干并不是一个词。    

    而如果是做词型还原,则一般可以使用WordNetLemmatizer类,即wordnet词形还原方法。

from nltk.stem import WordNetLemmatizer
wnl = WordNetLemmatizer()
print(wnl.lemmatize('countries'))  

    输出是"country",比较符合需求。

    在实际的英文文本挖掘预处理的时候,建议使用基于wordnet的词形还原就可以了。

    在这里有个词干提取和词型还原的demo,如果是这块的新手可以去看看,上手很合适。

6. 英文文本挖掘预处理五:转化为小写

    由于英文单词有大小写之分,我们期望统计时像“Home”和“home”是一个词。因此一般需要将所有的词都转化为小写。这个直接用python的API就可以搞定。

7. 英文文本挖掘预处理六:引入停用词

    在英文文本中有很多无效的词,比如“a”,“to”,一些短词,还有一些标点符号,这些我们不想在文本分析的时候引入,因此需要去掉,这些词就是停用词。个人常用的英文停用词表下载地址在这。当然也有其他版本的停用词表,不过这个版本是我常用的。

    在我们用scikit-learn做特征处理的时候,可以通过参数stop_words来引入一个数组作为停用词表。这个方法和前文讲中文停用词的方法相同,这里就不写出代码,大家参考前文即可。

8. 英文文本挖掘预处理七:特征处理

    现在我们就可以用scikit-learn来对我们的文本特征进行处理了,在文本挖掘预处理之向量化与Hash Trick中,我们讲到了两种特征处理的方法,向量化与Hash Trick。而向量化是最常用的方法,因为它可以接着进行TF-IDF的特征处理。在文本挖掘预处理之TF-IDF中,我们也讲到了TF-IDF特征处理的方法。

    TfidfVectorizer类可以帮助我们完成向量化,TF-IDF和标准化三步。当然,还可以帮我们处理停用词。这部分工作和中文的特征处理也是完全相同的,大家参考前文即可。

9. 英文文本挖掘预处理八:建立分析模型

    有了每段文本的TF-IDF的特征向量,我们就可以利用这些数据建立分类模型,或者聚类模型了,或者进行主题模型的分析。此时的分类聚类模型和之前讲的非自然语言处理的数据分析没有什么两样。因此对应的算法都可以直接使用。而主题模型是自然语言处理比较特殊的一块,这个我们后面再单独讲。

10. 英文文本挖掘预处理总结

    上面我们对英文文本挖掘预处理的过程做了一个总结,希望可以帮助到大家。需要注意的是这个流程主要针对一些常用的文本挖掘,并使用了词袋模型,对于某一些自然语言处理的需求则流程需要修改。比如有时候需要做词性标注,而有时候我们也需要英文分词,比如得到"New York"而不是“New”和“York”,因此这个流程仅供自然语言处理入门者参考,我们可以根据我们的数据分析目的选择合适的预处理方法。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值