Векторы / матрицы MLlib to Breeze являются частными для области org.apache.spark.mllib?

Я где-то читал, что локальные векторы / матрицы MLlib в настоящее время обертывают реализацию Breeze, но методы, конвертирующие MLlib в векторы / матрицы Breeze, являются частными для области org.apache.spark.mllib. Для решения этой проблемы рекомендуется написать код в пакете org.apache.spark.mllib.something.

Есть лучший способ сделать это? Можете ли вы привести некоторые соответствующие примеры?

Спасибо и всего наилучшего,

5 ответов

Я сделал то же решение, что и @dlwh. Вот код, который делает это:

package org.apache.spark.mllib.linalg

object VectorPub {

  implicit class VectorPublications(val vector : Vector) extends AnyVal {
    def toBreeze : breeze.linalg.Vector[scala.Double] = vector.toBreeze

  }

  implicit class BreezeVectorPublications(val breezeVector : breeze.linalg.Vector[Double]) extends AnyVal {
    def fromBreeze : Vector = Vectors.fromBreeze(breezeVector)
  }
}

обратите внимание, что неявный класс расширяет AnyVal, чтобы предотвратить выделение нового объекта при вызове этих методов

Мое решение является своего рода гибридом тех из @barclar и @lev, выше. Вам не нужно помещать свой код в org.apache.spark.mllib.linalg если вы не используете неявные преобразования spark-ml. Вы можете определить свои собственные неявные преобразования в вашем собственном пакете, например:

package your.package

import org.apache.spark.ml.linalg.DenseVector
import org.apache.spark.ml.linalg.SparseVector
import org.apache.spark.ml.linalg.Vector
import breeze.linalg.{DenseVector => BDV, SparseVector => BSV, Vector => BV}

object BreezeConverters
{
    implicit def toBreeze( dv: DenseVector ): BDV[Double] =
        new BDV[Double](dv.values)

    implicit def toBreeze( sv: SparseVector ): BSV[Double] =
        new BSV[Double](sv.indices, sv.values, sv.size)

    implicit def toBreeze( v: Vector ): BV[Double] =
        v match {
            case dv: DenseVector => toBreeze(dv)
            case sv: SparseVector => toBreeze(sv)
        }

    implicit def fromBreeze( dv: BDV[Double] ): DenseVector =
        new DenseVector(dv.toArray)

    implicit def fromBreeze( sv: BSV[Double] ): SparseVector =
        new SparseVector(sv.length, sv.index, sv.data)

    implicit def fromBreeze( bv: BV[Double] ): Vector =
        bv match {
            case dv: BDV[Double] => fromBreeze(dv)
            case sv: BSV[Double] => fromBreeze(sv)
        }
}

Затем вы можете импортировать эти последствия в ваш код с помощью:

import your.package.BreezeConverters._

Насколько я понимаю, люди Spark не хотят предоставлять сторонние API (включая Breeze), чтобы их было легче изменить, если они решат отойти от них.

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

Вот лучшее, что у меня есть. Примечание для @dlwh: пожалуйста, предоставьте любые улучшения, которые могут вам понадобиться.

Решение, которое я мог бы предложить - не помещать код в пакет mlib .linalg, - это преобразовать каждый вектор в новый Breeze DenseVector.

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 и избежать преобразования разреженных в плотные векторы:

def toBreeze(vector: Vector) : breeze.linalg.Vector[scala.Double] = vector match {
      case sv: SparseVector => new breeze.linalg.SparseVector[Double](sv.indices, sv.values, sv.size)
      case dv: DenseVector => new breeze.linalg.DenseVector[Double](dv.values)
    }

Это метод, который я бы использовал для преобразования Mlib DenceMatrix в простую матрицу, может быть, это поможет!!

import breeze.linalg._
import org.apache.spark.mllib.linalg.Matrix

def toBreez(X:org.apache.spark.mllib.linalg.Matrix):breeze.linalg.DenseMatrix[Double] = {
var i=0;
var j=0;
val m = breeze.linalg.DenseMatrix.zeros[Double](X.numRows,X.numCols)
for(i <- 0 to X.numRows-1){
  for(j <- 0 to X.numCols-1){
    m(i,j)=X.apply(i, j)
  }
}
m
}
Другие вопросы по тегам