将特征的 Spark 向量转换为数组

Luc*_*ess 2 arrays scala vector apache-spark apache-spark-sql

我有一个 features 列,它使用 Spark 的 VectorAssembler 打包成一个向量向量,如下所示。data是输入数据帧(类型spark.sql.DataFrame)。

val featureCols = Array("feature_1","feature_2","feature_3")
val featureAssembler = new VectorAssembler().setInputCols(featureCols).setOutputCol("features")
val dataWithFeatures = featureAssembler.transform(data)
Run Code Online (Sandbox Code Playgroud)

我现在用的是开发一个自定义分类ClassifierClassificationModel开发者API。ClassificationModel需要开发一个predictRaw()函数,该函数输出模型的预测标签向量。

def predictRaw(features: FeaturesType) : Vector
Run Code Online (Sandbox Code Playgroud)

这个函数是由 API 设置的,它接受一个参数、特征FeaturesType并输出一个 Vector(在我的例子中,我把它当作一个 SparkDenseVector作为DenseVector扩展Vectortrait)。

由于 VectorAssembler 的封装,features列是类型的Vector,每个元素本身就是一个向量,每个训练样本的原始特征。例如:

特征列 - Vector
[1.0, 2.0, 3.0] 类型 - element1,本身是一个向量
[3.5, 4.5, 5.5] - element2,本身是一个向量

我需要将这些功能提取到一个Array[Double]中以实现我的predictRaw()逻辑。理想情况下,我想要以下结果以保留基数:

`val result: Array[Double] = Array(1.0, 3.5, 2.0, 4.5, 3.0, 4.5)` 
Run Code Online (Sandbox Code Playgroud)

即以列为主的顺序,因为我会将其转换为矩阵。

我试过了:

val array = features.toArray // this gives an array of vectors and doesn't work
Run Code Online (Sandbox Code Playgroud)

我还尝试将功能作为 DataFrame 对象而不是 Vector 输入,但由于 VectorAssembler 的功能打包,API 需要一个 Vector。例如,这个函数本身就可以工作,但不符合 API,因为它期望 FeaturesType 是 Vector 而不是 DataFrame:

def predictRaw(features: DataFrame) :DenseVector = {
  val featuresArray: Array[Double] = features.rdd.map(r => r.getAs[Vector](0).toArray).collect 
//rest of logic would go here
}
Run Code Online (Sandbox Code Playgroud)

我的问题是那features是类型Vector,不是DataFrame。另一种选择可能是打包features为 aDataFrame但我不知道如何在不使用VectorAssembler.

感谢所有建议,谢谢!我已经查看了 Spark DataFrame(逻辑回归概率向量)中向量的 Access 元素,但这是在 python 中,我使用的是 Scala。

小智 8

如果您只想将 DenseVector 转换为 Array[Double],那么使用 UDF 非常简单:

import org.apache.spark.ml.linalg.DenseVector
val toArr: Any => Array[Double] = _.asInstanceOf[DenseVector].toArray
val toArrUdf = udf(toArr)
val dataWithFeaturesArr = dataWithFeatures.withColumn("features_arr",toArrUdf('features))
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个新列:

|-- features_arr: array (nullable = true)
|    |-- element: double (containsNull = false)
Run Code Online (Sandbox Code Playgroud)