Latent Semantic Idexing,译为隐性语义索引,也可译为潜在语义索引,简称 LSI ;有的文章也叫Latent Semantic Analysis,译为隐性语义分析,也可译为潜在语义分析,简称 LSA )。两者是一个东西,后面我们统称 LSI 。隐性语义索引,是在信息检索领域提出来的一个概念,是近年来逐渐兴起的不同于关键词检索的搜索引擎解决方案,其通过海量文献找出词汇之间的关系,当两个词或一组词大量出现在同一个文档中时,这些词之间就可以被认为是语义相关。比如:
(1)”手机”和”电话”这两个词在人们写文章时经常混用,这两个词在大量的网页中同时出现,搜索引擎就会认为这两个词是极为语义相关的。
(2)”Latent Semantic Idexing”和”隐性语义索引”(虽然一个是英语,一个是中文)这两个词大量出现在相同的网页中,虽然搜索引擎还不能知道”Latent Semantic Idexing或”隐性语义索引”指的是什么,但是却可以从语义上把”Latent Semantic Idexing”、”隐性语义索引”、”LSI”、”潜在语义索引”等词紧紧的连在一起。可见潜在语义索引并不依赖于语言。
(3)如梨子和李子这两个词,也是大量出现在相同文档中,不过紧密度低于同义词。所以搜索引擎不会认为它们是语义相关的。
(4)对“水”一词而言,与其语义相关的可能是“热水”、“凉水”之类,但潜在相关的则可以是“蒸汽”、“ 冰”等,这里有很大区别。
隐性语义索引使得检索结果的实际效果更接近于人的自然语言,在一定程度上提高检索结果的相关性,目前已被逐渐的应用到图书馆、数据库和搜索引擎的算法当中。Google是典型的代表。
本文分四部分:
(1)基础知识
(2)讲解奇异值分解(SVD);
(3)讲解利用SVD进行信息检索的隐性语义检索(LSI);
(4)实例分析。
基础知识
1.矩阵的秩:矩阵的秩是矩阵中线性无关的行或列的个数
2.对角矩阵:对角矩阵是除对角线外所有元素都为零的方阵
3.单位矩阵:如果对角矩阵中所有对角线上的元素都为1,该矩阵称为单位矩阵
4.奇异值:假设
C
是
5.对称矩阵:若矩阵
A
满足条件
6.正定矩阵:设
C
是
判定定理:
判定定理1:对称阵
A
为正定的充分必要条件是:
判定定理2:对称阵
A
为正定的充分必要条件是:
判定定理3:任意阵
A
为正定的充分必要条件是:
奇异值分解(SVD)
奇异值分解(Singular Value Decomposition)是线性代数中一种重要的矩阵分解,是矩阵分析中正规矩阵酉对角化的推广。奇异值分解在有两个方面的应用:一是 SVD 在降维中的应用;二是 SVD 在协同过滤推荐算法中的应用。具体应用内容本文不阐述。下面来看一下奇异值分解的定义。
假设
C
是一个
C
等价于
U
是
直观的解释
在矩阵
C
的奇异值分解中
·
·
V
的列(columns)是
·
Σ
对角线上的元素是奇异值,可视为是在输入与输出间进行的标量的”膨胀控制”。这些是
C∗C
及
CC∗
的奇异值,并与
U
和
奇异值的物理意义及几何意义
矩阵的奇异值是一个数学意义上的概念,一般是由奇异值分解(简称 SVD 分解)得到。
如果要问奇异值表示什么物理意义,那么就必须考虑在不同的实际工程应用中奇异值所对应的含义。例如在图像处理领域,奇异值不仅可以应用在数据压缩上,还可以对图像去噪。如果一副图像包含噪声,我们有理由相信那些较小的奇异值就是由于噪声引起的。当我们强行令这些较小的奇异值为0时,就可以去除图片中的噪声。奇异值往往对应着矩阵中隐含的重要信息,且重要性和奇异值大小正相关。
奇异值的几何含义为:这组变换后的新的向量序列的长度。
奇异值分解的物理意义及几何意义
奇异值分解是一个有着很明显的物理意义的一种方法,它可以将一个比较复杂的矩阵用更小更简单的几个子矩阵的相乘来表示,这些小矩阵描述的是矩阵的重要的特性。就像是描述一个人一样,给别人描述说这个人长得浓眉大眼,方脸,络腮胡,而且带个黑框的眼镜,这样寥寥的几个特征,就让别人脑海里面就有一个较为清楚的认识,实际上,人脸上的特征是有着无数种的,之所以能这么描述,是因为人天生就有着非常好的抽取重要特征的能力,让机器学会抽取重要的特征, SVD 是一个重要的方法。
奇异值分解的几何含义为:对于任何的一个矩阵,我们要找到一组两两正交单位向量序列,使得矩阵作用在此向量序列上后得到新的向量序列保持两两正交。
下面说一下在python中实现SVD
Numpy有一个linalg的线性代数工具箱。接下来我们了解一下领用该工具箱如何实现下矩阵的 SVD 处理。例如矩阵 A ,对其进行奇异值分解,结果如下所示。
import numpy as np
from numpy import *
A=np.mat([[1,3,5,9,17],[8,12,3,4,7],[3,1,5,7,13],[11,10,5,9,3],[14,16,2,8,7],[45,8,12,4,6]])
print A
[[ 1 3 5 9 17]
[ 8 12 3 4 7]
[ 3 1 5 7 13]
[11 10 5 9 3]
[14 16 2 8 7]
[45 8 12 4 6]]
U1,Sigma1,VT1 =linalg.svd(A)
print U1
print Sigma1
print VT1
[[-0.16962844 -0.6484007 -0.39706552 0.05248991 -0.09048465 -0.61822248]
[-0.25120752 -0.25273347 0.35846092 0.48851171 0.71005302 0.04132019]
[-0.16078086 -0.44559884 -0.41720788 -0.08597781 0.00943516 0.77074481]
[-0.29331235 -0.15910768 0.3281765 -0.84221499 0.25758716 -0.07263307]
[-0.37474761 -0.25291321 0.56980035 0.19204829 -0.64898559 0.11341016]
[-0.80981639 0.47735066 -0.32773476 0.07071283 0.0038446 -0.06251893]]
[ 56.73235626 25.68065671 14.90317788 5.0664686 2.04201107]
[[-0.83860911 -0.33652353 -0.2527574 -0.2209323 -0.26606256]
[ 0.47439383 -0.28202104 -0.07014443 -0.44825973 -0.69968393]
[-0.13030237 0.83672216 -0.27835124 0.07655086 -0.44674139]
[ 0.06099689 0.22697424 -0.33165679 -0.77688942 0.48084163]
[-0.22580062 0.23578544 0.86239076 -0.37527979 -0.09416247]]
注意:矩阵Sisma以行向量返回,而非矩阵。(由于矩阵除了对角线上元素其它全为0,故为节省空间仅返回对角元素。)
隐性语义索引(LSI)
隐性语义索引是一种简单实用的主题模型。隐性语义索引是一种用奇异值分解(
LSI 使用 SVD 来对单词-文档矩阵进行分解。 SVD 可以看作是从单词-文档矩阵中发现不相关的索引变量(因子),将原来的数据映射到语义空间内。 LSI 本质上是把每个特征映射到了一个更低维的子空间(sub space), 不过必须提醒的是,无论是上述哪一种降维方法,都会造成信息的偏差,进而影响后续分类/聚类的准确率。 降维是希望以可接受的效果损失下,大大提高运行效率和节省内存空间。然而能不降维的时候还是不要降维(比如你只有几千篇文档要处理,那样真的没有必要降维)。
首先简要回顾下
SVD
:对于一个
m×n
的矩阵
C
,可以分解为下面三个矩阵:
为了降低矩阵的维度到
k
,
如果把上式用到我们的主题模型,则
SVD
可以这样解释:我们输入的有
m
个文本,每个文本有
也可以反过来解释:我们输入的有
m
个词,对应
这样我们通过一次 SVD ,就可以得到文档和主题的相关度,词和词义的相关度以及词义和主题的相关度。
下面来说一下如何利用 SVD 进行信息检索的 LSI 方法:
设
C
是一个
1.利用
2.利用 SVD 分解降维后的结果来构造一个新的、改进的词汇-文档矩阵 C′ ;
3.通过 C′ 得到一个更好的计算相似度的方法。
4.向之前一样按相似度高低输出文档结果。
实例分析:
下面我们举个例子来说明: C=UΣV∗
C | d1 | d2 | d3 | d4 | d5 | d6 |
---|---|---|---|---|---|---|
ship | 1 | 0 | 1 | 0 | 0 | 0 |
boat | 0 | 1 | 0 | 0 | 0 | 0 |
ocean | 1 | 1 | 0 | 0 | 0 | 0 |
wood | 0 | 0 | 0 | 1 | 1 | 0 |
tree | 0 | 0 | 0 | 1 | 0 | 1 |
import numpy as np
from numpy import *
C=np.mat([[1,0,1,0,0,0],[0,1,0,0,0,0],[1,1,0,0,0,0],[0,0,0,1,1,0],[0,0,0,1,0,1]])
print C
U,Sigma,VT =linalg.svd(C)
print U
print Sigma
print VT
[[1 0 1 0 0 0]
[0 1 0 0 0 0]
[1 1 0 0 0 0]
[0 0 0 1 1 0]
[0 0 0 1 0 1]]
[[ 0.59100905 0. -0.73697623 0. 0.32798528]
[ 0.32798528 0. 0.59100905 0. 0.73697623]
[ 0.73697623 0. 0.32798528 0. -0.59100905]
[ 0. 0.70710678 0. -0.70710678 0. ]
[ 0. 0.70710678 0. 0.70710678 0. ]]
[ 1.80193774 1.73205081 1.2469796 1. 0.44504187]
[[ 7.36976229e-01 5.91009049e-01 3.27985278e-01 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[ -0.00000000e+00 -0.00000000e+00 0.00000000e+00 8.16496581e-01
4.08248290e-01 4.08248290e-01]
[ -3.27985278e-01 7.36976229e-01 -5.91009049e-01 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 3.33066907e-16
-7.07106781e-01 7.07106781e-01]
[ -5.91009049e-01 3.27985278e-01 7.36976229e-01 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 -5.77350269e-01
5.77350269e-01 5.77350269e-01]]
U | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
ship | 0.591 | 0 | -0.737 | 0 | 0.328 |
boat | 0.328 | 0 | 0.591 | 0 | 0.737 |
ocean | 0.737 | 0 | 0.328 | 0 | -0.591 |
wood | 0 | 0.707 | 0 | -0.707 | 0 |
tree | 0 | 0.707 | 0 | 0.707 | 0 |
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
1 | 1.801 | 0 | 0 | 0 | 0 |
2 | 0 | 1.732 | 0 | 0 | 0 |
3 | 0 | 0 | 1.247 | 0 | 0 |
4 | 0 | 0 | 0 | 1.00 | 0 |
5 | 0 | 0 | 0 | 0 | 0.445 |
Σ 中对角元素是矩阵 C 的奇异值。奇异值的大小度量的事相应的语义维度的重要性。
d1 | d2 | d3 | d4 | d5 | d6 | |
---|---|---|---|---|---|---|
1 | 0.737 | 0.591 | 0.328 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0.816 | 0.408 | 0.408 |
3 | 0.328 | 0.737 | 0.591 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0.707 | 0.707 |
5 | 0.591 | 0.328 | 0.737 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0.577 | 0.577 | 0.577 |
VT 中每一列对应一篇文档,每一行对应一个语义维度, Vjm 代表的是文档j与语义维度的关系强弱程度。矩阵 VT 是一个正定矩阵。
在这里我们通过忽略较小的奇异值,即忽略较小的奇异值对应的语义维度来达到降维的目的。在本例题中这里假设忽略后2个小于等于1的语义维度,相当于 U、VT 矩阵上的相应维度被忽略。此时的矩阵分别记为记为 Σ3、U3、VT3 。
Σ3 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
1 | 1.801 | 0 | 0 | 0 | 0 |
2 | 0 | 1.732 | 0 | 0 | 0 |
3 | 0 | 0 | 1.247 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 |
U3 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
ship | 0.591 | 0 | -0.737 | 0 | 0 |
boat | 0.328 | 0 | 0.591 | 0 | 0 |
ocean | 0.737 | 0 | 0.328 | 0 | 0 |
wood | 0 | 0.707 | 0 | 0 | 0 |
tree | 0 | 0.707 | 0 | 0 | 0 |
VT3 | d1 | d2 | d3 | d4 | d5 | d6 |
---|---|---|---|---|---|---|
1 | 0.737 | 0.591 | 0.328 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0.816 | 0.408 | 0.408 |
3 | 0.328 | 0.737 | 0.591 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
利用 SVD 分解降维后的结果来构造一个新的、改进的词汇-文档矩阵 C′ 。
通过python程序求得 C′ ,其代码及结果如下所示:
U3=U[:,:3];
lamda=Sigma[:3];Sigma3=diag(lamda)
VT3=VT[:3,:]
print U3
print Sigma3
print VT3
[[ 0.59100905 0. -0.73697623]
[ 0.32798528 0. 0.59100905]
[ 0.73697623 0. 0.32798528]
[ 0. 0.70710678 0. ]
[ 0. 0.70710678 0. ]]
[[ 1.80193774 0. 0. ]
[ 0. 1.73205081 0. ]
[ 0. 0. 1.2469796 ]]
[[ 0.73697623 0.59100905 0.32798528 0. 0. 0. ]
[-0. -0. 0. 0.81649658 0.40824829 0.40824829]
[-0.32798528 0.73697623 -0.59100905 0. 0. 0. ]]
CC=U3*Sigma3*VT3
print CC
[[ 1.08626792 -0.04787509 0.89242566 0. 0. 0. ]
[ 0.19384227 0.89242566 -0.24171735 0. 0. 0. ]
[ 0.84455057 1.08626792 0.19384227 0. 0. 0. ]
[ 0. 0. 0. 1. 0.5 0.5 ]
[ 0. 0. 0. 1. 0.5 0.5 ]]
通过python程序求得 C' 结果如下:
C′ | d1 | d2 | d3 | d4 | d5 | d6 |
---|---|---|---|---|---|---|
ship | 1.086 | -0.048 | 0.892 | 0 | 0 | 0 |
boat | 0.194 | 0.892 | -0.242 | 0 | 0 | 0 |
ocean | 0.845 | 1.086 | 0.194 | 0 | 0 | 0 |
wood | 0 | 0 | 0 | 1 | 0.5 | 0 |
tree | 0 | 0 | 0 | 1 | 0.5 | 01 |
矩阵 C′ 可以看做是矩阵 C 的一个三维表示。
在上面我们通过
则对于上面的三文档两主题的例子。我们可以计算第一个文本和第二个文本在C与C’的余弦相似度,程序如下 :
import math
costhta1=1/(math.sqrt(pow(1,2)+pow(0,2))*math.sqrt(pow(1,2)+pow(1,2))*math.sqrt(pow(0,2)+pow(16,2)))
costhta2=(1.086*(-0.048)+0.194*0.892+0.845*1.086)/(math.sqrt(pow(1.086,2)+pow(-0.048,2))*math.sqrt(pow(0.194,2)+pow(0.892,2))*math.sqrt(pow(0.845,2)+pow(1.086,2)))
print costhta1,costhta2
0.0441941738242 0.760617359816
由上程序结果可知:
cosθc=112+02√×12+12√×02+12√≈0.044
cosθc′=1.086∗(−0.048)+0.194∗0.892+0.845∗1.0861.0862+(−0.048)2√×0.1942+0.8922√×0.8452+1.0862√≈0.761
通过余弦相似度求得文档一与文档二在原词汇-文档矩阵中和新词汇-文档矩阵的相似度分别为0.044、0.761,相似度有所提高。可以知道原文档的相关性不高,通过LSI将它们映射到低维空间后,两者的相似度会提高。因此可知LSI能够解决一词多义与语义关联问题。
总结
LSI是最早出现的主题模型了,它的算法原理很简单,一次奇异值分解就可以得到主题模型,同时解决词义的问题,非常漂亮。但是LSI有很多不足,导致它在当前实际的主题模型中已基本不再使用。
主要的问题有:
1.SVD计算非常的耗时,尤其是我们的文本处理,词和文本数都是非常大的,对于这样的高维度矩阵做奇异值分解是非常难的。
2.主题值的选取对结果的影响非常大,很难选择合适的k值。
3.LSI得到的不是一个概率模型,缺乏统计基础,结果难以直观的解释。
对于问题1,主题模型非负矩阵分解(NMF)可以解决矩阵分解的速度问题。
对于问题2,大部分主题模型的主题的个数选取一般都是凭经验的,较新的层次狄利克雷过程(HDP)可以自动选择主题个数。
对于问题3,人们整出了PLSI(也叫PLSA)和隐含狄利克雷分布(LDA)这类基于概率分布的主题模型来替代基于矩阵分解的主题模型。
对于一些规模较小的问题,如果想快速粗粒度的找出一些主题分布的关系,则LSI是比较好的一个选择,其他时候,如果你需要使用主题模型,推荐使用LDA和HDP。
参考文献
[1] We Recommend a Singular Value Decomposition(Feature Column from the AMS)。
[2] 徐树方,《矩阵计算的理论与方法》,北京大学出版社。
[3]http://blog.youkuaiyun.com/zhongkejingwang/article/details/43053513