LSI潜在语义空间基本原理与代码实现.docx

上传人:b****6 文档编号:9041900 上传时间:2023-02-02 格式:DOCX 页数:13 大小:412KB
下载 相关 举报
LSI潜在语义空间基本原理与代码实现.docx_第1页
第1页 / 共13页
LSI潜在语义空间基本原理与代码实现.docx_第2页
第2页 / 共13页
LSI潜在语义空间基本原理与代码实现.docx_第3页
第3页 / 共13页
LSI潜在语义空间基本原理与代码实现.docx_第4页
第4页 / 共13页
LSI潜在语义空间基本原理与代码实现.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

LSI潜在语义空间基本原理与代码实现.docx

《LSI潜在语义空间基本原理与代码实现.docx》由会员分享,可在线阅读,更多相关《LSI潜在语义空间基本原理与代码实现.docx(13页珍藏版)》请在冰豆网上搜索。

LSI潜在语义空间基本原理与代码实现.docx

LSI潜在语义空间基本原理与代码实现

窗体底端

潜在语义分析

 

1LSAIntroduction

LSA(latentsemanticanalysis)潜在语义分析,也被称为LSI(latentsemanticindex),是ScottDeerwester,SusanT.Dumais等人在1990年提出来的一种新的索引和检索方法。

该方法和传统向量空间模型(vectorspacemodel)一样使用向量来表示词(terms)和文档(documents),并通过向量间的关系(如夹角)来判断词及文档间的关系;而不同的是,LSA将词和文档映射到潜在语义空间,从而去除了原始向量空间中的一些“噪音”,提高了信息检索的精确度。

2传统方法的缺点

传统向量空间模型使用精确的词匹配,即精确匹配用户输入的词与向量空间中存在的词。

由于一词多义(polysemy)和一义多词(synonymy)的存在,使得该模型无法提供给用户语义层面的检索。

比如用户搜索”automobile”,即汽车,传统向量空间模型仅仅会返回包含”automobile”单词的页面,而实际上包含”car”单词的页面也可能是用户所需要的。

 

下面是LDA原始Paper[1]里举的一个例子:

上图是一个Term-Document矩阵,X代表该单词出现在对应的文件里,星号表示该词出现在查询(Query)中,当用户输入查询”IDFincomputer-basedinformationlookup”时,用户是希望查找与信息检索中IDF(文档频率)相关的网页,按照精确词匹配的话,文档2和3分别包含查询中的两个词,因此应该被返回,而文档1不包含任何查询中的词,因此不会被返回。

但我们仔细看看会发现,文档1中的access,retrieval,indexing,database这些词都是和查询相似度十分高的,其中retrieval和lookup是同义词。

显然,从用户的角度看,文档1应该是相关文档,应该被返回。

再来看文档2:

computerinformationtheory,虽然包含查询中的一次词information,但文档2和IDF或信息检索无关,不是用户需要的文档,不应该被返回。

从以上分析可以看出,在本次检索中,和查询相关的文档1并未返回给用户,而无查询无关的文档2却返回给了用户。

这就是同义词和多义词如何导致传统向量空间模型检索精确度的下降。

3LSA如何解决这些问题

LSA潜在语义分析的目的,就是要找出词(terms)在文档和查询中真正的含义,也就是潜在语义,从而解决上节所描述的问题。

具体说来就是对一个大型的文档集合使用一个合理的维度建模,并将词和文档都表示到该空间,比如有2000个文档,包含7000个索引词,LSA使用一个维度为100的向量空间将文档和词表示到该空间,进而在该空间进行信息检索。

而将文档表示到此空间的过程就是SVD奇异值分解和降维的过程。

降维是LSA分析中最重要的一步,通过降维,去除了文档中的“噪音”,也就是无关信息(比如词的误用或不相关的词偶尔出现在一起),语义结构逐渐呈现。

相比传统向量空间,潜在语义空间的维度更小,语义关系更明确。

4 SVD分解[2]

SVD分解作为掌握LSA的基础知识,我单独把它作为一篇文章,可以在这里找到。

5LSA技术细节[1][3]

本节主要讨论LSA技术细节的理论部分,具体代码层面分析和实践在第7节讨论。

