文本分析
文本分析指从文本中抽取出的特征来量化来表示文本信息,并在此基础上对其进行基于数学模型的处理。它是文本挖掘、信息检索的一个基本问题。
在“大数据”盛行的今天,对于非结构化信息的处理已经成了许多工作的必选项,而自然语言书写的文本,就是最典型的一种非结构化信息。
文本分析已经从学院派象牙塔中的研究课题逐步渗入到各个应用领域。对于正在做或者有志于做数据分析的人,掌握基本的文本分析知识和技法,已经成为必要。
向量空间模型
针对文本的具体操作很多,最典型的就是分类和聚类。引入机器学习的办法,让程序自己“学会”如何去区分不同类型的文本,是当前业界通行的办法。
而如此做的前提,是要把一个个自然语言文档(Document),转换为一个个可以用来进行数学运算的向量(Vector)。
当你用某种机器学习算法对某些文本进行分析的时候,你首先需要一个训练集(Training Set)。
假设这个训练集中包含N个文档,你要把这N个文档转换成N个与之一一对应的向量。再假设每个向量包含M维。
那么最终,当全部转换完之后,你把所有N个M维向量放在一起,就构成了一个NxM的矩阵(Matrix)。
这个矩阵就是你的训练集所构建的向量空间模型(Vector Space Model,VSM)。
之后的算法,就是运行在这个NxM的矩阵之上的。
构建向量空间模型
N是文档数,那么M是什麽数呢?M是你的全部训练集文本(所有N个文档)中包含的Term数。
这个Term可以是字,也可以是词,还可以是若干连续出现的字的组合,具体是什么,可以由你自己来确定。
在此,我们介绍一种最简单,最方便,效果总体而言还不错的,确定Term的方法:基于n-gram的文本特征提取方法。
基于n-gram的文档特征提取
n-gram中的n和文档个数的N无关(此处特别用大小写来区分他们),这个n是一个由你确定的值,它指的是最长Term中包含的汉字的个数。
一般情况下,我们选n=2就好了。当n==2时的n-gram又叫做bigram。n==1时叫unigram,n==3时叫trigram。
假设我们的N个文档中有一个是下面这个样子(为简单起见,假设整个文档就一句话):
张继科在比赛中露出了碎花内裤。
那么我们首先把这个文档切分成unigram:
{张,继,科,在,比,赛,中,露,出,了,碎,花,内,裤}
然后再将其切分成bigram:
{张继,继科,科在,在比,比赛,赛中,中露,露出,出了,了碎,碎花,花内,内裤}
注意到bigram是怎么切分的没有?对了,就是取长度为2的窗口,从头到尾连续切分文档,每次后移长度为1。
上面切分出来的这些字段,我们将其称为Term。我们将unigram和bigram的所有Term合并起来,就是基于bigram的全部Term,总共27个:
{张,继,科,在,比,赛,中,露,出,了,碎,花,内,裤,张继,继科,科在,在比,比赛,赛中,中露,露出,出了,了碎,碎花,花内,内裤}。
这是一个文档,所有文档,都按如此方法切分成若干的Term。
NOTE:如果是基于trigram的,则取全部unigram,bigram和trigram的Term的集合。
针对Term计算TF-IDF
N个文档,设其中第i个文档的Term为ci个(i 取值区间为[1, N])。那么这N个文档分别有:c1,c2...cn个Term。
这些Term中肯定有些是重复的。我们对所有这些Term做一个去重操作,最后得出的uni-Term的个数就是M。
换言之,在这N个文档中,基于bigram抽取的文本特征共有M个。
那么针对具体的一个文档,我们就可以构建一个M维的向量,其中每一维对应这M个Term中的一个。
每一个维度的值,都是一个实数(一般在计算机处理中是float或者double类型)。
这个实数值,通常的情况下,取这一维度所对应Term在全部训练文档中的TF-IDF(请自行百度TF-IDF)。
VSM成型
假设我们一共处理了1万个文档(N == 10000),总共得出了2万个Term (M == 20000)。
上面那个例子,“张继科比赛中露出了碎花内裤” 这一文档共包含27个Term。对应这个文档的向量就会是一个2万维的向量,其中27个维度有大于零的值,其他维度的值都是0——很稀疏啊!
最后这1万个文档就组成了一个10000 x 20000的矩阵。
缩减VSM
如果在一个10000 x 20000的矩阵里,每个Vector都只有20多个维度有非零值,那它也太稀疏了。这样稀疏的矩阵恐怕也不会有太好的运算效果。
而且,一些区分度过大的Term(例如某一个Term仅仅只在一个或者极少的文档中出现),在经过运算之后往往会拥有过大的权重,导致之后只要一个文档包含这个Term就会被归到某一个类。这种情况显然是我们要避免的。
因此,我们最好先对所有的Term做一个过滤。此处讲两个特别简单和常见的Term筛选方法:
1. 设定DF(DocumentFrequency)的下限
设定一个Threshold (e.g. DF_Threshold = 2),若一个Term的DF小于该Threshold,则将该Term弃之不用。
2. 当对文本进行分类运算时,可以根据每个Term的信息熵对其进行筛选
一个Term的信息熵(Entroy)表现了该Term在不同类别中的分布情况。
一般而言,一个Term的Entropy越大,则说明它在各个类中均匀出现的概率越大,因此区分度就越小;反之,Entroy越小也就说明该Term的类别区分度越大。
我们当然要选用Entroy尽量小的Term。具体选用多少,可以自己定义一个Threshold。
Entropy_Threshold可以是一个数字(例如8000),也可以是一个百分比(例如40%)。
计算了所有Term的Entropy之后,按Entropy从小到大排序,选取不大于
Entropy_Threshold的前若干个,作为最终构建VSM的Term。
假设所有的训练样本一共被分为K类,则Entropy的计算方法如下(设tx表示某个具体的Term):
Entropy(tx) = Sigma[i] ((-P(ci) *log(P(ci)))) -- i取值范围为[1,K]
其中,P(ci) 表示tx在第i个列别中的出现概率,具体计算方法采用softmax算法,如下:
P(ci)= exp(y(ci)) /Sigmaj -- j取值范围为[1,K]
其中y(ci) 为tx在类别j中出现的次数。
来看一个简单的例子,假设我们的样本空间一共被分为5个类别,则C == 5。
假设tx在5个列别中出现的次数依次为{1,3,0,0,4}。则:
p(c1) = exp(1) / (exp(1) + exp(3) +exp(0) + exp(0) + exp(4))
p(c2) = exp(3) / (exp(1) + exp(3) + exp(0) + exp(0) + exp(4))
p(c3)= exp(0) / (exp(1) + exp(3) + exp(0)+ exp(0) + exp(4))
p(c4)= exp(0) / (exp(1) + exp(3) + exp(0)+ exp(0) + exp(4))
p(c5)= exp(4) / (exp(1) + exp(3) + exp(0) +exp(0) + exp(4))
entroy(tx) = -p(c1)log(p(c1)) -p(c2)log(p(c2)) -p(c3)log(p(c3))-p(c4)log(p(c4)) -p(c5)*log(p(c5))
就这样计算!
经过筛选,M个Term缩减为M' 个,我们NxM' 矩阵变得更加精炼有效了。现在,把它扔给算法库去做训练吧!
基于VSM的运算
如果要做聚类,则我们将这个矩阵作为输入传给某个算法,例如:KMeansClustering,我们设K = 5。
该算法经过运算之后,会给每一个向量赋一个[0,4]区间内的值,这个值就表示了该向量对应文档最终被聚类的结果。
如果要做分类操作,则需要对训练集中的文档进行人工标注,给每一个文档标注一个指定的类别。
然后,除了将文档本身转化成一个向量之外,还需要将这个类别转化成一个数值,一般直接将类名排序,然后把排序的index作为类别数值即可。
然后同样是把这个VSM输入给一个具体算法,例如:基于Logistic Regression的Multiclassification。经过运算后,会得到一个专门的分类模型。
我们再将一个新的,不属于训练集的文档根据上面的VSM进行转换,转换成一个向量。把这个向量输入给分类模型,分类模型会根据每一个预定的类,给出一个该向量被分到该类的可能性数值,可能性取值区间(0, 1)。
这几类中可能性最高的那个,就是分类模型预测的这个文档的最终分类。