如何查找多个向量均为零的索引

whs*_*s2k 4 python numpy sparse-matrix apache-spark pyspark

初学者 pySpark 问题在这里:

如何找到所有向量都为零的索引?

经过一系列转换后,我有一个大约 2.5M 行的 Spark df 和一个长度大约为 262K 的 tfidf 稀疏向量。我想执行 PCA 降维,以使这些数据对于多层感知器模型拟合来说更易于管理,但 pyspark 的 PCA 仅限于最多 65,535 列。

+--------------------+
|      tfidf_features| df.count() >>> 2.5M 
+--------------------+ Example Vector:
|(262144,[1,37,75,...| SparseVector(262144, {7858: 1.7047, 12326: 1.2993, 15207: 0.0953, 
|(262144,[0],[0.12...|      24112: 0.452, 40184: 1.7047,...255115: 1.2993, 255507: 1.2993})
|(262144,[0],[0.12...|
|(262144,[0],[0.12...|
|(262144,[0,6,22,3...|
+--------------------+
Run Code Online (Sandbox Code Playgroud)

因此,我想删除稀疏 tfidf 向量的索引或列,这些索引或列对于所有约 2.5M 文档(行)均为零。这有望使我的 PCA 最大值低于 65,535。

我的计划是创建一个 udf,(1)将稀疏向量转换为密集向量(或 np 数组)(2)搜索所有向量以查找所有向量均为零的索引(3)删除索引。然而,我正在努力解决第二部分(找到所有向量为零的索引)。这是我到目前为止的情况,但我认为我的攻击计划太耗时而且不太Pythonic(特别是对于这么大的数据集):

import numpy as np    
row_count = df.count()
def find_zero_indicies(df):
     vectors = df.select('tfidf_features').take(row_count)[0]
     zero_indices = []
     to_delete = []
     for vec in vectors:
          vec = vec.toArray()
          for value in vec:
               if value.nonzero():
                    zero_indices.append(vec.index(value))
     for value in zero_indices:
          if zero_inices.count(value) == row_count:
               to_delete.append(value)
return to_delete
Run Code Online (Sandbox Code Playgroud)

任何建议或帮助表示赞赏!

zer*_*323 5

如果有的话,找到应该保留的索引更有意义:

from pyspark.ml.linalg import DenseVector, SparseVector
from pyspark.sql.functions import explode, udf
from operator import itemgetter

@udf("array<integer>")
def indices(v):
    if isinstance(v, DenseVector):
        return [i for i in range(len(v))]
    if isinstance(v, SparseVector):
        return v.indices.tolist()
    return []

indices_list = (df
    .select(explode(indices("tfidf_features")))
    .distinct()
    .rdd.map(itemgetter(0))
    .collect())
Run Code Online (Sandbox Code Playgroud)

并使用VectorSlicer

from pyspark.ml.feature import VectorSlicer

slicer = VectorSlicer(
    inputCol="tfidf_features",
    outputCol="tfidf_features_subset", indices=indices_list)

slicer.transform(df)
Run Code Online (Sandbox Code Playgroud)

然而在实践中,我建议使用固定大小的向量,或者使用HashingTF

HashingTF(inputCol="words", outputCol="tfidf_features", numFeatures=65535)
Run Code Online (Sandbox Code Playgroud)

或者CountVectorizer

CountVectorizer(inputCol="words", outputCol="vectorizer_features", 
    vocabSize=65535)
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都可以将其与StopWordsRemover.