LSA的步骤如下:

1.分析文档集合,建立Term-Document矩阵。

2.对Term-Document矩阵进行奇异值分解。

3.对SVD分解后的矩阵进行降维,也就是奇异值分解一节所提到的低阶近似。

4.使用降维后的矩阵构建潜在语义空间,或重建Term-Document矩阵。

下面是IntroductiontoLatentSemanticAnalysis里面的一个例子,描述了完整的LSA步骤,例子后面有我的补充:

假设文档集合如下:

原始的Term-Document矩阵如下:

对其进行奇异值分解:

然后对分解后的矩阵降维,这里保留{S}的最大两个奇异值,相应的{W}{P}矩阵如图,注意{P}在公式中需要转置。

到了这一步后,我们有两种处理方法,论文IntroductiontoLatentSemanticAnalysis是将降维后的三个矩阵再乘起来,重新构建了{X}矩阵如下:

观察{X}矩阵和{X^}矩阵可以发现:

{X}中human-C2值为0,因为C2中并不包含human单词,但是{X^}中human-C2为0.40,表明human和C2有一定的关系,为什么呢?

因为C2:

”Asurveyofuseropinionofcomputersystemresponsetime”中包含user单词,和human是近似词,因此human-C2的值被提高了。

同理还可以分析其他在{X^}中数值改变了的词。

以上分析方法清晰的把LSA的效果显示出来了,也就是在{X^}中呈现出了潜在语义,然后希望能创建潜在语义空间,并在该空间中检索信息。

这里以比较两个单词为例:

设奇异值分解形式为:

X=TSDT,T代表term,s代表singlevalue矩阵,D代表Document,DT表示D的转置。

X的两个行向量点乘(内积)的值代表了两个词在文档中共同出现的程度。

比如T1在D1中出现10词,T2在D1中出现5次,T3在D1中出现0词,那么只考虑在D1维度上的值,T1(dot)T2=50,T1(dot)T2=0,显然T1与T2更相似,T1与T3就不那么相似。

那么用矩阵X(dot)XT就可以求出所有词与词的相似程度。

而由奇异值分解的公式的:

X(dot)XT =T(dot)S2(dot)TT =TS(dot)(TS)T

上面公式表明了,我们想求X(dot)XT的(i,j)个元素时,可以点乘TS矩阵的第i和j列来表示。

因此我们可以把TS矩阵的行看作是term的坐标,这个坐标就是潜在语义空间的坐标。

同理我们还可以推出XT(dot)X=D(dot)S2(dot)DT,从而DS的行表示了文档的坐标。

这样,我们就获得了所有文档和单词在潜在语义空间的坐标,这时我们就可以通过向量间的夹角来判断两个对象的相似程度,方法和传统向量空间模型相同。

接下来主要讨论下检索文本的步骤。

用户输入的检索语句被称为伪文本,因为它也是有多个词汇构成,和文本相似。

所以很自然的想法就是将该伪文本转换为文档坐标,然后通过比较该伪文档与每个文档的空间夹角,检索出该伪文本的相关文档。

设Xq表示伪文本的列向量,其中该列代表文档集合的索引词,该列的值代表伪文本中该索引词出现的次数。

比如一个文档集合有索引词{T1,T2,T3},伪文本为t1,t3,t2,t1,则Xq={2,1,1}。

获得Xq后,通过公式

Dq =XqT TS-1

计算伪文档的文档坐标。

其中T和S分别代表奇异分解中得到的矩阵(S=TSDT).注意上面的公式中S-1代表S的逆矩阵。

Dq计算出来后,就可以迭代比较Dq和文档集合中所有所有文档,计算两者个cosine夹角

6LSA实践

本节主要讨论LSA的实现,编程语言使用C++,环境Linuxgcc,使用了GNUScientificLibrary[5]。

本节代码可以在

1.创建Term-Document矩阵

LSA是基于向量空间模型的,因此首先需要创建一个MxN的Term-Document矩阵,其中行表示每一个词,列表示每一个文档。

而矩阵的值等于相应词的TF*IDF值。

待检索的文档集合放在程序根目录下的corpus文件夹,每一个文档一个文件。

