使用text8文件的Spark Word2Vec示例

时间:2015-07-17 11:45:45

标签: apache-spark

我试图从apache.spark.org运行此示例(代码在下面,整个教程在这里:https://spark.apache.org/docs/latest/mllib-feature-extraction.html)使用他们在其网站上引用的text8文件({{3 }}):

import org.apache.spark._
import org.apache.spark.rdd._
import org.apache.spark.SparkContext._
import org.apache.spark.mllib.feature.{Word2Vec, Word2VecModel}

val input = sc.textFile("/Users/rkita/Documents/Learning/random/spark/MLlib/examples/text8",4).map(line => line.split(" ").toSeq)

val word2vec = new Word2Vec()

val model = word2vec.fit(input)

val synonyms = model.findSynonyms("china", 40)

for((synonym, cosineSimilarity) <- synonyms) {
  println(s"$synonym $cosineSimilarity")
}

// Save and load model
model.save(sc, "myModelPath")
val sameModel = Word2VecModel.load(sc, "myModelPath")

我正在使用我的mac上的Spark(2核,8GB RAM),我想我已经在spark-env.sh文件中正确设置了内存分配,其中包含以下内容:

export SPARK_EXECUTOR_MEMORY=4g
export SPARK_WORKER_MEMORY=4g

当我尝试适应模型时,我不断收到java堆错误。我在python中也得到了相同的结果。我也使用JAVA_OPTS增加了java内存大小。

该文件只有100MB,所以我认为我的内存设置不正确,但我不确定这是否是根本原因。

有没有其他人在笔记本电脑上试过这个例子?

我无法将该文件放在我们公司的服务器上,因为我们不应该导入外部数据,所以我减少了在个人笔记本电脑上的工作。如果您有任何建议,我很高兴听到他们的意见。 THX!

2 个答案:

答案 0 :(得分:1)

首先,我是Spark的新手,因此其他人可能会有更快或更好的解决方案。 我遇到了运行此示例代码的相同困难。 我设法使其成功,主要是通过:

  1. 在我的机器上运行我自己的Spark群集:使用Spark安装的/ sbin /目录中的启动脚本。为此,您必须根据需要配置conf / spark-env.sh文件。请勿使用127.0.0.1 IP for Spark。
  2. 将Scala代码编译并打包为jar(sbt包),然后将其提供给集群(请参阅scala代码中的addJar(...))。似乎可以使用classpath / extra classpath向Spark提供已编译的代码,但我还没有尝试过。
  3. 设置执行程序内存和驱动程序内存(请参阅Scala代码)
  4. spark-env.sh:

    export SPARK_MASTER_IP=192.168.1.53
    export SPARK_MASTER_PORT=7077
    export SPARK_MASTER_WEBUI_PORT=8080
    
    export SPARK_DAEMON_MEMORY=1G
    # Worker : 1 by server
    # Number of worker instances to run on each machine (default: 1). 
    # You can make this more than 1 if you have have very large machines and would like multiple Spark worker processes. 
    # If you do set this, make sure to also set SPARK_WORKER_CORES explicitly to limit the cores per worker, 
    # or else each worker will try to use all the cores.
    export SPARK_WORKER_INSTANCES=2
    # Total number of cores to allow Spark applications to use on the machine (default: all available cores).
    export SPARK_WORKER_CORES=7
    
    #Total amount of memory to allow Spark applications to use on the machine, e.g. 1000m, 2g 
    # (default: total memory minus 1 GB); 
    # note that each application's individual memory is configured using its spark.executor.memory property.
    export SPARK_WORKER_MEMORY=8G
    export SPARK_WORKER_DIR=/tmp
    
    # Executor : 1 by application run on the server
    # export SPARK_EXECUTOR_INSTANCES=4
    # export SPARK_EXECUTOR_MEMORY=4G
    
    export SPARK_SCALA_VERSION="2.10"
    

    运行示例的Scala文件:

    import org.apache.spark.SparkContext
    import org.apache.spark.SparkContext._
    import org.apache.spark.SparkConf
    import org.apache.log4j.Logger
    import org.apache.log4j.Level
    import org.apache.spark.mllib.feature.{Word2Vec, Word2VecModel}
    
    object SparkDemo {
    
      def log[A](key:String)(job : =>A) = {
        val start = System.currentTimeMillis
        val output = job
        println("===> %s in %s seconds"
          .format(key, (System.currentTimeMillis - start) / 1000.0))
        output
      }
    
      def main(args: Array[String]):Unit ={
    
        val modelName ="w2vModel"
    
        val sc = new SparkContext(
          new SparkConf()
          .setAppName("SparkDemo")
          .set("spark.executor.memory", "8G")
          .set("spark.driver.maxResultSize", "16G")
          .setMaster("spark://192.168.1.53:7077") // ip of the spark master.
          // .setMaster("local[2]") // does not work... workers loose contact with the master after 120s
        )
    
        // take a look into target folder if you are unsure how the jar is named
        // onliner to compile / run : sbt package && sbt run
        sc.addJar("./target/scala-2.10/sparkling_2.10-0.1.jar")
    
        val input = sc.textFile("./text8").map(line => line.split(" ").toSeq)
    
        val word2vec = new Word2Vec()
    
        val model = log("compute model") { word2vec.fit(input) }
        log ("save model") { model.save(sc, modelName) }
    
        val synonyms = model.findSynonyms("china", 40)
        for((synonym, cosineSimilarity) <- synonyms) {
          println(s"$synonym $cosineSimilarity")
        }
    
        val model2 = log("reload model") { Word2VecModel.load(sc, modelName) }
      }
    }
    

答案 1 :(得分:0)

sc.textFile仅拆分换行符,text8不包含换行符。

您正在创建1行RDD。 .map(line => line.split(" ").toSeq)创建另一个RDD[Seq[String]]类型的1行RDD。

Word2Vec最适用于每行RDD一个句子(这也应该避免Java堆错误)。不幸的是,text8已经被剥离了一段时间,所以你不能只拆分它们,但你可以找到原始版本here以及用于处理它的perl脚本,编辑脚本并不困难。不删除期间。