添加稀疏向量 3.0.0 Apache Spark Scala
Adding Sparse Vectors 3.0.0 Apache Spark Scala
我正在尝试创建一个如下添加的函数
two org.apache.spark.ml.linalg.Vector
。或者即两个稀疏向量
此向量可能如下所示
(28,[1,2,3,4,7,11,12,13,14,15,17,20,22,23,24,25],[0.13028398104008743,0.23648605632753023,0.7094581689825907,0.13028398104008743,0.23648605632753023,0.0,0.14218861229025295,0.3580566057240087,0.14218861229025295,0.13028398104008743,0.26056796208017485,0.0,0.14218861229025295,0.06514199052004371,0.13028398104008743,0.23648605632753023])
例如
def add_vectors(x: org.apache.spark.ml.linalg.Vector,y:org.apache.spark.ml.linalg.Vector): org.apache.spark.ml.linalg.Vector = {
}
我们来看一个用例
val x = Vectors.sparse(2, List(0), List(1)) // [1, 0]
val y = Vectors.sparse(2, List(1), List(1)) // [0, 1]
I want to output to be
Vectors.sparse(2, List(0,1), List(1,1))
这是他们共享相同索引的另一种情况
val x = Vectors.sparse(2, List(1), List(1))
val y = Vectors.sparse(2, List(1), List(1))
这个输出应该是
Vectors.sparse(2, List(1), List(2))
我意识到这样做比看起来要难。我研究了一种可能的解决方案,将向量转换为 breeze,将它们添加到 breeze,然后将其转换回向量。例如 。所以我尝试实现这个。
def add_vectors(x: org.apache.spark.ml.linalg.Vector,y:org.apache.spark.ml.linalg.Vector) ={
val dense_x = x.toDense
val dense_y = y.toDense
val bv1 = new DenseVector(dense_x.toArray)
val bv2 = new DenseVector(dense_y.toArray)
val vectout = Vectors.dense((bv1 + bv2).toArray)
vectout
}
然而这让我在最后一行出错
val vectout = Vectors.dense((bv1 + bv2).toArray)
无法解析重载方法 'dense'。
我想知道为什么会出现错误以及解决方法?
为了回答我自己的问题,我不得不考虑向量的稀疏程度。例如稀疏向量需要 3 个参数。维数,一个索引数组,最后是一个值数组。例如
val indices: Array[Int] = Array(1,2)
val norms: Array[Double] = Array(0.5,0.3)
val num_int = 4
val vector: Vector = Vectors.sparse(num_int, indices, norms)
如果我将此 SparseVector 转换为数组,我将得到以下结果。
代码:
val choiced_array = vector.toArray
choiced_array.map(element => print(element + " "))
输出:
[0.0, 0.5,0.3,0.0].
这被认为是它的更密集表示。因此,一旦将两个向量转换为数组,就可以使用以下代码添加它们
val add: Array[Double] = (vector.toArray, vector_2.toArray).zipped.map(_ + _)
这为您提供了另一个同时添加的数组。接下来要创建新的稀疏向量,您需要创建一个 indices 数组,如构造
中所示
var i = -1;
val new_indices_pre = add.map( (element:Double) => {
i = i + 1
if(element > 0.0)
i
else{
-1
}
})
然后让我们过滤掉所有指示该索引为零的 -1 索引指示。
new_indices_pre.filter(element => element != -1)
记得从添加了两个向量的数组中过滤掉 none 个零值。
val final_add = add.filter(element => element > 0.0)
最后,我们可以制作新的稀疏向量
Vectors.sparse(num_int,new_indices,final_add)
我正在尝试创建一个如下添加的函数
two org.apache.spark.ml.linalg.Vector
。或者即两个稀疏向量
此向量可能如下所示
(28,[1,2,3,4,7,11,12,13,14,15,17,20,22,23,24,25],[0.13028398104008743,0.23648605632753023,0.7094581689825907,0.13028398104008743,0.23648605632753023,0.0,0.14218861229025295,0.3580566057240087,0.14218861229025295,0.13028398104008743,0.26056796208017485,0.0,0.14218861229025295,0.06514199052004371,0.13028398104008743,0.23648605632753023])
例如
def add_vectors(x: org.apache.spark.ml.linalg.Vector,y:org.apache.spark.ml.linalg.Vector): org.apache.spark.ml.linalg.Vector = {
}
我们来看一个用例
val x = Vectors.sparse(2, List(0), List(1)) // [1, 0]
val y = Vectors.sparse(2, List(1), List(1)) // [0, 1]
I want to output to be
Vectors.sparse(2, List(0,1), List(1,1))
这是他们共享相同索引的另一种情况
val x = Vectors.sparse(2, List(1), List(1))
val y = Vectors.sparse(2, List(1), List(1))
这个输出应该是
Vectors.sparse(2, List(1), List(2))
我意识到这样做比看起来要难。我研究了一种可能的解决方案,将向量转换为 breeze,将它们添加到 breeze,然后将其转换回向量。例如
def add_vectors(x: org.apache.spark.ml.linalg.Vector,y:org.apache.spark.ml.linalg.Vector) ={
val dense_x = x.toDense
val dense_y = y.toDense
val bv1 = new DenseVector(dense_x.toArray)
val bv2 = new DenseVector(dense_y.toArray)
val vectout = Vectors.dense((bv1 + bv2).toArray)
vectout
}
然而这让我在最后一行出错
val vectout = Vectors.dense((bv1 + bv2).toArray)
无法解析重载方法 'dense'。 我想知道为什么会出现错误以及解决方法?
为了回答我自己的问题,我不得不考虑向量的稀疏程度。例如稀疏向量需要 3 个参数。维数,一个索引数组,最后是一个值数组。例如
val indices: Array[Int] = Array(1,2)
val norms: Array[Double] = Array(0.5,0.3)
val num_int = 4
val vector: Vector = Vectors.sparse(num_int, indices, norms)
如果我将此 SparseVector 转换为数组,我将得到以下结果。
代码:
val choiced_array = vector.toArray
choiced_array.map(element => print(element + " "))
输出:
[0.0, 0.5,0.3,0.0].
这被认为是它的更密集表示。因此,一旦将两个向量转换为数组,就可以使用以下代码添加它们
val add: Array[Double] = (vector.toArray, vector_2.toArray).zipped.map(_ + _)
这为您提供了另一个同时添加的数组。接下来要创建新的稀疏向量,您需要创建一个 indices 数组,如构造
中所示 var i = -1;
val new_indices_pre = add.map( (element:Double) => {
i = i + 1
if(element > 0.0)
i
else{
-1
}
})
然后让我们过滤掉所有指示该索引为零的 -1 索引指示。
new_indices_pre.filter(element => element != -1)
记得从添加了两个向量的数组中过滤掉 none 个零值。
val final_add = add.filter(element => element > 0.0)
最后,我们可以制作新的稀疏向量
Vectors.sparse(num_int,new_indices,final_add)