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

时间:2015-10-02 16:35:34

标签: scala machine-learning apache-spark apache-spark-mllib

TL; DR; 我正在尝试训练现有数据集(Seq[Words]及相应类别),并使用该训练数据集使用类别相似度过滤其他数据集。< / p>

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

所以,我现在正在尝试使用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

1 个答案:

答案 0 :(得分:1)

使用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(...)似乎只能使用你拥有的数据,所以它的预测算法总会返回一些东西,即使它与任何东西都不匹配。

我想你想要某种无监督的学习方法。你可以尝试的最简单的事情是K-means:

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)