我使用Sparkit-Learn的SparkCountVectorizer和SparkTfidfVectorizer将一堆文档转换为TFIDF矩阵。
我创建了TFIDF矩阵并且它具有正确的尺寸(496,861个文档由189,398个不同的标记):
>>> tfidf
<class 'splearn.rdd.SparseRDD'> from PythonRDD[20] at RDD at PythonRDD.scala:48
>>> tfidf.shape
(496861, 189398)
切片单个向量会返回正确的输出(1个文档由189,398个不同的标记):
>>> tfidf.flatMap(lambda x: x).take(1)
[<1x189398 sparse matrix of type '<class 'numpy.float64'>'
with 49 stored elements in Compressed Sparse Row format>]
现在我希望获得每个文档的转置(即,尺寸为189,398的向量乘以1):
>>> tfidf.flatMap(lambda x: x.T).take(1)
但这是我得到的:
[<1x7764 sparse matrix of type '<class 'numpy.float64'>'
with 77 stored elements in Compressed Sparse Row format>]
因此,我得到1x7764向量而不是189389x1向量。我理解7764:当我读取数据时我.repartition()
64件,结果是,496861(文件数)除以64是7763.4。我不明白为什么Sparkit-Learn在一个案例(lambda x: x
)中按平面行进行迭代,在另一个案例中用分区进行迭代(lambda x: x.T
)。我完全糊涂了。
如果它很重要,我的最终目标是过滤TFIDF矩阵,以便我只获得某些列中具有非零值的向量(即,只包含某些单词的文档)并且索引未转置的1x189389向量不会工作(在我[0]
之后我放了多少x
我总是找回相同的1x189389向量。
答案 0 :(得分:1)
你转移了一个错误的东西。 splearn.rdd.SparseRDD
存储数据块,因此您可以转置块而不是单个向量。如果块有7764行和18938列,则转置一个有18938行和7764列,这些列将在展平时逐行迭代。
您需要的是:
(tfidf
# Iterate over each block and yield the rows
# block-size x 18938 -> 1 x 18938
.flatMap(lambda x: x)
# Take each row and transpose it
# 1 x 18938 -> 1 x 18938
.map(lambda x: x.T))
或
(tfidf
# Iterate over each row in block (generator expression)
# and transpose it block-size x 18938 -> block-size x 18938 x 1
#
# and then flatten (with flatMap) yielding rows 18938 x 1
.flatMap(lambda xs: (x.T for x in xs)))
注意:我并不熟悉Sparkit-learn所以可以有更优雅的解决方案。