首先需要创建语料的单词列表,作为T-D矩阵的列向量,每一个单词对应一个id。

[code=cpp]

CreateVectorSpace.cc

FunctionintCreateKeyWordMap()

//循环读入每个文档

while((ent=readdir(currentDir))!

=NULL)

{

//omit.and..

if((strcmp(ent->d_name,"." 

 ==0)||(strcmp(ent->d_name,".." 

 ==0))

continue;

else

{

//readeachfileindirectory'corpus'

stringfilename="./corpus/";

filename+=ent->d_name;

ifstreamin(filename.c_str());

//checkiffileopensucceeded

if(!

in)

{

cout<<"error,cannotopeninputfile"<

return-1;

}

Parse();//分析单词

[/code]

在循环的过程中,识别每一个单词,并判断该单词是否为stopword。

英文的stopword可以在ftp:

//ftp.cs.cornell.edu/pub/smart/english.stop找到。

[code=cpp]

CreateVectorSpace.cc

FunctionParse()

//readonechareachtime

//thenrecognizeawordandcheckifitisinthestoplist

voidParse(ifstream*in,int*wordIndex)

{

stringpendingWord;

charch;

while

(1)

{

……

if(!

LETTER(ch))/*afterrecognizedaword*/

{

if(!

stoplist.count(pendingWord))

{

/*ifnotexistinthelist*/

if(wordList.find(pendingWord)==wordList.end())

{

wordList.insert(make_pair(pendingWord,*wordIndex));

(*wordIndex)++;

}

}

……

[/code]

接下来需要处理单词,由于英文单词有前缀和后缀,如单词的单复数(book->books),过去时(like->liked),这些词虽然形式不同但含义相同,因此要将它们处理为同一的形式,也就是单词的原型。

相关的算法为PorterStemming[6]算法。

获得单词列表后,就可以构造T-D矩阵了,过程是依次读入每个文档,遇到单词列表中存在的词,相应的矩阵单元加1。

这里用到了GSL的几个函数,用法可参考GSL手册[5]。

[code=cpp]

CreateVectorSpace.cc

FunctionCreateMatrix()

gsl_matrix*CreateMatrix()

{

……

//分配T-D矩阵空间

gsl_matrix*mtx=gsl_matrix_alloc(wordList.size(),docList.size());

map:

:

const_iteratormap_it=docList.begin();

//foreachdocument

while(map_it!

=docList.end())

{

…..

//如果当前单词在单词列表中存在

if(wordList.find(pendingWord)!

=wordList.end())

{

//矩阵相应的单元值加1

gsl_matrix_set(mtx,wordList[pendingWord],map_it->second,

gsl_matrix_get(mtx,wordList[pendingWord],map_it->second)+1);

wordCount[map_it->second]+=1;

}

……

[/code]

现在已经创建了T-D矩阵,但是矩阵单元值为单词在文档中出现的频率,因此下一步是求每个单词的TF*IDF值[7]。

TF代表单词在某一文档中出现的频率,IDF为inversedocumentfrequency,代表的含义是如果一个单词在很多文档中都出现了,那么用它来区分文档的价值就降低。

具体公式:

[code=cpp]

SVD.CC

FunctionCreateTfIdfMatrix()

gsl_matrix*CreateTfIdfMatrix()

{

……

doubletermfrequence=gsl_matrix_get(mtx,i,j)/wordCount[j];

doubleidf=log((double)docList.size()/(double)getDocumentFrequence(mtx,i));

gsl_matrix_set(mtx,i,j,termfrequence*idf);

……

[/code]

至此T-D矩阵创建完成。

2.SVD分解

SVD分解使用GSL库中的gsl_linalg_SV_decomp函数

[code=cpp]

SVD.cc

FunctionCountSVD(gsl_matrix*)

voidCountSVD(gsl_matrix*mtx)

{

//S=USV^Tsofirstlet'sallocateU,S,Vthesethreematrix

v_mtx=gsl_matrix_alloc(docList.size(),docList.size());/*VisaNbyNmatrix*/

s_vct=gsl_vector_alloc(docList.size());/*Sisstoredinan-dvector*/

gsl_vector*workspace=gsl_vector_alloc(docList.size());/*workspaceforgslfunction*/

gsl_linalg_SV_decomp(mtx,v_mtx,s_vct,workspace);

}

[/code]

3.降维

降维在程序你实现十分简单,也就是给矩阵(由于是对角矩阵,因此程序里表示为向量)赋值零。

[code=cpp]

SVD.cc

FunctionReduceDim(int)

voidReduceDim(intkeep)

{

for(inti=keep;i

gsl_vector_set(s_vct,i,0);

}

[/code]

4.查询

SVD分解完成后,我们就已经获得了潜在语义空间,接下来就可以接受用户的输入,将伪文本转换到文档坐标,然后通过比较向量的夹角,找出相关文档。

[code=cpp]

voidQuery(stringquery)

{

//transformqueryintoLSAspace

istringstreamstream(query);

stringword;

//为Xq创建gsl向量,Xq表示伪文本的列向量

gsl_vector*q_vct=gsl_vector_alloc(wordList.size());

//为Dq创建gsl向量,Dq表示伪文本的文档向量

gsl_vector*d_vct=gsl_vector_alloc(LSD);

//首先计算Xq

while(stream>>word)

{

if(wordList.count(word)!

=0)/*wordisinthelist*/

gsl_vector_set(q_vct,wordList[word],

gsl_vector_get(q_vct,wordList[word])+1);

}

//Dq=Xq'TS^-1

//再求Xq'乘T

for(inti=0;i

{

doublesum=0;

for(intj=0;j

sum+=gsl_vector_get(q_vct,j)*gsl_matrix_get(mtx,j,i);

gsl_vector_set(d_vct,i,sum);

}

//最后求(Xq'T)S^-1

for(intk=0;k

gsl_vector_set(d_vct,k,

gsl_vector_get(d_vct,k)*(1/gsl_vector_get(s_vct,k)));

//用文档集合中每个文档和Dq比较

for(intl=0;l

{

……

//求两向量夹角,返回cosine值

relation=CompareVector(d_vct,temp_d_vct,LSD);

}

}

[/code]

5.测试

我们先用以前讨论过的文档集

将C1~M4分别保存到9个文件里,放到corpus文件夹

运行程序,输入格式为lsa.out[query]

./lsa.outhumancomputerinteraction

可以看出与主题最相关的文档是C3,其次是C1。

C1~C5文件是同主题文档,主题是人机互交,而M1~M4的共同主题是计算机图形。

而查询”humancomputerinteraction”显然描述的是人机互交。

因此也可以从结果看到C1~C5的相关度全部都高于M1~M4文档。

最后,观察C3,C5文档,它们并不包含任何查询中的词,而计算出的相似度却不为0,并且C3的相似度达0.999658,这也正是LSA潜在语义的效果。

下面是文档两两比较后的结果表格(已导入到Excel)

上图1~9和A~B都分别代表文档{C1,C2,C3,C4,C5,M1,M2,M3,M4}

上图非常清晰的显示出了文档的关系:

先来看[1~5][A~E]也就是第1~5行,

A~E列,由于文档C1~C5是一个主题的文档,所以可以看出[1~5][A~E]都大于0.9,而[1~5][F~I]都不超过0.5,也表明C1~C5文档与M1~M4文档主题是不相干的。

同理可以分析[6~9][F~I]。

上面的讨论表明,潜在语义分析在主题分类上效果明显。

如果设定一个分类的阈值,比如0.8,那么上面9个文档就被自动分为了{C1,C2,C3,C4,C5}和{M1,M2,M3,M4}

在另一个测试中,我从NewYorkTimes网站收集的6个主题,每个主题5篇文章

搜索”whatagreatday”结果如下:

伪文本坐标(0.00402821,-0.0183549,0.00361756),每个文档的相关度如果设定检索阈值为0.9,那么文档movie2,sport4,art2被返回。

7总结

LSA通过对潜在语义空间的建模,提高的信息检索的精确度。

而后又有人提出了PLSA(Probabilisticlatentsemanticanalysis)和LDA(LatentDirichletallocation),将LSA的思想带入到概率统计模型中。

LSA对一词多义问题依然没有解决,仅仅解决了一义多词。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1