1,LSA算法原理
LSA(latent semantic analysis)潜在语义分析,也被称为LSI(latent semantic index),是Scott Deerwester, Susan T. Dumais等人在1990年提出来的一种新的索引和检索方法。该方法和传统向量空间模型(vector space model)一样使用向量来表示词(terms)和文档(documents),并通过向量间的关系(如夹角)来判断词及文档间的关系;而不同的是,LSA将词和文档映射到潜在语义空间,从而去除了原始向量空间中的一些“噪音”,提高了信息检索的精确度。LSA的基本思想就是把高维的文档降到低维空间,那个空间被称为潜在语义空间。这个映射必须是严格线性的而且是基于共现表(就是那个矩阵啦)的奇异值分解。
LSA(隐性语义分析)的目的是要从文本中发现隐含的语义维度-即“Topic”或者“Concept”。LSA的目标就是要寻找到能够很好解决实体间词法和语义关系的数据映射。我们知道,在文档的空间向量模型(VSM)中,文档被表示成由特征词出现概率组成的多维向量,这种方法的好处是可以将query和文档转化成同一空间下的向量计算相似度,可以对不同词项赋予不同的权重,在文本检索、分类、聚类问题中都得到了广泛应用,在基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现和基于Kmeans算法、MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现系列文章中的分类聚类算法大多都是采用向量空间模型。然而,向量空间模型没有能力处理一词多义和一义多词问题,例如同义词也分别被表示成独立的一维,计算向量的余弦相似度时会低估用户期望的相似度;而某个词项有多个词义时,始终对应同一维度,因此计算的结果会高估用户期望的相似度。
原理:LSA潜在语义分析的目的,就是要找出词(terms)在文档和查询中真正的含义,也就是潜在语义,从而解决上节所描述的问题。具体说来就是对一个大型的文档集合使用一个合理的维度建模,并将词和文档都表示到该空间,比如有2000个文档,包含7000个索引词,LSA使用一个维度为100的向量空间将文档和词表示到该空间,进而在该空间进行信息检索。而将文档表示到此空间的过程就是SVD奇异值分解和降维的过程。降维是LSA分析中最重要的一步,通过降维,去除了文档中的“噪音”,也就是无关信息(比如词的误用或不相关的词偶尔出现在一起),语义结构逐渐呈现。相比传统向量空间,潜在语义空间的维度更小,语义关系更明确。
2,gensim中的LSA算法
import jieba
from gensim import corpora, similarities, models
# 加载自定义字典
jieba.load_userdict(config.userdict)
# 加载停用词
stopwords = utils.init_stop_words(config.stopwords)
sentences = ['逍遥派掌门人无崖子为寻找一个色艺双全、聪明伶俐的徒弟,设下“珍珑”棋局,为少林寺虚字辈弟子虚竹误撞解开。',
'慕容复为应召拒绝王语嫣的爱情;众人救起伤心自杀的王语嫣,后段誉终于获得她的芳心。',
'鸠摩智贪练少林武功,走火入魔,幸被段誉吸去全身功力,保住性命,大彻大悟,成为一代高僧。',
'张无忌历尽艰辛,备受误解,化解恩仇,最终也查明了丐帮史火龙之死乃是成昆、陈友谅师徒所为',
'武氏与柯镇恶带着垂死的陆氏夫妇和几个小孩相聚,不料李莫愁尾随追来,打伤武三通',
'人工智能亦称智械、机器智能,指由人制造出来的机器所表现出来的智能。',
'人工智能的研究是高度技术性和专业的,各分支领域都是深入且各不相通的,因而涉及范围极广。',
'自然语言认知和理解是让计算机把输入的语言变成有意思的符号和关系,然后根据目的再处理。']
corpora_sen = []
for line in sentences:
words = jieba.cut(line.strip()) # jieba分词
seg = [word for word in list(words) if word not in stopwords]
corpora_sen.append(seg)
# 生成字典
dictionary = corpora.Dictionary(corpora_sen)
# 把句子转化为向量
corpus = []
for word in corpora_sen:
temp = dictionary.doc2bow(word)
corpus.append(temp)
tfidf_model = models.TfidfModel(corpus)
corpus_tfidf = tfidf_model[corpus]
# 使用lsi模型计算相似度
lsi = models.LsiModel(corpus_tfidf)
lsi.print_topics(num_words=10)
corpus_lsi = lsi[corpus_tfidf] # 把tf-idf空间向量转化为lsi空间
similarity_lsi = similarities.Similarity('Similarity-LSI-index', corpus_lsi, num_features=600, num_best=3)
test_sen = '自然语言处理与人工智能'
seg_sen = list(jieba.cut(test_sen))
test_corpus = dictionary.doc2bow(seg_sen)
lsi_vector = lsi[test_corpus]
print(similarity_lsi[lsi_vector])