我目前正在尝试在UMBC Webbase Corpus上训练一组Word2Vec矢量(400个文件中大约30GB的文本)。
即使在100 GB以上的机器上,我也经常遇到内存不足的情况。我在应用程序本身运行Spark。我尝试稍微调整一下,但我无法对超过10 GB的文本数据执行此操作。我实现的明显瓶颈是先前计算的RDD的并集,即内存不足异常的来源。
也许您有经验可以提出比这更有效的内存实现:
object SparkJobs {
val conf = new SparkConf()
.setAppName("TestApp")
.setMaster("local[*]")
.set("spark.executor.memory", "100g")
.set("spark.rdd.compress", "true")
val sc = new SparkContext(conf)
def trainBasedOnWebBaseFiles(path: String): Unit = {
val folder: File = new File(path)
val files: ParSeq[File] = folder.listFiles(new TxtFileFilter).toIndexedSeq.par
var i = 0;
val props = new Properties();
props.setProperty("annotators", "tokenize, ssplit");
props.setProperty("nthreads","2")
val pipeline = new StanfordCoreNLP(props);
//preprocess files parallel
val training_data_raw: ParSeq[RDD[Seq[String]]] = files.map(file => {
//preprocess line of file
println(file.getName() +"-" + file.getTotalSpace())
val rdd_lines: Iterator[Option[Seq[String]]] = for (line <- Source.fromFile(file,"utf-8").getLines) yield {
//performs some preprocessing like tokenization, stop word filtering etc.
processWebBaseLine(pipeline, line)
}
val filtered_rdd_lines = rdd_lines.filter(line => line.isDefined).map(line => line.get).toList
println(s"File $i done")
i = i + 1
sc.parallelize(filtered_rdd_lines).persist(StorageLevel.MEMORY_ONLY_SER)
})
val rdd_file = sc.union(training_data_raw.seq)
val starttime = System.currentTimeMillis()
println("Start Training")
val word2vec = new Word2Vec()
word2vec.setVectorSize(100)
val model: Word2VecModel = word2vec.fit(rdd_file)
println("Training time: " + (System.currentTimeMillis() - starttime))
ModelUtil.storeWord2VecModel(model, Config.WORD2VEC_MODEL_PATH)
}}
}
答案 0 :(得分:1)
就像Sarvesh在评论中指出的那样,单个机器的数据可能太多了。使用更多的机器。我们通常认为需要20-30 GB的内存才能使用1 GB的文件。通过这种(非常粗略的)估计,您需要600-800 GB的内存用于30 GB输入。 (您可以通过加载部分数据来获得更准确的估算。)
作为更一般的评论,我建议您避免使用rdd.union
和sc.parallelize
。请使用带有通配符的sc.textFile
将所有文件加载到单个RDD中。
答案 1 :(得分:0)
您是否尝试从较小的语料库中获取word2vec向量?我告诉你这是因为我在一个更小的一个上运行了word2vec spark实现,我遇到了问题,因为存在这个问题:http://mail-archives.apache.org/mod_mbox/spark-issues/201412.mbox/%3CJIRA.12761684.1418621192000.36769.1418759475999@Atlassian.JIRA%3E
因此,对于我的用例,该问题使word2vec spark实现有点无用。因此,我使用spark来按摩我的语料库,但不是为了实际获取向量。
rdd.union
。.toList
可能会从RDD中收集每一行并将其收集到您的驱动程序计算机(用于提交任务的计算机)中,这可能就是您为什么会出现内存不足的原因。你应该完全避免将RDD变成一个列表!