【问题标题】:Writing output of the Principal Components Analysis to text file将主成分分析的输出写入文本文件
【发布时间】:2016-04-25 18:23:50
【问题描述】:

我已经对之前使用 sc.textFile 加载的矩阵执行了主成分分析。输出是 org.apache.spark.mllib.linalg.Matrix 然后我将其转换为 RDD[Vector[Double]]。

与:

import java.io.PrintWriter

我做到了:

    val pw = new PrintWriter("Matrix.csv")
    rows3.collect().foreach(line => pw.println(line))
    pw.flush

输出 csv 很有希望。唯一的问题是每一行都是一个 DenseVector(一些值)。如何将每一行拆分成对应的系数?

非常感谢

【问题讨论】:

标签: scala apache-spark apache-spark-mllib


【解决方案1】:

您可以使用computePrincipalComponentsbreeze.linalg.csvwrite 的结果:

import java.io.File
import breeze.linalg.{DenseMatrix => BDM, csvwrite}

val mat: RowMatrix = ...
val pca = mat.computePrincipalComponents(...)

csvwrite(
    new File("Matrix.csv"),
    new BDM[Double](mat.numRows, mat.numCols, mat.toArray))

【讨论】:

  • 除了当我检查输出文件时,并不是所有的值都显示出来;和控制台输出基本一样,比如第一行:“value1 value2 ... (523 total)”
【解决方案2】:

将每个向量转换为字符串(您可以在驱动程序或执行程序上执行此操作)

val pw = new PrintWriter("Matrix.csv")
rows3.map(_.mkString(",")).collect().foreach(line => pw.println(line))
pw.flush

编辑: 如果您的数据太大而无法放入驱动程序的内存中,您可以尝试类似的方法:

val rdd = rows3.map(_.mkString(",")).zipWithIndex.cache
val total = rdd.count
val step = 10000 //rows in each chunk
val range = 0 to total by step
val limits = ranges.zip(range.drop(1))
limits.foreach { case(start, end) => 
                  rdd.filter(x => x._2 >= start && x._2 < end)
                     .map(_._1)
                     .collect
                     .foreach(pw.println(_))
}

我无法尝试,但这是一般的想法

【讨论】:

  • 这不是应该的做法。您应该忘记您正在尝试使用分布式系统的边界进行编写。如果这不会导致 JVM 开销,您应该会遇到一些并发问题!
  • 我知道它会起作用,但 Spark 作为分布式系统的全部目的是它的可扩展性。另外,考虑到对作为输出的可变数据的非原子转换,您可能会遇到一些并发问题。
  • 不存在并发问题。 collect() 返回一个本地数组,在此之前不会发生任何可变的事情。如果您知道输出数据很小(但中间数据很大),那么这是使用 Spark 的一种非常合理的方式。
  • 嗯,computePrincipalComponents 返回org.apache.spark.mllib.linalg.Matrix,它已经是一个本地数据结构。首先真的没有理由将其转换为 RDD。
猜你喜欢
  • 2017-10-02
  • 1970-01-01
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 2016-07-13
相关资源
最近更新 更多