如何使用RowMatrix.columnSimilarities(相似度搜索)

How to use RowMatrix.columnSimilarities (similarity search)

TL;DR; 我正在尝试训练现有数据集(Seq[Words] 具有相应类别),并使用该训练数据集来过滤另一个数据集使用类别相似性。

我正在尝试训练数据语料库,然后将其用于文本分析*。我试过使用 NaiveBayes,但这似乎只适用于您拥有的数据,因此它的预测算法将始终 return 某些东西,即使它不匹配任何东西。

所以,我现在尝试使用 TFIDF 并将该输出传递到 RowMatrix 并计算相似性。但是,我不确定如何 运行 我的查询(现在一个词)。这是我尝试过的:

val rddOfTfidfFromCorpus : RDD[Vector]
val query = "word"
val tf = new HashingTF().transform(List(query))
val tfIDF = new IDF().fit(sc.makeRDD(List(tf))).transform(tf)  
val mergedVectors = rddOfTfidfFromCorpus.union(sc.makeRDD(List(tfIDF)))
val similarities = new RowMatrix(mergedVectors).columnSimilarities(1.0)

这是我卡住的地方(如果我在这里之前所做的一切都正确的话)。我尝试将 similarities ij 过滤到查询的 TFIDF 部分,最后得到一个空集合。

要点是我想训练一个数据语料库并找到它属于哪个类别。上面的代码至少试图将它归为一个类别并检查我是否可以从中得到预测至少....

*请注意,这是一个玩具示例,所以我只需要足够好用的东西 *我使用的是 Spark 1.4.0

在这里使用 columnSimilarities 没有意义。由于矩阵中的每一列都代表一组术语,因此您将获得标记而非文档之间的相似性矩阵。您可以转置矩阵然后使用 columnSimilarities 但据我了解您想要的是查询和语料库之间的相似性。您可以使用矩阵乘法表示如下:

对于初学者,您需要 IDFModel 您已经在语料库上训练过。让我们假设它被称为 idf:

import org.apache.spark.mllib.feature.IDFModel
val idf: IDFModel = ??? // Trained using corpus data

还有一个小帮手:

def toBlockMatrix(rdd: RDD[Vector]) = new IndexedRowMatrix(
  rdd.zipWithIndex.map{case (v, i) => IndexedRow(i, v)}
).toCoordinateMatrix.toBlockMatrix

首先让我们将查询转换为 RDD 并计算 TF:

val query: Seq[String] = ??? 
val queryTf = new HashingTF().transform(query)

接下来我们可以应用IDF模型并将结果转换为矩阵:

val queryTfidf = idf.transform(queryTf)
val queryMatrix = toBlockMatrix(queryTfidf)

我们还需要一个语料库矩阵:

val corpusMatrix = toBlockMatrix(rddOfTfidfFromCorpus)

如果将两者相乘,我们得到一个矩阵,其行数等于查询中的文档数,列数等于语料库中的文档数。

val dotProducts = queryMatrix.multiply(corpusMatrix.transpose)

要获得适当的余弦相似度,您必须除以幅度的乘积,但如果您可以处理的话。

这里有两个问题。首先它是相当昂贵的。而且我不确定它是否真的有用。为了降低成本,您可以先应用一些降维算法,但暂时保留它。

从下面的说法来看

NaiveBayes (...) seems to only work with the data you have, so it's predict algorithm will always return something, even if it doesn't match anything.

我猜你想要某种无监督学习方法。您可以尝试的最简单的方法是 K 均值:

import org.apache.spark.mllib.clustering.{KMeans, KMeansModel}

val numClusters: Int = ???
val numIterations = 20

val model = KMeans.train(rddOfTfidfFromCorpus, numClusters, numIterations)
val predictions = model.predict(queryTfidf)