【发布时间】:2016-01-05 19:15:55
【问题描述】:
我有一个大文本文件,其中包含由 Gigaword 构建的 Word2Vec 向量(大小超过 3GB),每一行都是一个单词及其对应的向量。它是按频率排序的,所以列表中频率高的词比低频率的词高。
对于给定的单词列表,我需要构建一个由单词及其 word2vec 向量组成的 Scala Map。以下是我的做法:
-
对于每个单词,将文件作为迭代器打开:
val it = scala.io.Source.fromFile(filePath).getLines() -
使用
find查找匹配的单词,如果没有找到则使用默认值:val match = it.find(_.split(" ").head == word).getOrElse("zzz" 0d)
这是我的完整方法:
def buildArray2b: (Double, Array[(String, breeze.linalg.DenseVector[Double])]) = {
val startAll = System.currentTimeMillis().toDouble
val stream = (for (word <- this.vocabulary.map(each => each.toLowerCase)) yield {
println("starting " + word)
val start = System.currentTimeMillis().toDouble
println("building iterator")
val iterator = Source.fromInputStream(this.inputStream).getLines()
println("finding")
val line = iterator.find(it => it.split(" ").head == word).getOrElse("zzz 0.0")
println("found")
val splitLine = line.split(" ") //split string into elements
val tail = splitLine.tail.map(_.toDouble) //build w2v vector
val vectorizedLine = splitLine.head -> breeze.linalg.DenseVector(tail) //build map entry
val stop = System.currentTimeMillis().toDouble
println(word + ":" + (stop - start) / 1000d)
vectorizedLine
}).toArray
val stopAll = System.currentTimeMillis().toDouble
val elapsed = (stopAll - startAll) / 1000d
(elapsed, stream)
}
这里是找到以下单词“a”、“quixotic”和“the”的次数的输出:
scala> w2v.buildArray2
a:0.001
quixotic:0.795
the:25.6
我不知道为什么很快就可以找到“不切实际的”(与“a”和“the”相比,它在列表中应该“靠后”),却永远找到了“the”这个词。
我在数据结构方面的经验很少,因此我很感激 (1) 对此问题的任何见解以及 (2) 关于如何使这个过程更高效的任何建议。
为此,我已经尝试了以下方法:
- 将整个文件加载到地图中。这需要很长时间才能先转换为序列,然后再转换为地图。
- 将 .txt 文件转换为 .json,然后使用包(在本例中为
json4s)将该 .json 文件直接打开到地图中。我遇到了内存错误(我已经为这个项目分配了 14g 内存)。
提前感谢任何 cmets/见解!
【问题讨论】: