任务4 自然语言处理
朴素贝叶斯
首先,要明白贝叶斯统计方式与统计学中的频率概念是不同,从频率的角度出发,即假定数据遵循某种分布,我们的目标是确定该分布的几个参数,在某个固定的环境一下做模型。而贝叶斯则是根据实际的推理方式来建模。我们拿到的数据,来更新模型对某事件即将发生的可能性的预测结果。在贝叶斯统计学中,我们使用数据来描述模型,而不是使用模型来描述数据。
贝叶斯定理旨在计算P(A|B)的值,也就是在已知B发生的条件下,A发生的概率是多少。大多数情况下,B是被观察事件,比如“昨天下雨了”,A为预测结果“今天会下雨”。对数据挖掘来说,B通常是观察样本个体,A为被预测个体所属类别。所以,说简单一点,贝叶斯就是计算的是:B是A类别的概率。
贝叶斯公式:
举例说明,我们想计算含有单词drugs的邮件为垃圾邮件的概率。
在这里,A为“这是封垃圾邮件”。我们先来计算P(A),它也被称为先验概率,计算方法是,统计训练中的垃圾邮件的比例,如果我们的数据集每100封邮件有30封垃圾邮件,P(A)为30/100=0.3。
B表示“该封邮件含有单词drugs”。类似地,我们可以通过计算数据集中含有单词drugs的邮件数P(B)。如果每100封邮件有10封包含有drugs,那么P(B)就为10/100=0.1。
P(B|A)指的是垃圾邮件中含有的单词drugs的概率,计算起来也很容易,如果30封邮件中有6封含有drugs,那么P(B|A)的概率为6/30=0.2。
现在,就可以根据贝叶斯定理计算出P(A|B),得到含有drugs的邮件为垃圾邮件的概率。把上面的每一项带入前面的贝叶斯公式,得到结果为0.6。这表明如果邮件中含有drugs这个词,那么该邮件为垃圾邮件的概率为60%。
朴素贝叶斯
其实,通过上面的例子我们可以知道它能计算个体从属于给定类别的概率。因此,他能用来分类。
我们用C表示某种类别,用D代表数据集中的一篇文档,来计算贝叶斯公式所要用到的各种统计量,对于不好计算的,做出朴素假设,简化计算。
P©为某一类别的概率,可以从训练集中计算得到。
P(D)为某一文档的概率,它牵扯到很多特征,计算很难,但是,可以这样理解,当在计算文档属于哪一类别时,对于所有类别来说,每一篇文档都是独立重复事件,P(D)相同,因此根本不用计算它。稍后看怎样处理它。
P(D|C)为文档D属于C类的概率,由于D包含很多特征,计算起来很难,这时朴素贝叶斯就派上用场了,我们朴素地假定各个特征是互相独立的,分别计算每个特征(D1、D2、D3等)在给定类别的概率,再求他们的积。
上式右侧对于二值特征相对比较容易计算。直接在数据集中进行统计,就能得到所有特征的概率值。
相反,如果我们不做朴素的假设,就要计算每个类别不同特征之间的相关性。这些计算很难完成,如果没有大量的数据或足够的语言分析模型是不可能完成的。
到这里,算法就很明确了。对于每个类别,我们都要计算P(C|D),忽略P(D)项。概率较高的那个类别即为分类结果。
算法应用示例
下面举例说明下计算过程,假如数据集中有以下一条用二值特征表示的数据:[1,0,0,1]。
训练集中有75%的数据集属于类别0,25%属于类别1,且每一个特征属于每个类别的概率为:
类别0:[0.3, 0.4, 0.4, 0.7]
类别1:[0.7, 0.3, 0.4, 0.9]
注:上述类别中的小数表示有多少概率该特征为1,例如0.3表示有30%的数据,特征1的值为1。
我们来计算一下这条数据属于类别0的概率。类别为0时,P(C=0) = 0.75。
朴素贝叶斯算法不用P(D),因此我们不用计算它。
P(D|C=0) = P(D1|C=0) * P(D2|C=0) * P(D3|C=0) * P(D4|C=0)
= 0.3 * 0.6 * 0.6 * 0.7
= 0.0756
现在我们就可以计算该条数据从属于每个类别的概率。
P(C=0|D) = P(C=0) * P(D|C=0)
= 0.75 * 0.0756
= 0.0567
接着计算类别1的概率,方法同上。可以得到
P(C=1|D) = 0.06615
由此可以推断这条数据应该分到类别1中。以上就是朴素贝叶斯的全部计算过程。还有一点应该注意,通常, P(C=0|D) + P(C=1|D) 应该等于1。然而在上述中并不是等于1,这是因为我们在计算中省去了公式中的P(D)项。
补充:
上述只考虑了二值特征属性(离散属性)的情况,但是,在实际情况中也会遇上非离散属性而是连续属性的情况,这时就该用概率密度函数来计算条件概率P(x|c)。μ(c,i)和 σ(c,i)^2分别是第c类样本在第i个属性上取值的均值和方差。则有:
同时,对于朴素贝叶斯还需要说明的一点是:若某种属性值在训练集中没有与某个类同时出现过,则直接基于概率估计公式得出来概率为0,再通过各个属性概率连乘式计算出的概率也为0,这就导致没有办法进行分类了,所以,为了避免属性携带的信息被训练集未出现的属性值“抹去”,在估计概率值时通常要进行“平滑”,常用“拉普拉斯修正”,具体来讲,令N表示训练集D中可能的类别数,Ni表示第i个属性可能的取值数。
拉普拉斯修正避免了样本不充分而导致概率估计为零的问题,并且在训练集样本变大的时候,修正过程所引入的先验的影响也会逐渐变得可忽视,使得估计值越来越接近实际概率值。
-
朴素贝叶斯的原理
朴素贝叶斯法对条件概率分布做了独立性假设,由于这是一个较强的假设,朴素贝叶斯法也由此而得名,具体的,条件独立性的假设是:对于已知类别,假设所有属性相互独立,换言之,假设每个属性独立地对分类结果产生影响。
-
利用朴素贝叶斯模型进行文本分类
朴素贝叶斯理论源于随机变量的独立性:就文本分类而言,从朴素贝叶斯的角度来看,句子中的两两词之间的关系是相互独立的,即一个对象的特征向量中每个维度都是相互独立的。这是朴素贝叶斯理论的思想基础。其流程如下
-
第一阶段,训练数据生成训练样本集:TF-IDF。
-
第二阶段,对每个类别计算P(yi)。
-
第三阶段,对每个特征属性计算所有类别下的条件概率p(ai|yi)。
-
第四阶段,对每个类别计算p(x|yi)p(yi)。
-
第五阶段,以p(x|yi)p(yi)的最大项作为x的所属类别。
SVM模型
- SVM的原理
见博客:https://blog.youkuaiyun.com/weixin_39605679/article/details/81170300
- 利用SVM模型进行文本分类
以天气分类为例,我们的目的是运用支持向量机SVM(libsvm)来训练出一个天气分类的模型,这个模型可以将新来的语料分成天气类和非天气类两个大类,即正类与负类,具体的流程如下:
1.爬取语料数据
首先,第一步要做的就是网上爬取天气相关的语料,可以运用Python爬虫爬取百度相关搜索的词条,进行多轮爬取,我们将跟天气相关的语料称为正语料,与天气无关的语料称为负语料,正语料和负语料分开爬取,一般来说,训练模型所需要的正负语料比例大概是1:3到1:5,也就是说训练天气模型的时候,正语料大概是10000条左右,负语料为30000+条。
2.语料的处理
爬完语料之后进行人工筛选,将一些不纯的正语料去掉,剩下的纯净的正语料。之后再将剩下的正负语料进行进一步处理,比如停用词的去除等操作,就是讲语料中没有意义的词去除,eg,“吗”、“的”…
3.抽取测试语料
这里要注意,语料处理好之后,大概要从语料中抽10%的语料,用于模型训练好之后的测试,即抽取大概1000条正语料和3000条负语料作为测试语料,剩下的语料作为训练语料。
4.分词处理
将所有的语料进行分词处理,将完整的语料分成若干词语,分词可以运用“结巴”分词的库。
5.语料标注
将每一个分词后的语料进行标注,正语料标注为1,负语料标注为0。语料和标签之间用TAB分隔,即“\t”。
6.打乱语料
将标注好的正负语料进行混合,然后进行打乱顺序,让带标签的正负语料充分混合。
7.特征提取(特征选择)
可以运用卡方或者互信息等方法将分词之后的语料每个词的特征提取出来,即每一个词语与当前类别的相关程度,特征提取也是为后面的向量化做准备的。可以用feature_select.py。
python feature_select.py input.txt output.txt
1
特征提取结束可以得到weather_train_feature_select.txt ,里面会有每个特征词与相关类别的相关度排序。
8.向量化
就是将我们处理好的数据进行向量化,将我们的语料转化成向量,分好词的语料命中之前特征提取的特征词,那么就将向量中的这个值设置为1,其他的为0。这个过程中,特征词就是这个向量的维度,每个语料都是一个这么多维度的向量。向量化执行一个vector.sh脚本文件,里面指定feature_num,text_data,train_model这几个文件,其中feature_num=500是指我们取前500个特征词作为我们训练模型的维度,text_data使我们之前分好词打好标签的混合好的语料,train_data是我们指定好向量化好之后生成的向量化文件。
同时还需要指定如下文件:
其中feature_file是进行特征选择之后的文件,weather_feature_kv.dict是一些时间和地点的简直对,目的是为了减少我们特征向量的维度,内容如图所示:
weather_feature.tire是自定义的一些的天气参数,如图所示:
我们之前定的维度是500维,加上这两个文件,特征向量就是502维的。
9.参数调优
向量化之后就是可以调用libsvm中的grid.py,libsvm就可以自动调出最优的参数c和g。(libsvm自行下载)调用示例:
python grid.py libsvm.weather.train.txt
1
其中libsvm.weather.train.txt是我们上一步向量化得到的文件。之后是漫长的参数调优,最后会得到c和g的结果。
10.训练模型
参数调优之后,我们就可以调用libsvm中的svm-train来训练模型,训练的时候同时要设置之前参数调优得到的结果,最终我们会得到一个天气的模型,训练模型用到train_model.sh,其中要制定好生成的模型文件路径 :
train_model=…/…/…/weather_source/libsvm.fea${feature_num}.weather.model
1
除此之外,还要将参数调优得到的结果c和g传入一起训练,还要将参数b设置为1,为了得到的分数是其概率。最终可以得到我们想要的模型,如果我们
11.预测结果
调用svmpredict,根据训练获得的模型,对数据集合进行预测。通过对数据集合的预测,可测得准确率与召回率。调用方法如下所示:
./svm-predict ../weather_source/libsvm.weather.test.train.txt ../weather_source/libsvm.fea500.weather.model ../weather_source/predict_result.txt
1
最终就会得到预测的结果predict_result.txt 。
LDA主题模型
前面的博客提到PCA是常用的有效的数据降维的方法,与之相同的是LDA也是一种将数据降维的方法。PCA已经是一种表现很好的数据降维的方法,那为什么还要有LDA呢?下面我们就来回答这个问题?
PCA是一种无监督的数据降维方法,与之不同的是LDA是一种有监督的数据降维方法。我们知道即使在训练样本上,我们提供了类别标签,在使用PCA模型的时候,我们是不利用类别标签的,而LDA在进行数据降维的时候是利用数据的类别标签提供的信息的。
从几何的角度来看,PCA和LDA都是讲数据投影到新的相互正交的坐标轴上。只不过在投影的过程中他们使用的约束是不同的,也可以说目标是不同的。PCA是将数据投影到方差最大的几个相互正交的方向上,以期待保留最多的样本信息。样本的方差越大表示样本的多样性越好,在训练模型的时候,我们当然希望数据的差别越大越好。否则即使样本很多但是他们彼此相似或者相同,提供的样本信息将相同,相当于只有很少的样本提供信息是有用的。样本信息不足将导致模型性能不够理想。这就是PCA降维的目标:将数据投影到方差最大的几个相互正交的方向上。这种约束有时候很有用,比如在下面这个例子:
对于这个样本集我们可以将数据投影到x轴或者y轴,但这都不是最佳的投影方向,因为这两个方向都不能最好地反映数据的分布。很明显还存在最佳的方向可以描述数据的分布趋势,那就是图中红色直线所在的方向。也是数据样本做投影,方差最大的方向。向这个方向做投影,投影后数据的方差最大,数据保留的信息最多。
但是,对于另外的一些不同分布的数据集,PCA的这个投影后方差最大的目标就不太合适了。比如对于下面图片中的数据集:
针对这个数据集,如果同样选择使用PCA,选择方差最大的方向作为投影方向,来对数据进行降维。那么PCA选出的最佳投影方向,将是图中红色直线所示的方向。这样做投影确实方差最大,但是是不是有其他问题。聪明的你一定发现了,这样做投影之后两类数据样本将混合在一起,将不再线性可分,甚至是不可分的。这对我们来说简直就是地狱,本来线性可分的样本被我们亲手变得不再可分。
帅气英俊的你也一定发现了,图中还有一条耀眼的黄色直线,向这条直线做投影即能使数据降维,同时还能保证两类数据仍然是线性可分的。上面的这个数据集如果使用LDA降维,找出的投影方向就是黄色直线所在的方向。
这其实就是LDA的思想,或者说LDA降维的目标:将带有标签的数据降维,投影到低维空间同时满足三个条件:
- 尽可能多地保留数据样本的信息(即选择最大的特征是对应的特征向量所代表的的方向)。
- 寻找使样本尽可能好分的最佳投影方向。
- 投影后使得同类样本尽可能近,不同类样本尽可能远。
其实第二个和第三个条件是基本等价的,我们很容易想到,使样本尽可能好分的投影方向,就是要使投影后使得同类样本尽可能近,不同类样本尽可能远。
上面大致讲解的LDA的基本思想,以及与PCA的不同,下面就来介绍一下LDA模型。
LDA模型
LDA模型实现基本思想是和PCA相同的,都是向低维空间做投影,所以对于向量投影的基本的知识,这里就不再进行讲解了,不懂得同学可以参看文章开头提到的那篇PCA的博客。
符号
- x : 表示训练样本,使用列向量表示
- xjixij:表示第i类中的第j个样本
- C:表示有C类样本
- μiμi:表示第i类训练样本的均值 (i=1,2,…,C)
- MiMi:表示第i类训练样本的数目
- MM:表示训练样本的总数目 M=∑Ci=0MiM=∑i=0CMi
- μμ:是所有样本的均值向量 μ=1M∑Mi=1xi=1C∑Ci=1μiμ=1M∑i=1Mxi=1C∑i=1Cμi
- DiDi:表示第i类样本集合
- SwSw:表示类内散度矩阵,w是within的简写
- SbSb:表示类间散度矩阵,b是between的简写
优化目标
为什么是线性判别分析呢?所谓的线性就是,我们要将数据点投影到直线上(可能是多条直线),直线的函数解析式又称为线性函数。通常直线的表达式为
y=wTxy=wTx
其实这里的x就是样本向量(列向量),如果投影到一条直线上w就是一个特征向量(列向量形式)或者多个特征向量构成的矩阵。至于w为什么是特征向量,后面我们就能推导出来。y为投影后的样本点(列向量)。
我们首先使用两类样本来说明,然后再推广至多类问题。
将数据投影到直线w上,则两类样本的中心在直线上的投影分别为wTμ0wTμ0和wTμ1wTμ1,若将所有的样本点都都投影到直线上,则两类样本的协方差分别为wT∑0wwT∑0w和wT∑1wwT∑1w.
投影后同类样本协方差矩阵的求法:
∑x∈Di(wTx−wTui)2=∑x∈Di(wT(x−ui))2=∑x∈DiwT(x−μi)(x−ui)Tw=wT∑x∈Di[(x−μi)(x−ui)T]w∑x∈Di(wTx−wTui)2=∑x∈Di(wT(x−ui))2=∑x∈DiwT(x−μi)(x−ui)Tw=wT∑x∈Di[(x−μi)(x−ui)T]w
上式的中间部分∑x∈Di(x−μi)(x−ui)T∑x∈Di(x−μi)(x−ui)T便是同类样本投影前的协方差矩阵。由还可以看出同类样本投影前后协方差矩阵之间的关系。如果投影前的协方差矩阵为ΣΣ 则投影后的为 wTΣwwTΣw.
上式的推导需要用到如下公式:a,ba,b 都是列向量,(a⋅b)2=(aTb)2=(aTb)(aTb)=(aTb)(aTb)T=aTbbTa(a⋅b)2=(aTb)2=(aTb)(aTb)=(aTb)(aTb)T=aTbbTa .
**欲使同类样例的投影点尽可能接近,可以让同类样本点的协方差矩阵尽可能小,**即wT∑0w+wT∑1wwT∑0w+wT∑1w 尽可能小; 而欲使异类样例的投影点尽可能远离,可以让类中心之间的距离尽可能大,即||wTμ0−wTμ1||22||wTμ0−wTμ1||22 尽可能大。同时考虑二者,则可得到欲最大化的目标
J=||wTμ0−wTμ1||22wT(∑0+∑1)w=wT(μ0−μ1)(μ0−μ1)TwwT(∑0+∑1)wJ=||wTμ0−wTμ1||22wT(∑0+∑1)w=wT(μ0−μ1)(μ0−μ1)TwwT(∑0+∑1)w
上式中的||⋅||||⋅||表示欧几里得范数,||x−μi||2=(x−μi)T(x−μi)||x−μi||2=(x−μi)T(x−μi)
协方差与样本分布的关系
上面的这段话来自于周志华老师的机器学习书籍,不知道大家对上面的这段话是否存在疑问? 我在阅读 的时候是存在疑问的,即为什么同类样本点的协方差矩阵尽可能小,同类样例的投影点就尽可能接近。我想大概是这样的:我们在最初接触协方差是用来表示两个变量的相关性,我们来看一下协方差和方差的公式:
cov=1n∑(X−X¯)(Y−Y¯)cov=1n∑(X−X¯)(Y−Y¯)
cov=1n∑(X−X¯)(X−X¯)cov=1n∑(X−X¯)(X−X¯)
可以看到协方差的公式和方差十分相近,甚至可以说方差是协方差的一种特例。我们知道方差可以用来度量数据的离散程度,(X−X¯)(X−X¯)越大,表示数据距离样本中心越远,数据越离散,数据的方差越大。同样我们观察,协方差的公式,(X−X¯)(X−X¯)和(Y−Y¯)(Y−Y¯)越大,表示数据距离样本中心越远,数据分布越分散,协方差越大。相反他们越小表示数据距离样本中心越近,数据分布越集中,协方差越小。
所以协方差不仅是反映了变量之间的相关性,同样反映了多维样本分布的离散程度(一维样本使用方差),协方差越大(对于负相关来说是绝对值越大),表示数据的分布越分散。所以上面的**“欲使同类样例的投影点尽可能接近,可以让同类样本点的协方差矩阵尽可能小”**就可以理解了。
类间散度矩阵
类间散度矩阵其实就是协方差矩阵乘以样本数目,即散度矩阵与协方差矩阵只是相差一个系数。对于协方差矩阵和散度矩阵有疑问的同学可以参考博文:机器学习中的数学(3)——协方差矩阵和散布(散度)矩阵
对于两类样本而言:
Sb=(μ0−μ1)(μ0−μ1)TSb=(μ0−μ1)(μ0−μ1)T
对于多类问题,类间散度矩阵公式:
Sb=∑i=1C(μi−μ)(μi−μ)TSb=∑i=1C(μi−μ)(μi−μ)T
表示各个类样本均值的协方差矩阵。
如果我们只使用这样一个类间散度矩阵这样一个约束条件来对数据进行降维:即使得类间的样本投影后尽可能远离。那么参考PCA的降维过程:
Sbu=λuSbu=λu
不同的是,为了保证类间的样本投影后尽可能远离,我们应该选择特征值最大的特征向量代表的方向做投影。这样才能保证,不同类样本投影之后方差尽可能地大,尽可能能地远离。
类内散度矩阵
对于两类问题而言:
Sw=Σ0+Σ1=∑x∈D0(x−μ0)(x−u0)T+∑x∈D1(x−μ1)(x−u1)TSw=Σ0+Σ1=∑x∈D0(x−μ0)(x−u0)T+∑x∈D1(x−μ1)(x−u1)T
对于多类问题类内散度矩阵公式:
Sw=∑i=1C∑j=1Mi(xji−μi)(xji−μ1)TSw=∑i=1C∑j=1Mi(xij−μi)(xij−μ1)T
其中:
∑j=1Mi(xji−μi)(xji−μi)T∑j=1Mi(xij−μi)(xij−μi)T
表示第i类样本的协方差矩阵。所以SwSw就是表示C类样本协方差矩阵之和。
如果我们只使用这样一个类内散度矩阵这样一个约束条件来对数据进行降维:即使得类内的样本投影后尽可能接近。那么参考PCA的降维过程:
Swu=λuSwu=λu
不同的是,为了保证类内的样本投影后尽可能接近,我们应该选择特征值最小的特征向量代表的方向做投影。这样才能保证,同类样本投影之后方差尽可能地小,尽可能能地接近。
优化
定义过类内散度矩阵和类间散度矩阵后,我们可以将上述的优化目标重新写为:
J=wTSbwwTSwwJ=wTSbwwTSww
这就是LDA欲最大化的目标,即SbSb与SwSw的广义瑞利商。
如何确定ww呢?注意到上式的分子和分母都是关于ww的二次项,因此上式的解与ww的长度无关,只与其方向有关.不失一般性,令wTSww=1wTSww=1,则上式等价于:
minw−wTSbwminw−wTSbw
st.wTSww=1st.wTSww=1
使用拉格朗日乘子法,(对于拉格朗日乘子法不太了解的同学可以参考博文:机器学习中的数学(5)——拉格朗日乘子法和KKT条件)上式等价于:
c(w)=wTSbw−λ(wTSww−1)c(w)=wTSbw−λ(wTSww−1)
dcdw=2Sbw−2λSww=0dcdw=2Sbw−2λSww=0
Sbw=λSwwSbw=λSww
S−1wSbw=λwSw−1Sbw=λw
可以看到上式就有转化为一个求解特征值和特征向量的问题了。w就是我们要求解的特征向量,这就验证了我们之前所说的式子y=wTxy=wTx中的w就是特征向量构成的矩阵。
但是到这里我们仍然有个问题需要解决,那就是SwSw是否可逆。遗憾的是在实际的应用中,它通常是不可逆的,我们通常有连个办法解决该问题。
拓展
解决方法一:
令Sw=Sw+γISw=Sw+γI, 其中γγ是一个特别小的数,这样SwSw一定可逆。
解决方法二: