初学者pySpark问题:
如何找到所有向量为零的索引?
经过一系列的变换后,我得到了一个带有~2.5M行的火花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...|
+--------------------+
因此,我想删除所有~2.5M文档(行)为零的稀疏tfidf向量的指标或列。这有望让我低于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
任何建议或帮助表示赞赏!
答案 0 :(得分:2)
如果有的话,找到应该保留的索引更有意义:
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())
并使用VectorSlicer
:
from pyspark.ml.feature import VectorSlicer
slicer = VectorSlicer(
inputCol="tfidf_features",
outputCol="tfidf_features_subset", indices=indices_list)
slicer.transform(df)
然而,在实践中,我建议使用固定大小的矢量,使用HashingTF
:
HashingTF(inputCol="words", outputCol="tfidf_features", numFeatures=65535)
或CountVectorizer
:
CountVectorizer(inputCol="words", outputCol="vectorizer_features",
vocabSize=65535)
在这两种情况下,您都可以将其与StopWordsRemover
结合使用。