【问题标题】:In Apache-spark, how to add the sparse vector?在 Apache-spark 中,如何添加稀疏向量?
【发布时间】:2015-12-04 01:21:13
【问题描述】:

我正在尝试使用 spark 开发自己的前馈神经网络。但是我在 spark 的稀疏向量中找不到乘法、加法或除法等操作。该文件称它是使用微风矢量实现的。但我可以在微风中找到添加操作,但在火花矢量中找不到。如何解决这个问题?

【问题讨论】:

    标签: scala apache-spark scala-breeze


    【解决方案1】:

    Spark 的 Vector 实现不支持代数运算。不幸的是,Spark API 不再支持通过asBreezefromBreeze 方法将SparkVectors 转换为BreezeVectors,因为相对于spark 包,这些方法已设为包私有。

    但是,您可以编写自己的 Spark 到 Breeze 转换器。下面的代码使用类型类定义了这样一个转换器,它允许您始终获得最具体的类型。

    import breeze.linalg.{Vector => BreezeVector, DenseVector => DenseBreezeVector, SparseVector => SparseBreezeVector}
    import org.apache.spark.mllib.linalg.{Vector => SparkVector, DenseVector => DenseSparkVector, SparseVector => SparseSparkVector}
    
    package object myPackage {
    
      implicit class RichSparkVector[I <: SparkVector](vector: I) {
        def asBreeze[O <: BreezeVector[Double]](implicit converter: Spark2BreezeConverter[I, O]): O = {
          converter.convert(vector)
        }
      }
    
      implicit class RichBreezeVector[I <: BreezeVector[Double]](breezeVector: I) {
        def fromBreeze[O <: SparkVector](implicit converter: Breeze2SparkConverter[I, O]): O = {
          converter.convert(breezeVector)
        }
      }
    }
    
    trait Spark2BreezeConverter[I <: SparkVector, O <: BreezeVector[Double]] {
      def convert(sparkVector: I): O
    }
    
    object Spark2BreezeConverter {
      implicit val denseSpark2DenseBreezeConverter = new Spark2BreezeConverter[DenseSparkVector, DenseBreezeVector[Double]] {
        override def convert(sparkVector: DenseSparkVector): DenseBreezeVector[Double] = {
          new DenseBreezeVector[Double](sparkVector.values)
        }
      }
    
      implicit val sparkSpark2SparseBreezeConverter = new Spark2BreezeConverter[SparseSparkVector, SparseBreezeVector[Double]] {
        override def convert(sparkVector: SparseSparkVector): SparseBreezeVector[Double] = {
          new SparseBreezeVector[Double](sparkVector.indices, sparkVector.values, sparkVector.size)
        }
      }
    
      implicit val defaultSpark2BreezeConverter = new Spark2BreezeConverter[SparkVector, BreezeVector[Double]] {
        override def convert(sparkVector: SparkVector): BreezeVector[Double] = {
          sparkVector match {
            case dv: DenseSparkVector => denseSpark2DenseBreezeConverter.convert(dv)
            case sv: SparseSparkVector => sparkSpark2SparseBreezeConverter.convert(sv)
          }
        }
      }
    }
    
    trait Breeze2SparkConverter[I <: BreezeVector[Double], O <: SparkVector] {
      def convert(breezeVector: I): O
    }
    
    object Breeze2SparkConverter {
      implicit val denseBreeze2DenseSparkVector = new Breeze2SparkConverter[DenseBreezeVector[Double], DenseSparkVector] {
        override def convert(breezeVector: DenseBreezeVector[Double]): DenseSparkVector = {
          new DenseSparkVector(breezeVector.data)
        }
      }
    
      implicit val sparseBreeze2SparseSparkVector = new Breeze2SparkConverter[SparseBreezeVector[Double], SparseSparkVector] {
        override def convert(breezeVector: SparseBreezeVector[Double]): SparseSparkVector = {
          val size = breezeVector.activeSize
          val indices = breezeVector.array.index.take(size)
          val data = breezeVector.data.take(size)
          new SparseSparkVector(size, indices, data)
        }
      }
    
      implicit val defaultBreeze2SparkVector = new Breeze2SparkConverter[BreezeVector[Double], SparkVector] {
        override def convert(breezeVector: BreezeVector[Double]): SparkVector = {
          breezeVector match {
            case dv: DenseBreezeVector[Double] => denseBreeze2DenseSparkVector.convert(dv)
            case sv: SparseBreezeVector[Double] => sparseBreeze2SparseSparkVector.convert(sv)
          }
        }
      }
    }
    

    【讨论】:

    • 但是我发现pyspark支持这个操作。我正在考虑改用python。我觉得这个设置很奇怪。当我们想定制自己的 ML lib 时,我们无法利用 spark 的优势。
    • 很遗憾,Spark 不提供基本转换,因为它使它们的 Sparse/DenseVectors 无用。
    • 您的提案中存在错误。在sparseBreeze2SparseSparkVector 中,您将size = breezeVector.activeSize 传递给Spark SparseVector 构造函数。对于长度为 100 但有 10 个元素的稀疏矩阵,这是 10;但是你想传递 100。相反,构造函数应该是new SparseSparkVector(breezeVector.length, indices, data)。此外,您的函数之一被命名为 sparkSpark2SparseBreezeConverter 而不是 sparseSpark2SparseBreezeConverter
    • 话虽如此,通过这些错误修复,本文中的稀疏转换器刚刚通过 QA 并投入生产,因此感谢您的出色回答。
    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2023-03-22
    • 2016-03-07
    • 2016-06-02
    • 1970-01-01
    • 2018-07-11
    相关资源
    最近更新 更多