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