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) )
}
}