Scala spark mllib中的Java堆空间

Scala spark mllib中的Java堆空间,scala,apache-spark,apache-spark-mllib,Scala,Apache Spark,Apache Spark Mllib,我有下面运行的代码,它通过交叉验证为随机森林分类计算一些指标 def run(data:RDD[LabeledPoint], metric:String = "PR") = { val cv_data:Array[(RDD[LabeledPoint], RDD[LabeledPoint])] = MLUtils.kFold(data, numFolds, 0) val result : Array[(Double, Double)] = cv_data.par.map{cas

我有下面运行的代码,它通过交叉验证为随机森林分类计算一些指标

def run(data:RDD[LabeledPoint], metric:String = "PR") = {

    val cv_data:Array[(RDD[LabeledPoint], RDD[LabeledPoint])] = MLUtils.kFold(data, numFolds, 0)

    val result : Array[(Double, Double)] = cv_data.par.map{case (training, validation) =>
      training.persist(org.apache.spark.storage.StorageLevel.MEMORY_ONLY)
      validation.persist(org.apache.spark.storage.StorageLevel.MEMORY_ONLY)

      val res :ParArray[(Double, Double)] = CV_params.par.zipWithIndex.map { case (p,i) =>
        // Training classifier
        val model = RandomForest.trainClassifier(training, numClasses, categoricalFeaturesInfo, params(0).asInstanceOf[Int], params(3).asInstanceOf[String], params(4).asInstanceOf[String],
  params(1).asInstanceOf[Int], params(2).asInstanceOf[Int])
        // Prediction
        val labelAndPreds:RDD[(Double, Double)] = model.predictWithLabels(validation)
        // Metrics computation
        val bcm = new BinaryClassificationMetrics(labelAndPreds)
        (bcm.areaUnderROC() / numFolds, bcm.areaUnderPR() / numFolds)
      }

      training.unpersist()
      validation.unpersist()
      res
    }.reduce((s1,s2) => s1.zip(s2).map(t => (t._1._1 + t._2._1, t._1._2 + t._2._2))).toArray

    val cv_roc = result.map(_._1)
    val cv_pr = result.map(_._2)

    // Extract best params
    val which_max = (metric match {
      case "ROC" => cv_roc
      case "PR" => cv_pr
      case _ =>
        logWarning("Metrics set to default one: PR")
        cv_pr
    }).zipWithIndex.maxBy(_._1)._2

    best_values_array = CV_params(which_max)
    CV_areaUnderROC = cv_roc
    CV_areaUnderPR = cv_pr
  }
}

val numTrees = Array(50)
val maxDepth = Array(30)
val maxBins = Array(100)
val featureSubsetStrategy = Array("sqrt")
val impurity = Array("gini")

val CV_params: Array[Array[Any]] = {
    for (a <- numTrees; b <- maxDepth; c <- maxBins; d <- featureSubsetStrategy;
         e <- impurityString) yield Array(a, b, c, d, e)
}

run(data, "PR")
我不知道错误来自何处,因为分配的总内存(26GB)远高于作业期间消耗的内存(我在spark web UI上检查过)


任何帮助都将不胜感激。谢谢大家!

只是一个猜测,但您正在做的一件不同寻常的事情是在调用
.par
的同时提交许多作业。请注意,spark通常以不同的方式实现并行性——您提交一个作业,但该作业被分解为多个可以并行运行的任务

原则上,你所做的事情没有错,如果一个作业内的并行化很小,这可能是有用的;在这种情况下,如果您一次提交一个作业,您将无法有效地利用集群。OTOH,仅使用
.par
可能会导致并行提交太多作业。这种方便的方法将不断提交作业,试图让驱动程序保持忙碌(无论如何,一级近似);但事实上,在spark中,在等待集群完成繁重工作时,驾驶员相对空闲并不罕见。因此,虽然驱动程序可能有大量可用的cpu,但它可能会占用大量内存,因为它同时执行准备1000个作业所需的簿记(不确定生成了多少个作业)


如果您确实希望并行提交作业,那么将其限制为一个小数目可能会有所帮助,例如一次只能提交2或4个作业。

只是猜测,但您正在做的一件不同寻常的事情是在调用
.par
的同时并行提交许多作业。请注意,spark通常以不同的方式实现并行性——您提交一个作业,但该作业被分解为多个可以并行运行的任务

原则上,你所做的事情没有错,如果一个作业内的并行化很小,这可能是有用的;在这种情况下,如果您一次提交一个作业,您将无法有效地利用集群。OTOH,仅使用
.par
可能会导致并行提交太多作业。这种方便的方法将不断提交作业,试图让驱动程序保持忙碌(无论如何,一级近似);但事实上,在spark中,在等待集群完成繁重工作时,驾驶员相对空闲并不罕见。因此,虽然驱动程序可能有大量可用的cpu,但它可能会占用大量内存,因为它同时执行准备1000个作业所需的簿记(不确定生成了多少个作业)


如果您确实希望同时提交作业,可以将其限制为少量,例如一次仅提交2或4个作业。

尝试取消正在培训的模型的持久性,您不需要它,否则它将保留在内存中。一旦通过交叉验证获得最佳超参数,您可以使用适合的最佳参数进行尝试。如何取消模型(即非RDD对象)的持久化?我的错,实际上您无法从RF分类器中取消模型的持久化,但仅针对MatrixFactoryModel…您是否尝试过使用内存和磁盘作为存储级别?否。我会尝试。但我不认为内存不足的问题来自RDD,因为在我的例子中,RDD的总重量低于1GB。请尝试取消您正在训练的模型的持久性,您不需要它,否则它将保留在内存中。一旦通过交叉验证获得最佳超参数,您可以使用适合的最佳参数进行尝试。如何取消模型(即非RDD对象)的持久化?我的错,实际上您无法从RF分类器中取消模型的持久化,但仅针对MatrixFactoryModel…您是否尝试过使用内存和磁盘作为存储级别?否。我会尝试。但我不认为内存不足问题来自RDD,因为在我的例子中,RDD的总重量低于1GB。
Exception in thread "dag-scheduler-event-loop" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2271)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
at java.io.ObjectOutputStream$BlockDataOutputStream.write(ObjectOutputStream.java:1841)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1533)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)