Добавление разреженных векторов 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)) 

Я понял, что делать это сложнее, чем кажется. Я рассмотрел одно из возможных решений преобразования векторов в ветер, добавления их в ветер и последующего преобразования обратно в вектор. например Добавление двух RDD[mllib.linalg.Vector]. Поэтому я попытался реализовать это.

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)

Не удается разрешить перегруженный метод "плотный". Мне интересно, почему возникает ошибка и как ее исправить?


person Sajeed    schedule 07.08.2020    source источник


Ответы (1)


Чтобы ответить на мой собственный вопрос, мне пришлось подумать о том, насколько редки векторы. Например, Разреженные векторы требуют 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(_ + _)

Это дает вам еще один массив из них обоих. Далее, чтобы создать новый разреженный вектор, вам нужно создать массив индексов, как показано в конструкции

 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)

Не забудьте отфильтровать нулевые значения из массива, в который добавлены два вектора.

val final_add = add.filter(element => element > 0.0)

Наконец, мы можем создать новый разреженный вектор.

Vectors.sparse(num_int,new_indices,final_add)
person Sajeed    schedule 08.08.2020