对不起,如果我的问题听起来很愚蠢:) 你可以推荐我在java中用LSI实现的任何伪代码或好算法吗? 我不是数学专家。我试着读一些关于维基百科和其他网站的文章 LSI(潜在的语义索引)他们充满了数学。 我知道LSI充满了数学。但是,如果我看到一些源代码或算法。我更了解事情 容易。这就是我在这里问的原因,因为有很多GURU在这里! 提前致谢
答案 0 :(得分:13)
LSA的概念基于一个假设:在同一文档中出现的两个词越多,它们就越相似。实际上,我们可以预期单词“编程”和“算法”将更频繁地出现在相同的文档中,比如“编程”和“养狗”。
文档相同:两个文档中更常见/相似的单词,它们本身就越相似。因此,您可以通过单词的频率表达文档的相似性,反之亦然。
了解这一点,我们可以构建一个共生矩阵,其中列名表示文档,行名称 - 单词,每个cells[i][j]
表示文档中单词words[i]
的频率documents[j]
。频率可以通过多种方式计算,IIRC,原始LSA使用tf-idf索引。
有了这样的矩阵,你可以通过比较相应的列来找到两个文档的相似性。如何比较它们?同样,有几种方法。最受欢迎的是余弦距离。你必须记住从学校数学,矩阵可以被视为一堆向量,所以每列只是一个多维空间中的向量。这就是为什么这个模型被称为“向量空间模型”。有关VSM和余弦距离的更多信息here。
但我们对这种矩阵有一个问题:它很大。非常非常大。使用它的计算成本太高,所以我们必须以某种方式减少它。 LSA使用SVD技术来保留最“重要”的向量。在还原矩阵准备好使用之后。
因此,LSA的算法看起来像这样:
如果您要自己编写LSA库,那么开始的好点是Lucene搜索引擎,这将使步骤1和2更容易,以及一些具有SVD功能的高维矩阵的实现例如Parallel Colt或UJMP。
还要注意从LSA长大的其他技术,如Random Indexing。 RI使用相同的想法并显示大致相同的结果,但不使用完整矩阵阶段并且是完全递增的,这使得它在计算上更有效。
答案 1 :(得分:1)
这可能有点晚了,但我总是喜欢Sujit Pal的博客http://sujitpal.blogspot.com/2008/09/ir-math-with-java-tf-idf-and-lsi.html,如果你有兴趣,我会在我的网站上写一点。
这个过程并不像往常那样复杂。实际上你需要的只是一个可以对矩阵进行单值分解的库。
如果你有兴趣,我可以用几个短暂的消息来解释:
1)您创建一个矩阵/数据集/ etc,其中包含各种文档的单词计数 - 不同的文档将是您的列,行将是不同的单词。
2)一旦你创建了矩阵,就可以使用像Jama(用于Java)或SmartMathLibrary(用于C#)这样的库并运行单值分解。所有这一切都是将原始矩阵分解为三个不同的部分/矩阵,它们基本上代表了你的文档,你的文字和乘数(sigma)的类型,这些被称为向量。
3)一旦你拥有了单词,文档,sigma向量,你只需复制矢量/矩阵的较小部分然后将它们相乘,就可以平均缩小它们(k)。通过缩小它们可以使数据正常化,这就是LSI。
这里有一些相当明确的资源:
http://lsa.colorado.edu/papers/JASIS.lsi.90.pdf http://www.soe.ucsc.edu/classes/cmps290c/Spring07/proj/Flynn_talk.pdf
希望这会对你有所帮助。
埃里克
答案 2 :(得分:1)
我知道这太迟了:)但最近我发现this link对理解这些原则非常有帮助。只是注意到它,所以搜索它的人可能会发现它很有用。
目前,我正在寻找对概率潜在语义分析/索引的类似介绍。少数数学和更多解释其背后原理的例子。如果有人知道这样的介绍,请告诉我。