我有一個很大的文本文件,它由從Gigaword構建的Word2Vec向量組成(它的大小超過3GB),每行都是一個單詞及其相應的向量。它按頻率排序,以便列表中的高頻詞比低頻詞更高。重複搜索Scala迭代器的最有效方法
對於給定的單詞列表,我需要構建一個包含單詞和它的word2vec向量的Scala地圖。下面是我的做法:
每個字,打開該文件作爲一個迭代器:
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)
}
這裏是與時俱進的輸出,找到下面的話 「一」, 「阿Q精神」 和 「」:
scala> w2v.buildArray2
a:0.001
quixotic:0.795
the:25.6
我不知道爲什麼它沒有時間找到「quixotic」(與「a」和「the」相比,它應該是「遠」),b永遠找到「the」這個詞。我對數據結構的經驗很少,所以我很感激(1)對這個問題的深入瞭解,以及(2)關於如何使這個過程更高效的任何建議。
爲此,我已經試過如下:
- 加載整個文件轉換成地圖。這需要很長時間才能首先轉換爲序列,然後轉換爲地圖。
- 將.txt文件轉換爲.json文件,然後使用包(在本例中爲
json4s
)將該.json文件直接打開到地圖中。我遇到了內存錯誤(我已經有14g的內存分配給這個項目)。
在此先感謝您的任何意見/見解!
謝謝@Andreas Neumann和Chris。我可能沒有提出明確的問題。如果我不需要,我不* *想遍歷整個word2vec文件。它*巨大*,平均而言,我的'詞彙'只有大約500個不同的單詞。這就是爲什麼我使用'find'而不必通過整個word2vec文件* IF *我的詞彙表中的所有單詞都存在。 – mcapizzi
您可以對它進行優化,並在找到它們時從詞彙集中移除元素,然後在找到所有詞彙單詞後終止循環。 – Chris
這是一個好主意!我會試一試。謝謝。 – mcapizzi