密集向量列到稀疏向量列

时间:2020-02-06 20:57:54

标签: apache-spark pyspark

我有一个特殊的情况,我需要从DenseVector转到稀疏向量列。

我正在尝试实施在这里找到的SMOTE技术:https://github.com/Angkirat/Smote-for-Spark/blob/master/PythonCode.py 但是在第44行,由于错误,我不得不将其从min_Array[neigh][0] - min_Array[i][0]更改为DenseVector(min_Array[neigh][0]) - DenseVector(min_Array[i][0])

一旦有了DenseVector列,就需要将其转换回SparseVector列以合并我的数据。

我尝试了以下方法:

df = sc.parallelize([
  (1, DenseVector([0.0, 1.0, 1.0, 2.0, 1.0, 3.0, 0.0, 0.0, 0.0, 0.0])),
  (2, DenseVector([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0])),
  (3, DenseVector([0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])),
]).toDF(["row_num", "features"])
list_to_vector_udf = udf(lambda l: Vectors.sparse(l), VectorUDT())
df = df.withColumn('features', list_to_vector_udf(df["features"]))

“ int()参数必须是字符串,类似字节的对象或数字,而不是'DenseVector'

assembler = VectorAssembler(inputCols=['features'],outputCol='features')
df = assembler.transform(df)

“不支持列特征的数据类型struct ,values:array >。”

1 个答案:

答案 0 :(得分:0)

将密集向量转换为稀疏向量通常没有太大意义,因为密集向量已经占用了内存。如果确实需要执行此操作,请查看稀疏矢量API,它可以接受对列表(索引,值),或者需要将非零索引和值直接传递给构造函数。类似于以下内容:

from pyspark.ml.linalg import Vectors, VectorUDT
from pyspark.ml.linalg import DenseVector

df = sc.parallelize([
    (1, DenseVector([0.0, 1.0, 1.0, 2.0, 1.0, 3.0, 0.0, 0.0, 0.0, 0.0])),
    (2, DenseVector([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0])),
    (3, DenseVector([0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])),
]).toDF(["row_num", "features"])

def to_sparse(dense_vector):
    size = len(dense_vector)
    pairs = [(i, v) for i, v in enumerate(dense_vector.values.tolist()) if v != 0]
    return Vectors.sparse(size, pairs)

dense_to_sparse_udf = udf(to_sparse, VectorUDT())
df = df.withColumn('features', dense_to_sparse_udf(df["features"]))

df.show()
+-------+--------------------+
|row_num|            features|
+-------+--------------------+
|      1|(10,[1,2,3,4,5],[...|
|      2|    (10,[9],[100.0])|
|      3|      (10,[1],[1.0])|
+-------+--------------------+