Scala 添加两个RDD[mllib.linalg.Vector]';s

Scala 添加两个RDD[mllib.linalg.Vector]';s,scala,apache-spark,apache-spark-mllib,Scala,Apache Spark,Apache Spark Mllib,我需要添加存储在两个文件中的两个矩阵 latest1.txt和latest2.txt的内容具有下一个str: 1 2 3 4 5 6 7 8 9 我想加上r1,r2。那么,有没有办法在ApacheSpark中添加这两个RDD[mllib.linalg.Vector]s。这实际上是一个好问题。我经常使用mllib,没有意识到这些基本的线性代数运算不容易访问 关键是,基本的breeze向量具有您期望的所有线性代数操作-当然包括您特别提到的基本元素加法 但是,breeze的实现是通过以下方式对外部世界

我需要添加存储在两个文件中的两个矩阵

latest1.txt
latest2.txt
的内容具有下一个str:

1 2 3 4 5 6 7 8 9
我想加上r1,r2。那么,有没有办法在ApacheSpark中添加这两个
RDD[mllib.linalg.Vector]
s。这实际上是一个好问题。我经常使用mllib,没有意识到这些基本的线性代数运算不容易访问

关键是,基本的breeze向量具有您期望的所有线性代数操作-当然包括您特别提到的基本元素加法

但是,breeze的实现是通过以下方式对外部世界隐藏的:

[private mllib]
那么,从外部世界/公共API的角度来看,我们如何访问这些原语呢

其中一些已经暴露:例如平方和:

/**
 * Returns the squared distance between two Vectors.
 * @param v1 first Vector.
 * @param v2 second Vector.
 * @return squared distance between two Vectors.
 */
def sqdist(v1: Vector, v2: Vector): Double = { 
  ...
}
然而,这些可用方法的选择是有限的——事实上,不包括基本操作,包括按元素的加法、减法、乘法等

下面是我能看到的最好的:

  • 将矢量转换为微风:
  • 在breeze中执行向量操作
  • 从breeze转换回mllib向量
以下是一些示例代码:

val v1 = Vectors.dense(1.0, 2.0, 3.0)
val v2 = Vectors.dense(4.0, 5.0, 6.0)
val bv1 = new DenseVector(v1.toArray)
val bv2 = new DenseVector(v2.toArray)

val vectout = Vectors.dense((bv1 + bv2).toArray)
vectout: org.apache.spark.mllib.linalg.Vector = [5.0,7.0,9.0]

下面的代码公开了Spark的asBreeze和fromBreeze方法。与使用
vector.toArray
相比,此解决方案支持
SparseVector
。请注意,Spark将来可能会更改其API,并已将
toBreeze
重命名为
asBreeze

package org.apache.spark.mllib.linalg
import breeze.linalg.{Vector => BV}
import org.apache.spark.sql.functions.udf

/** expose vector.toBreeze and Vectors.fromBreeze
  */
object VectorUtils {

  def fromBreeze(breezeVector: BV[Double]): Vector = {
    Vectors.fromBreeze( breezeVector )
  }

  def asBreeze(vector: Vector): BV[Double] = {
    // this is vector.asBreeze in Spark 2.0
    vector.toBreeze
  }

  val addVectors = udf {
    (v1: Vector, v2: Vector) => fromBreeze( asBreeze(v1) + asBreeze(v2) )
  }

}

有了这个,你可以做
df.withColumn(“xy”,addVectors($“x”,“$“y”))

将两个RDD压缩在一起,然后映射到生成的RDDyeah上。我喜欢val rdd3=rdd1.Zip(rdd2)scala>val rdd4=rdd3.map{e=>e.\u 1+e.\u 2}。我得到的错误是:错误:类型不匹配;发现:org.apache.spark.mllib.linalg.Vector required:String val r4=r3.map{e=>e.\u 1+e.\u 2}由于在mllib向量上没有+或add操作,因此在util.VectorsLooks上定义了加法操作。like+不是添加两个向量的运算符,因此您得到了尝试转换为String的默认隐式。耶,但我找不到任何执行加法的函数或运算符。是的
MLlib
不是一个完整的线性代数库,如果需要这样的操作,应该使用
Breeze
。但是如果向量是稀疏的呢。我目前正在处理稀疏向量。但是如果使用你的方法来转换向量,它将消耗更多的内存并降低计算速度。pyspark可以轻松完成此操作,这真是奇怪。所以我想改用python。这就是我正在尝试的@displayname我回答了这个问题。@javadba在处理稀疏向量时,您认为性能会受到多大影响?我正在处理长度为
2**20
的Spark向量,在Scala中似乎找不到有效的方法来处理这个问题。第一行不是应该是
import org.apache.Spark.mllib.linalg.\u
而不是包定义吗?如果我使用as is,我会得到一个错误,说“定义的非法开始”。@scottH no,因为函数需要是包的一部分才能访问私有函数。该代码在Spark 1.6.1中运行良好,但Spark 2+已经改变了一切。您是否尝试将代码编译到JAR中,而不是复制粘贴到spark shell?
package org.apache.spark.mllib.linalg
import breeze.linalg.{Vector => BV}
import org.apache.spark.sql.functions.udf

/** expose vector.toBreeze and Vectors.fromBreeze
  */
object VectorUtils {

  def fromBreeze(breezeVector: BV[Double]): Vector = {
    Vectors.fromBreeze( breezeVector )
  }

  def asBreeze(vector: Vector): BV[Double] = {
    // this is vector.asBreeze in Spark 2.0
    vector.toBreeze
  }

  val addVectors = udf {
    (v1: Vector, v2: Vector) => fromBreeze( asBreeze(v1) + asBreeze(v2) )
  }

}