【问题标题】:How to use RowMatrix.columnSimilarities (similarity search)如何使用 RowMatrix.columnSimilarities(相似度搜索)
【发布时间】:2015-12-30 22:30:39
【问题描述】:

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

我正在尝试训练一个数据语料库,然后将其用于文本分析*。我试过使用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

【问题讨论】:

  • @zero323 已更正,谢谢。并感谢您对代码的编辑....在我完成输入后忘记转移
  • 不客气。那么,可以解释一下您到底想在这里做什么吗?我无法理解您的代码:(某种聚类?相似性搜索?
  • 是的。相似性搜索
  • 我添加了一个 TLDR...抱歉,ml 是我在 Spark 中最薄弱的方面...。

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


【解决方案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)

【讨论】:

  • 被接受为答案......尽管由于每个向量的大小,我一直遇到内存问题。我可能会尝试使用 Word2Vec 而不是 TFIDF...我的理解是最终会导致更小的内存印记
  • 在 Kmeans 是我的好去处
  • 我认为这与 stackoverflow.com/questions/26449446/… 有关如何在不耗尽内存的情况下实现我的单词的特征?
  • 我刚刚收集了我的 tfidf,大约 75000 个向量在缓存中占用了 5MB(反序列化)......这是一组 54 个 wiki 页面......甚至不是整个集合跨度>
  • 在创建向量之前是否执行任何过滤步骤?停用词去除?删除稀有词?词干/词形还原?如果不是,它可能是一个很好的起点。根据清理后的多个术语,您可以调整numFeatures 参数。您可以尝试的另一件事是在应用 K-means 之前进行 PCA。
猜你喜欢
  • 2013-04-09
  • 2021-12-20
  • 2018-12-18
  • 2013-04-26
  • 2010-11-02
  • 2011-06-25
  • 2010-11-21
  • 2021-02-07
  • 1970-01-01
相关资源
最近更新 更多